From 1119f653597889cad1f3194cab74f6715cb8bf43 Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Thu, 5 Dec 2024 18:36:17 +0800 Subject: [PATCH 001/143] chore: adding apis for git --- app/client/src/git/{ => constants}/enums.ts | 9 +++++ .../src/git/requests/checkoutBranchRequest.ts | 17 +++++++++ .../requests/checkoutBranchRequest.types.ts | 8 ++++ app/client/src/git/requests/commitRequest.ts | 17 +++++++++ .../src/git/requests/commitRequest.types.ts | 6 +++ app/client/src/git/requests/connectRequest.ts | 14 +++++++ .../src/git/requests/connectRequest.types.ts | 24 ++++++++++++ app/client/src/git/requests/constants.ts | 1 + .../src/git/requests/createBranchRequest.ts | 17 +++++++++ .../git/requests/createBranchRequest.types.ts | 8 ++++ .../src/git/requests/deleteBranchRequest.ts | 14 +++++++ .../git/requests/deleteBranchRequest.types.ts | 8 ++++ app/client/src/git/requests/discardRequest.ts | 9 +++++ .../src/git/requests/disconnectRequest.ts | 10 +++++ .../git/requests/disconnectRequest.types.ts | 3 ++ .../fetchAutocommitProgressRequest.ts | 12 ++++++ .../fetchAutocommitProgressRequest.types.ts | 7 ++++ .../src/git/requests/fetchBranchesRequest.ts | 21 ++++++++++ .../requests/fetchBranchesRequest.types.ts | 11 ++++++ .../git/requests/fetchGitMetadataRequest.ts | 10 +++++ .../requests/fetchGitMetadataRequest.types.ts | 15 ++++++++ .../git/requests/fetchGlobalConfigRequest.ts | 10 +++++ .../fetchGlobalConfigRequest.types.ts | 4 ++ .../git/requests/fetchLocalConfigRequest.ts | 10 +++++ .../requests/fetchLocalConfigRequest.types.ts | 5 +++ .../git/requests/fetchMergeStatusRequest.ts | 17 +++++++++ .../requests/fetchMergeStatusRequest.types.ts | 10 +++++ .../requests/fetchProtectedBranchesRequest.ts | 10 +++++ .../fetchProtectedBranchesRequest.types.ts | 1 + .../src/git/requests/fetchSSHKeyRequest.ts | 9 +++++ .../git/requests/fetchSSHKeyRequest.types.ts | 6 +++ .../src/git/requests/fetchStatusRequest.ts | 14 +++++++ .../git/requests/fetchStatusRequest.types.ts | 38 +++++++++++++++++++ .../src/git/requests/generateSSHKeyRequest.ts | 18 +++++++++ .../requests/generateSSHKeyRequest.types.ts | 11 ++++++ .../src/git/requests/importGitRequest.ts | 14 +++++++ .../git/requests/importGitRequest.types.ts | 24 ++++++++++++ app/client/src/git/requests/mergeRequest.ts | 11 ++++++ .../src/git/requests/mergeRequest.types.ts | 9 +++++ app/client/src/git/requests/pullRequest.ts | 10 +++++ .../src/git/requests/pullRequest.types.ts | 6 +++ .../git/requests/toggleAutocommitRequest.ts | 12 ++++++ .../requests/toggleAutocommitRequest.types.ts | 1 + .../git/requests/triggerAutocommitRequest.ts | 10 +++++ .../triggerAutocommitRequest.types.ts | 7 ++++ .../git/requests/updateGlobalConfigRequest.ts | 13 +++++++ .../updateGlobalConfigRequest.types.ts | 11 ++++++ .../git/requests/updateLocalConfigRequest.ts | 14 +++++++ .../updateLocalConfigRequest.types.ts | 13 +++++++ .../updateProtectedBranchesRequest.ts | 17 +++++++++ .../updateProtectedBranchesRequest.types.ts | 5 +++ app/client/src/git/types.ts | 2 +- 52 files changed, 582 insertions(+), 1 deletion(-) rename app/client/src/git/{ => constants}/enums.ts (69%) create mode 100644 app/client/src/git/requests/checkoutBranchRequest.ts create mode 100644 app/client/src/git/requests/checkoutBranchRequest.types.ts create mode 100644 app/client/src/git/requests/commitRequest.ts create mode 100644 app/client/src/git/requests/commitRequest.types.ts create mode 100644 app/client/src/git/requests/connectRequest.ts create mode 100644 app/client/src/git/requests/connectRequest.types.ts create mode 100644 app/client/src/git/requests/constants.ts create mode 100644 app/client/src/git/requests/createBranchRequest.ts create mode 100644 app/client/src/git/requests/createBranchRequest.types.ts create mode 100644 app/client/src/git/requests/deleteBranchRequest.ts create mode 100644 app/client/src/git/requests/deleteBranchRequest.types.ts create mode 100644 app/client/src/git/requests/discardRequest.ts create mode 100644 app/client/src/git/requests/disconnectRequest.ts create mode 100644 app/client/src/git/requests/disconnectRequest.types.ts create mode 100644 app/client/src/git/requests/fetchAutocommitProgressRequest.ts create mode 100644 app/client/src/git/requests/fetchAutocommitProgressRequest.types.ts create mode 100644 app/client/src/git/requests/fetchBranchesRequest.ts create mode 100644 app/client/src/git/requests/fetchBranchesRequest.types.ts create mode 100644 app/client/src/git/requests/fetchGitMetadataRequest.ts create mode 100644 app/client/src/git/requests/fetchGitMetadataRequest.types.ts create mode 100644 app/client/src/git/requests/fetchGlobalConfigRequest.ts create mode 100644 app/client/src/git/requests/fetchGlobalConfigRequest.types.ts create mode 100644 app/client/src/git/requests/fetchLocalConfigRequest.ts create mode 100644 app/client/src/git/requests/fetchLocalConfigRequest.types.ts create mode 100644 app/client/src/git/requests/fetchMergeStatusRequest.ts create mode 100644 app/client/src/git/requests/fetchMergeStatusRequest.types.ts create mode 100644 app/client/src/git/requests/fetchProtectedBranchesRequest.ts create mode 100644 app/client/src/git/requests/fetchProtectedBranchesRequest.types.ts create mode 100644 app/client/src/git/requests/fetchSSHKeyRequest.ts create mode 100644 app/client/src/git/requests/fetchSSHKeyRequest.types.ts create mode 100644 app/client/src/git/requests/fetchStatusRequest.ts create mode 100644 app/client/src/git/requests/fetchStatusRequest.types.ts create mode 100644 app/client/src/git/requests/generateSSHKeyRequest.ts create mode 100644 app/client/src/git/requests/generateSSHKeyRequest.types.ts create mode 100644 app/client/src/git/requests/importGitRequest.ts create mode 100644 app/client/src/git/requests/importGitRequest.types.ts create mode 100644 app/client/src/git/requests/mergeRequest.ts create mode 100644 app/client/src/git/requests/mergeRequest.types.ts create mode 100644 app/client/src/git/requests/pullRequest.ts create mode 100644 app/client/src/git/requests/pullRequest.types.ts create mode 100644 app/client/src/git/requests/toggleAutocommitRequest.ts create mode 100644 app/client/src/git/requests/toggleAutocommitRequest.types.ts create mode 100644 app/client/src/git/requests/triggerAutocommitRequest.ts create mode 100644 app/client/src/git/requests/triggerAutocommitRequest.types.ts create mode 100644 app/client/src/git/requests/updateGlobalConfigRequest.ts create mode 100644 app/client/src/git/requests/updateGlobalConfigRequest.types.ts create mode 100644 app/client/src/git/requests/updateLocalConfigRequest.ts create mode 100644 app/client/src/git/requests/updateLocalConfigRequest.types.ts create mode 100644 app/client/src/git/requests/updateProtectedBranchesRequest.ts create mode 100644 app/client/src/git/requests/updateProtectedBranchesRequest.types.ts diff --git a/app/client/src/git/enums.ts b/app/client/src/git/constants/enums.ts similarity index 69% rename from app/client/src/git/enums.ts rename to app/client/src/git/constants/enums.ts index fe72149e9fe7..e431e6323ca8 100644 --- a/app/client/src/git/enums.ts +++ b/app/client/src/git/constants/enums.ts @@ -25,3 +25,12 @@ export enum GitSettingsTab { General = "General", Branch = "Branch", } + +export enum AutocommitStatus { + IN_PROGRESS = "IN_PROGRESS", + LOCKED = "LOCKED", + PUBLISHED = "PUBLISHED", + IDLE = "IDLE", + NOT_REQUIRED = "NOT_REQUIRED", + NON_GIT_APP = "NON_GIT_APP", +} diff --git a/app/client/src/git/requests/checkoutBranchRequest.ts b/app/client/src/git/requests/checkoutBranchRequest.ts new file mode 100644 index 000000000000..6deb91416dfc --- /dev/null +++ b/app/client/src/git/requests/checkoutBranchRequest.ts @@ -0,0 +1,17 @@ +import type { AxiosResponse } from "axios"; +import type { + CheckoutBranchRequestParams, + CheckoutBranchResponse, +} from "./checkoutBranchRequest.types"; +import { GIT_BASE_URL } from "./constants"; +import Api from "api/Api"; + +export async function checkoutBranchRequest( + branchedApplicationId: string, + params: CheckoutBranchRequestParams, +): Promise> { + return Api.get( + `${GIT_BASE_URL}/checkout-branch/app/${branchedApplicationId}`, + params, + ); +} diff --git a/app/client/src/git/requests/checkoutBranchRequest.types.ts b/app/client/src/git/requests/checkoutBranchRequest.types.ts new file mode 100644 index 000000000000..8c465fc624ee --- /dev/null +++ b/app/client/src/git/requests/checkoutBranchRequest.types.ts @@ -0,0 +1,8 @@ +export interface CheckoutBranchRequestParams { + branchName: string; +} + +export interface CheckoutBranchResponse { + id: string; // applicationId + baseId: string; // baseApplicationId +} diff --git a/app/client/src/git/requests/commitRequest.ts b/app/client/src/git/requests/commitRequest.ts new file mode 100644 index 000000000000..9c8959214d0d --- /dev/null +++ b/app/client/src/git/requests/commitRequest.ts @@ -0,0 +1,17 @@ +import Api from "api/Api"; +import type { + CommitRequestParams, + CommitResponse, +} from "./commitRequest.types"; +import { GIT_BASE_URL } from "./constants"; +import type { AxiosResponse } from "axios"; + +export async function commitRequest( + branchedApplicationId: string, + params: CommitRequestParams, +): Promise> { + return Api.post( + `${GIT_BASE_URL}/commit/app/${branchedApplicationId}`, + params, + ); +} diff --git a/app/client/src/git/requests/commitRequest.types.ts b/app/client/src/git/requests/commitRequest.types.ts new file mode 100644 index 000000000000..b9c4bd7d7871 --- /dev/null +++ b/app/client/src/git/requests/commitRequest.types.ts @@ -0,0 +1,6 @@ +export interface CommitRequestParams { + commitMessage: string; + doPush: boolean; +} + +export type CommitResponse = string; diff --git a/app/client/src/git/requests/connectRequest.ts b/app/client/src/git/requests/connectRequest.ts new file mode 100644 index 000000000000..ae40320d7175 --- /dev/null +++ b/app/client/src/git/requests/connectRequest.ts @@ -0,0 +1,14 @@ +import Api from "api/Api"; +import { GIT_BASE_URL } from "./constants"; +import type { + ConnectRequestParams, + ConnectResponse, +} from "./connectRequest.types"; +import type { AxiosResponse } from "axios"; + +export async function connectRequest( + baseApplicationId: string, + params: ConnectRequestParams, +): Promise> { + return Api.post(`${GIT_BASE_URL}/connect/app/${baseApplicationId}`, params); +} diff --git a/app/client/src/git/requests/connectRequest.types.ts b/app/client/src/git/requests/connectRequest.types.ts new file mode 100644 index 000000000000..ef529d1bc1ff --- /dev/null +++ b/app/client/src/git/requests/connectRequest.types.ts @@ -0,0 +1,24 @@ +export interface ConnectRequestParams { + remoteUrl: string; + gitProfile?: { + authorName: string; + authorEmail: string; + useDefaultProfile?: boolean; + }; +} + +export interface ConnectResponse { + id: string; + baseId: string; + gitApplicationMetadata: { + branchName: string; + browserSupportedRemoteUrl: string; + defaultApplicationId: string; + defaultArtifactId: string; + defaultBranchName: string; + isRepoPrivate: boolean; + lastCommitedAt: string; + remoteUrl: string; + repoName: string; + }; +} diff --git a/app/client/src/git/requests/constants.ts b/app/client/src/git/requests/constants.ts new file mode 100644 index 000000000000..8650f6f27e28 --- /dev/null +++ b/app/client/src/git/requests/constants.ts @@ -0,0 +1 @@ +export const GIT_BASE_URL = "/v1/git"; diff --git a/app/client/src/git/requests/createBranchRequest.ts b/app/client/src/git/requests/createBranchRequest.ts new file mode 100644 index 000000000000..5be88477f20d --- /dev/null +++ b/app/client/src/git/requests/createBranchRequest.ts @@ -0,0 +1,17 @@ +import type { AxiosResponse } from "axios"; +import type { + CreateBranchRequestParams, + CreateBranchResponse, +} from "./createBranchRequest.types"; +import { GIT_BASE_URL } from "./constants"; +import Api from "api/Api"; + +export async function createBranchRequest( + branchedApplicationId: string, + params: CreateBranchRequestParams, +): Promise> { + return Api.post( + `${GIT_BASE_URL}/create-branch/app/${branchedApplicationId}`, + params, + ); +} diff --git a/app/client/src/git/requests/createBranchRequest.types.ts b/app/client/src/git/requests/createBranchRequest.types.ts new file mode 100644 index 000000000000..28735db75183 --- /dev/null +++ b/app/client/src/git/requests/createBranchRequest.types.ts @@ -0,0 +1,8 @@ +export interface CreateBranchRequestParams { + branchName: string; +} + +export interface CreateBranchResponse { + id: string; // applicationId + baseId: string; // baseApplicationId +} diff --git a/app/client/src/git/requests/deleteBranchRequest.ts b/app/client/src/git/requests/deleteBranchRequest.ts new file mode 100644 index 000000000000..76075f03f3de --- /dev/null +++ b/app/client/src/git/requests/deleteBranchRequest.ts @@ -0,0 +1,14 @@ +import type { AxiosResponse } from "axios"; +import type { + DeleteBranchRequestParams, + DeleteBranchResponse, +} from "./deleteBranchRequest.types"; +import { GIT_BASE_URL } from "./constants"; +import Api from "api/Api"; + +export async function deleteBranchRequest( + baseApplicationId: string, + params: DeleteBranchRequestParams, +): Promise> { + return Api.delete(GIT_BASE_URL + "/branch/app/" + baseApplicationId, params); +} diff --git a/app/client/src/git/requests/deleteBranchRequest.types.ts b/app/client/src/git/requests/deleteBranchRequest.types.ts new file mode 100644 index 000000000000..f7db6f834859 --- /dev/null +++ b/app/client/src/git/requests/deleteBranchRequest.types.ts @@ -0,0 +1,8 @@ +export interface DeleteBranchRequestParams { + branchName: string; +} + +export interface DeleteBranchResponse { + id: string; // applicationId + baseId: string; // baseApplicationId +} diff --git a/app/client/src/git/requests/discardRequest.ts b/app/client/src/git/requests/discardRequest.ts new file mode 100644 index 000000000000..9e5849288baf --- /dev/null +++ b/app/client/src/git/requests/discardRequest.ts @@ -0,0 +1,9 @@ +import Api from "api/Api"; +import { GIT_BASE_URL } from "./constants"; +import type { AxiosResponse } from "axios"; + +export async function discardRequest( + branchedApplicationId: string, +): Promise> { + return Api.put(`${GIT_BASE_URL}/discard/app/${branchedApplicationId}`); +} diff --git a/app/client/src/git/requests/disconnectRequest.ts b/app/client/src/git/requests/disconnectRequest.ts new file mode 100644 index 000000000000..a27bcb496693 --- /dev/null +++ b/app/client/src/git/requests/disconnectRequest.ts @@ -0,0 +1,10 @@ +import type { AxiosResponse } from "axios"; +import { GIT_BASE_URL } from "./constants"; +import type { DisconnectResponse } from "./disconnectRequest.types"; +import Api from "api/Api"; + +export async function disconnectRequest( + baseApplicationId: string, +): Promise> { + return Api.post(`${GIT_BASE_URL}/disconnect/app/${baseApplicationId}`); +} diff --git a/app/client/src/git/requests/disconnectRequest.types.ts b/app/client/src/git/requests/disconnectRequest.types.ts new file mode 100644 index 000000000000..34ac4728a324 --- /dev/null +++ b/app/client/src/git/requests/disconnectRequest.types.ts @@ -0,0 +1,3 @@ +export interface DisconnectResponse { + [key: string]: string; +} diff --git a/app/client/src/git/requests/fetchAutocommitProgressRequest.ts b/app/client/src/git/requests/fetchAutocommitProgressRequest.ts new file mode 100644 index 000000000000..4d10ad93a1cd --- /dev/null +++ b/app/client/src/git/requests/fetchAutocommitProgressRequest.ts @@ -0,0 +1,12 @@ +import Api from "api/Api"; +import { GIT_BASE_URL } from "./constants"; +import type { AxiosResponse } from "axios"; +import type { FetchAutocommitProgressResponse } from "./fetchAutocommitProgressRequest.types"; + +export async function fetchAutocommitProgressRequest( + baseApplicationId: string, +): Promise> { + return Api.get( + `${GIT_BASE_URL}/auto-commit/progress/app/${baseApplicationId}`, + ); +} diff --git a/app/client/src/git/requests/fetchAutocommitProgressRequest.types.ts b/app/client/src/git/requests/fetchAutocommitProgressRequest.types.ts new file mode 100644 index 000000000000..60f10b5fc6b3 --- /dev/null +++ b/app/client/src/git/requests/fetchAutocommitProgressRequest.types.ts @@ -0,0 +1,7 @@ +import type { AutocommitStatus } from "../constants/enums"; + +export interface FetchAutocommitProgressResponse { + autoCommitResponse: AutocommitStatus; + progress: number; + branchName: string; +} diff --git a/app/client/src/git/requests/fetchBranchesRequest.ts b/app/client/src/git/requests/fetchBranchesRequest.ts new file mode 100644 index 000000000000..837f81653251 --- /dev/null +++ b/app/client/src/git/requests/fetchBranchesRequest.ts @@ -0,0 +1,21 @@ +import Api from "api/Api"; +import { GIT_BASE_URL } from "./constants"; +import type { + FetchBranchesRequestParams, + FetchBranchesResponse, +} from "./fetchBranchesRequest.types"; +import type { AxiosResponse } from "axios"; + +export async function fetchBranchesRequest( + branchedApplicationId: string, + params?: FetchBranchesRequestParams, +): Promise> { + const queryParams = {} as FetchBranchesRequestParams; + + if (params?.pruneBranches) queryParams.pruneBranches = true; + + return Api.get( + `${GIT_BASE_URL}/branch/app/${branchedApplicationId}`, + queryParams, + ); +} diff --git a/app/client/src/git/requests/fetchBranchesRequest.types.ts b/app/client/src/git/requests/fetchBranchesRequest.types.ts new file mode 100644 index 000000000000..e86e545b309e --- /dev/null +++ b/app/client/src/git/requests/fetchBranchesRequest.types.ts @@ -0,0 +1,11 @@ +export interface FetchBranchesRequestParams { + pruneBranches: boolean; +} + +interface SingleBranch { + branchName: string; + createdFromLocal: string; + default: boolean; +} + +export type FetchBranchesResponse = SingleBranch[]; diff --git a/app/client/src/git/requests/fetchGitMetadataRequest.ts b/app/client/src/git/requests/fetchGitMetadataRequest.ts new file mode 100644 index 000000000000..155052640918 --- /dev/null +++ b/app/client/src/git/requests/fetchGitMetadataRequest.ts @@ -0,0 +1,10 @@ +import Api from "api/Api"; +import { GIT_BASE_URL } from "./constants"; +import type { AxiosResponse } from "axios"; +import type { FetchGitMetadataResponse } from "./fetchGitMetadataRequest.types"; + +export async function fetchGitMetadataRequest( + baseApplicationId: string, +): Promise> { + return Api.get(`${GIT_BASE_URL}/metadata/app/${baseApplicationId}`); +} diff --git a/app/client/src/git/requests/fetchGitMetadataRequest.types.ts b/app/client/src/git/requests/fetchGitMetadataRequest.types.ts new file mode 100644 index 000000000000..95ef9f6ec3ab --- /dev/null +++ b/app/client/src/git/requests/fetchGitMetadataRequest.types.ts @@ -0,0 +1,15 @@ +export interface FetchGitMetadataResponse { + branchName: string; + defaultBranchName: string; + remoteUrl: string; + repoName: string; + browserSupportedUrl?: string; + isRepoPrivate?: boolean; + browserSupportedRemoteUrl: string; + defaultApplicationId: string; + isProtectedBranch: boolean; + autoCommitConfig: { + enabled: boolean; + }; + isAutoDeploymentEnabled?: boolean; +} diff --git a/app/client/src/git/requests/fetchGlobalConfigRequest.ts b/app/client/src/git/requests/fetchGlobalConfigRequest.ts new file mode 100644 index 000000000000..9fdaa4e7faa2 --- /dev/null +++ b/app/client/src/git/requests/fetchGlobalConfigRequest.ts @@ -0,0 +1,10 @@ +import Api from "api/Api"; +import { GIT_BASE_URL } from "./constants"; +import type { AxiosResponse } from "axios"; +import type { FetchGlobalConfigResponse } from "./fetchGlobalConfigRequest.types"; + +export async function fetchGlobalConfigRequest(): Promise< + AxiosResponse +> { + return Api.get(`${GIT_BASE_URL}/profile/default`); +} diff --git a/app/client/src/git/requests/fetchGlobalConfigRequest.types.ts b/app/client/src/git/requests/fetchGlobalConfigRequest.types.ts new file mode 100644 index 000000000000..1939b2df65fd --- /dev/null +++ b/app/client/src/git/requests/fetchGlobalConfigRequest.types.ts @@ -0,0 +1,4 @@ +export interface FetchGlobalConfigResponse { + authorName: string; + authorEmail: string; +} diff --git a/app/client/src/git/requests/fetchLocalConfigRequest.ts b/app/client/src/git/requests/fetchLocalConfigRequest.ts new file mode 100644 index 000000000000..5ef8150bd220 --- /dev/null +++ b/app/client/src/git/requests/fetchLocalConfigRequest.ts @@ -0,0 +1,10 @@ +import Api from "api/Api"; +import type { AxiosResponse } from "axios"; +import type { FetchGlobalConfigResponse } from "./fetchGlobalConfigRequest.types"; +import { GIT_BASE_URL } from "./constants"; + +export async function fetchLocalConfigRequest( + baseApplicationId: string, +): Promise> { + return Api.get(`${GIT_BASE_URL}/profile/app/${baseApplicationId}`); +} diff --git a/app/client/src/git/requests/fetchLocalConfigRequest.types.ts b/app/client/src/git/requests/fetchLocalConfigRequest.types.ts new file mode 100644 index 000000000000..98619580e009 --- /dev/null +++ b/app/client/src/git/requests/fetchLocalConfigRequest.types.ts @@ -0,0 +1,5 @@ +export interface fetchLocalConfigResponse { + authorName: string; + authorEmail: string; + useGlobalProfile: boolean; +} diff --git a/app/client/src/git/requests/fetchMergeStatusRequest.ts b/app/client/src/git/requests/fetchMergeStatusRequest.ts new file mode 100644 index 000000000000..00bc64c21f8e --- /dev/null +++ b/app/client/src/git/requests/fetchMergeStatusRequest.ts @@ -0,0 +1,17 @@ +import type { AxiosResponse } from "axios"; +import type { + FetchMergeStatusRequestParams, + FetchMergeStatusResponse, +} from "./fetchMergeStatusRequest.types"; +import Api from "api/Api"; +import { GIT_BASE_URL } from "./constants"; + +export async function fetchMergeStatusRequest( + branchedApplicationId: string, + params: FetchMergeStatusRequestParams, +): Promise> { + return Api.post( + `${GIT_BASE_URL}/merge/status/app/${branchedApplicationId}`, + params, + ); +} diff --git a/app/client/src/git/requests/fetchMergeStatusRequest.types.ts b/app/client/src/git/requests/fetchMergeStatusRequest.types.ts new file mode 100644 index 000000000000..76965ee37ff5 --- /dev/null +++ b/app/client/src/git/requests/fetchMergeStatusRequest.types.ts @@ -0,0 +1,10 @@ +export interface FetchMergeStatusRequestParams { + sourceBranch: string; + destinationBranch: string; +} + +export interface FetchMergeStatusResponse { + isMergeAble: boolean; + status: string; // merge status + message: string; +} diff --git a/app/client/src/git/requests/fetchProtectedBranchesRequest.ts b/app/client/src/git/requests/fetchProtectedBranchesRequest.ts new file mode 100644 index 000000000000..ebd72f8e0060 --- /dev/null +++ b/app/client/src/git/requests/fetchProtectedBranchesRequest.ts @@ -0,0 +1,10 @@ +import Api from "api/Api"; +import { GIT_BASE_URL } from "./constants"; +import type { AxiosResponse } from "axios"; +import type { FetchProtectedBranches } from "./fetchProtectedBranchesRequest.types"; + +export async function fetchProtectedBranchesRequest( + baseApplicationId: string, +): Promise> { + return Api.get(`${GIT_BASE_URL}/branch/app/${baseApplicationId}/protected`); +} diff --git a/app/client/src/git/requests/fetchProtectedBranchesRequest.types.ts b/app/client/src/git/requests/fetchProtectedBranchesRequest.types.ts new file mode 100644 index 000000000000..166cc05322ed --- /dev/null +++ b/app/client/src/git/requests/fetchProtectedBranchesRequest.types.ts @@ -0,0 +1 @@ +export type FetchProtectedBranches = string[]; diff --git a/app/client/src/git/requests/fetchSSHKeyRequest.ts b/app/client/src/git/requests/fetchSSHKeyRequest.ts new file mode 100644 index 000000000000..80a546cbe6d3 --- /dev/null +++ b/app/client/src/git/requests/fetchSSHKeyRequest.ts @@ -0,0 +1,9 @@ +import type { AxiosResponse } from "axios"; +import type { FetchSSHKeyResponse } from "./fetchSSHKeyRequest.types"; +import Api from "api/Api"; + +export async function fetchSSHKeyRequest( + baseApplicationId: string, +): Promise> { + return Api.get("v1/applications/ssh-keypair/" + baseApplicationId); +} diff --git a/app/client/src/git/requests/fetchSSHKeyRequest.types.ts b/app/client/src/git/requests/fetchSSHKeyRequest.types.ts new file mode 100644 index 000000000000..55b4f305b666 --- /dev/null +++ b/app/client/src/git/requests/fetchSSHKeyRequest.types.ts @@ -0,0 +1,6 @@ +export interface FetchSSHKeyResponse { + publicKey: string; + docUrl: string; + isRegeneratedKey: boolean; + regeneratedKey: boolean; +} diff --git a/app/client/src/git/requests/fetchStatusRequest.ts b/app/client/src/git/requests/fetchStatusRequest.ts new file mode 100644 index 000000000000..ddcd4e0671ef --- /dev/null +++ b/app/client/src/git/requests/fetchStatusRequest.ts @@ -0,0 +1,14 @@ +import Api from "api/Api"; +import type { + FetchStatusRequestParams, + FetchStatusResponse, +} from "./fetchStatusRequest.types"; +import { GIT_BASE_URL } from "./constants"; +import type { AxiosResponse } from "axios"; + +export async function fetchStatusRequest( + branchedApplicationId: string, + params: FetchStatusRequestParams, +): Promise> { + return Api.get(`${GIT_BASE_URL}/status/app/${branchedApplicationId}`, params); +} diff --git a/app/client/src/git/requests/fetchStatusRequest.types.ts b/app/client/src/git/requests/fetchStatusRequest.types.ts new file mode 100644 index 000000000000..0b1d1d5d3038 --- /dev/null +++ b/app/client/src/git/requests/fetchStatusRequest.types.ts @@ -0,0 +1,38 @@ +export interface FetchStatusRequestParams { + compareRemote: boolean; +} + +export interface FetchStatusResponse { + added: string[]; + aheadCount: number; + behindCount: number; + conflicting: string[]; + datasourcesAdded: string[]; + datasourcesModified: string[]; + datasourcesRemoved: string[]; + discardDocUrl: string; + isClean: boolean; + jsLibsAdded: string[]; + jsLibsModified: string[]; + jsLibsRemoved: string[]; + jsObjectsAdded: string[]; + jsObjectsModified: string[]; + jsObjectsRemoved: string[]; + migrationMessage: string; + modified: []; + modifiedDatasources: number; + modifiedJSLibs: number; + modifiedJSObjects: number; + modifiedModuleInstances: number; + modifiedModules: number; + modifiedPages: number; + modifiedQueries: number; + pagesAdded: string[]; + pagesModified: string[]; + pagesRemoved: string[]; + queriesAdded: string[]; + queriesModified: string[]; + queriesRemoved: string[]; + remoteBranch: string; + removed: string[]; +} diff --git a/app/client/src/git/requests/generateSSHKeyRequest.ts b/app/client/src/git/requests/generateSSHKeyRequest.ts new file mode 100644 index 000000000000..1a5248d0fc5f --- /dev/null +++ b/app/client/src/git/requests/generateSSHKeyRequest.ts @@ -0,0 +1,18 @@ +import type { AxiosResponse } from "axios"; +import type { + GenerateSSHKeyRequestParams, + GenerateSSHKeyResponse, +} from "./generateSSHKeyRequest.types"; +import { GIT_BASE_URL } from "./constants"; +import Api from "api/Api"; + +export async function generateSSHKeyRequest( + baseApplicationId: string, + params: GenerateSSHKeyRequestParams, +): Promise> { + const url = params.isImporting + ? `${GIT_BASE_URL}/import/keys?keyType=${params.keyType}` + : `v1/applications/ssh-keypair/${baseApplicationId}?keyType=${params.keyType}`; + + return params.isImporting ? Api.get(url) : Api.post(url); +} diff --git a/app/client/src/git/requests/generateSSHKeyRequest.types.ts b/app/client/src/git/requests/generateSSHKeyRequest.types.ts new file mode 100644 index 000000000000..ced29ad6dbc0 --- /dev/null +++ b/app/client/src/git/requests/generateSSHKeyRequest.types.ts @@ -0,0 +1,11 @@ +export interface GenerateSSHKeyRequestParams { + keyType: string; + isImporting: boolean; +} + +export interface GenerateSSHKeyResponse { + publicKey: string; + docUrl: string; + isRegeneratedKey: boolean; + regeneratedKey: boolean; +} diff --git a/app/client/src/git/requests/importGitRequest.ts b/app/client/src/git/requests/importGitRequest.ts new file mode 100644 index 000000000000..1bf2d8944644 --- /dev/null +++ b/app/client/src/git/requests/importGitRequest.ts @@ -0,0 +1,14 @@ +import Api from "api/Api"; +import { GIT_BASE_URL } from "./constants"; +import type { + ImportGitRequestParams, + ImportGitResponse, +} from "./importGitRequest.types"; +import type { AxiosResponse } from "axios"; + +export async function importGitRequest( + workspaceId: string, + params: ImportGitRequestParams, +): Promise> { + return Api.post(`${GIT_BASE_URL}/import/${workspaceId}`, params); +} diff --git a/app/client/src/git/requests/importGitRequest.types.ts b/app/client/src/git/requests/importGitRequest.types.ts new file mode 100644 index 000000000000..b0f3113d7a6e --- /dev/null +++ b/app/client/src/git/requests/importGitRequest.types.ts @@ -0,0 +1,24 @@ +export interface ImportGitRequestParams { + remoteUrl: string; + gitProfile?: { + authorName: string; + authorEmail: string; + useDefaultProfile?: boolean; + }; +} + +export interface ImportGitResponse { + id: string; + baseId: string; + gitApplicationMetadata: { + branchName: string; + browserSupportedRemoteUrl: string; + defaultApplicationId: string; + defaultArtifactId: string; + defaultBranchName: string; + isRepoPrivate: boolean; + lastCommitedAt: string; + remoteUrl: string; + repoName: string; + }; +} diff --git a/app/client/src/git/requests/mergeRequest.ts b/app/client/src/git/requests/mergeRequest.ts new file mode 100644 index 000000000000..b1623bfcc6d7 --- /dev/null +++ b/app/client/src/git/requests/mergeRequest.ts @@ -0,0 +1,11 @@ +import Api from "api/Api"; +import type { MergeRequestParams, MergeResponse } from "./mergeRequest.types"; +import { GIT_BASE_URL } from "./constants"; +import type { AxiosResponse } from "axios"; + +export async function mergeRequest( + branchedApplicationId: string, + params: MergeRequestParams, +): Promise> { + return Api.post(`${GIT_BASE_URL}/merge/app/${branchedApplicationId}`, params); +} diff --git a/app/client/src/git/requests/mergeRequest.types.ts b/app/client/src/git/requests/mergeRequest.types.ts new file mode 100644 index 000000000000..7ec27500b1ed --- /dev/null +++ b/app/client/src/git/requests/mergeRequest.types.ts @@ -0,0 +1,9 @@ +export interface MergeRequestParams { + sourceBranch: string; + destinationBranch: string; +} + +export interface MergeResponse { + isMergAble: boolean; + status: string; // merge status +} diff --git a/app/client/src/git/requests/pullRequest.ts b/app/client/src/git/requests/pullRequest.ts new file mode 100644 index 000000000000..e194df9bf2d0 --- /dev/null +++ b/app/client/src/git/requests/pullRequest.ts @@ -0,0 +1,10 @@ +import Api from "api/Api"; +import { GIT_BASE_URL } from "./constants"; +import type { AxiosResponse } from "axios"; +import type { PullRequestResponse } from "./pullRequest.types"; + +export async function pullRequest( + branchedApplicationId: string, +): Promise> { + return Api.get(`${GIT_BASE_URL}/pull/app/${branchedApplicationId}`); +} diff --git a/app/client/src/git/requests/pullRequest.types.ts b/app/client/src/git/requests/pullRequest.types.ts new file mode 100644 index 000000000000..abfb2586ca8e --- /dev/null +++ b/app/client/src/git/requests/pullRequest.types.ts @@ -0,0 +1,6 @@ +export interface PullRequestResponse { + mergeStatus: { + isMergeAble: boolean; + status: string; // pull merge status + }; +} diff --git a/app/client/src/git/requests/toggleAutocommitRequest.ts b/app/client/src/git/requests/toggleAutocommitRequest.ts new file mode 100644 index 000000000000..10dea3f94a27 --- /dev/null +++ b/app/client/src/git/requests/toggleAutocommitRequest.ts @@ -0,0 +1,12 @@ +import Api from "api/Api"; +import { GIT_BASE_URL } from "./constants"; +import type { AxiosResponse } from "axios"; +import type { ToggleAutocommitResponse } from "./toggleAutocommitRequest.types"; + +export async function toggleAutocommitRequest( + baseApplicationId: string, +): Promise> { + return Api.patch( + `${GIT_BASE_URL}/auto-commit/toggle/app/${baseApplicationId}`, + ); +} diff --git a/app/client/src/git/requests/toggleAutocommitRequest.types.ts b/app/client/src/git/requests/toggleAutocommitRequest.types.ts new file mode 100644 index 000000000000..9dc99ed84528 --- /dev/null +++ b/app/client/src/git/requests/toggleAutocommitRequest.types.ts @@ -0,0 +1 @@ +export type ToggleAutocommitResponse = boolean; diff --git a/app/client/src/git/requests/triggerAutocommitRequest.ts b/app/client/src/git/requests/triggerAutocommitRequest.ts new file mode 100644 index 000000000000..ccba7f2fdacb --- /dev/null +++ b/app/client/src/git/requests/triggerAutocommitRequest.ts @@ -0,0 +1,10 @@ +import Api from "api/Api"; +import { GIT_BASE_URL } from "./constants"; +import type { AxiosResponse } from "axios"; +import type { TriggerAutocommitResponse } from "./triggerAutocommitRequest.types"; + +export async function triggerAutocommitRequest( + branchedApplicationId: string, +): Promise> { + return Api.post(`${GIT_BASE_URL}/auto-commit/app/${branchedApplicationId}`); +} diff --git a/app/client/src/git/requests/triggerAutocommitRequest.types.ts b/app/client/src/git/requests/triggerAutocommitRequest.types.ts new file mode 100644 index 000000000000..6abf80ecf226 --- /dev/null +++ b/app/client/src/git/requests/triggerAutocommitRequest.types.ts @@ -0,0 +1,7 @@ +import type { AutocommitStatus } from "../constants/enums"; + +export interface TriggerAutocommitResponse { + autoCommitResponse: AutocommitStatus; + progress: number; + branchName: string; +} diff --git a/app/client/src/git/requests/updateGlobalConfigRequest.ts b/app/client/src/git/requests/updateGlobalConfigRequest.ts new file mode 100644 index 000000000000..df3a69f811ef --- /dev/null +++ b/app/client/src/git/requests/updateGlobalConfigRequest.ts @@ -0,0 +1,13 @@ +import type { AxiosResponse } from "axios"; +import type { + UpdateGlobalConfigRequestParams, + UpdateGlobalConfigResponse, +} from "./updateGlobalConfigRequest.types"; +import Api from "api/Api"; +import { GIT_BASE_URL } from "./constants"; + +export async function updateGlobalConfigRequest( + params: UpdateGlobalConfigRequestParams, +): Promise> { + return Api.post(`${GIT_BASE_URL}/profile/default`, params); +} diff --git a/app/client/src/git/requests/updateGlobalConfigRequest.types.ts b/app/client/src/git/requests/updateGlobalConfigRequest.types.ts new file mode 100644 index 000000000000..10116f7dc991 --- /dev/null +++ b/app/client/src/git/requests/updateGlobalConfigRequest.types.ts @@ -0,0 +1,11 @@ +export interface UpdateGlobalConfigRequestParams { + authorName: string; + authorEmail: string; +} + +export interface UpdateGlobalConfigResponse { + default: { + authorName: string; + authorEmail: string; + }; +} diff --git a/app/client/src/git/requests/updateLocalConfigRequest.ts b/app/client/src/git/requests/updateLocalConfigRequest.ts new file mode 100644 index 000000000000..2586826bdeb0 --- /dev/null +++ b/app/client/src/git/requests/updateLocalConfigRequest.ts @@ -0,0 +1,14 @@ +import type { AxiosResponse } from "axios"; +import type { + UpdateLocalConfigRequestParams, + UpdateLocalConfigResponse, +} from "./updateLocalConfigRequest.types"; +import Api from "api/Api"; +import { GIT_BASE_URL } from "./constants"; + +export async function updateLocalConfigRequest( + baseApplicationId: string, + params: UpdateLocalConfigRequestParams, +): Promise> { + return Api.put(`${GIT_BASE_URL}/profile/app/${baseApplicationId}`, params); +} diff --git a/app/client/src/git/requests/updateLocalConfigRequest.types.ts b/app/client/src/git/requests/updateLocalConfigRequest.types.ts new file mode 100644 index 000000000000..5414637a46c8 --- /dev/null +++ b/app/client/src/git/requests/updateLocalConfigRequest.types.ts @@ -0,0 +1,13 @@ +export interface UpdateLocalConfigRequestParams { + authorName: string; + authorEmail: string; + useGlobalProfile: boolean; +} + +export interface UpdateLocalConfigResponse { + [baseApplicationId: string]: { + authorName: string; + authorEmail: string; + useGlobalProfile: boolean; + }; +} diff --git a/app/client/src/git/requests/updateProtectedBranchesRequest.ts b/app/client/src/git/requests/updateProtectedBranchesRequest.ts new file mode 100644 index 000000000000..957d659e68f8 --- /dev/null +++ b/app/client/src/git/requests/updateProtectedBranchesRequest.ts @@ -0,0 +1,17 @@ +import Api from "api/Api"; +import { GIT_BASE_URL } from "./constants"; +import type { + UpdateProtectedBranchesRequestParams, + UpdateProtectedBranchesResponse, +} from "./updateProtectedBranchesRequest.types"; +import type { AxiosResponse } from "axios"; + +export async function updateProtectedBranchesRequest( + baseApplicationId: string, + params: UpdateProtectedBranchesRequestParams, +): Promise> { + return Api.post( + `${GIT_BASE_URL}/branch/app/${baseApplicationId}/protected`, + params, + ); +} diff --git a/app/client/src/git/requests/updateProtectedBranchesRequest.types.ts b/app/client/src/git/requests/updateProtectedBranchesRequest.types.ts new file mode 100644 index 000000000000..fff7073624e4 --- /dev/null +++ b/app/client/src/git/requests/updateProtectedBranchesRequest.types.ts @@ -0,0 +1,5 @@ +export interface UpdateProtectedBranchesRequestParams { + branchNames: string[]; +} + +export type UpdateProtectedBranchesResponse = string[]; diff --git a/app/client/src/git/types.ts b/app/client/src/git/types.ts index 7786dcc1b4a0..af349c168fb8 100644 --- a/app/client/src/git/types.ts +++ b/app/client/src/git/types.ts @@ -5,7 +5,7 @@ import type { GitImportStep, GitOpsTab, GitSettingsTab, -} from "./enums"; +} from "./constants/enums"; // These will be updated when contracts are finalized export type GitMetadata = Record; From 2900b65ecde0c48e5bcc8f7e12f27ff6a6afd668 Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Thu, 5 Dec 2024 19:06:11 +0800 Subject: [PATCH 002/143] fix: review changes --- .../src/git/actions/helpers/singleArtifactInitialState.ts | 2 +- app/client/src/git/requests/constants.ts | 1 + app/client/src/git/requests/deleteBranchRequest.ts | 2 +- app/client/src/git/requests/fetchLocalConfigRequest.ts | 4 ++-- app/client/src/git/requests/fetchLocalConfigRequest.types.ts | 2 +- app/client/src/git/requests/fetchSSHKeyRequest.ts | 3 ++- app/client/src/git/requests/fetchStatusRequest.types.ts | 2 +- app/client/src/git/requests/generateSSHKeyRequest.ts | 4 ++-- 8 files changed, 11 insertions(+), 9 deletions(-) diff --git a/app/client/src/git/actions/helpers/singleArtifactInitialState.ts b/app/client/src/git/actions/helpers/singleArtifactInitialState.ts index 0c8e0cb282f8..26735b772c47 100644 --- a/app/client/src/git/actions/helpers/singleArtifactInitialState.ts +++ b/app/client/src/git/actions/helpers/singleArtifactInitialState.ts @@ -3,7 +3,7 @@ import { GitImportStep, GitOpsTab, GitSettingsTab, -} from "../../enums"; +} from "../../constants/enums"; import type { GitSingleArtifactAPIResponsesReduxState, GitSingleArtifactUIReduxState, diff --git a/app/client/src/git/requests/constants.ts b/app/client/src/git/requests/constants.ts index 8650f6f27e28..e8626c4cc4a0 100644 --- a/app/client/src/git/requests/constants.ts +++ b/app/client/src/git/requests/constants.ts @@ -1 +1,2 @@ export const GIT_BASE_URL = "/v1/git"; +export const APPLICATION_BASE_URL = "/v1/applications"; diff --git a/app/client/src/git/requests/deleteBranchRequest.ts b/app/client/src/git/requests/deleteBranchRequest.ts index 76075f03f3de..3990ec648566 100644 --- a/app/client/src/git/requests/deleteBranchRequest.ts +++ b/app/client/src/git/requests/deleteBranchRequest.ts @@ -10,5 +10,5 @@ export async function deleteBranchRequest( baseApplicationId: string, params: DeleteBranchRequestParams, ): Promise> { - return Api.delete(GIT_BASE_URL + "/branch/app/" + baseApplicationId, params); + return Api.delete(`${GIT_BASE_URL}/branch/app/${baseApplicationId}`, params); } diff --git a/app/client/src/git/requests/fetchLocalConfigRequest.ts b/app/client/src/git/requests/fetchLocalConfigRequest.ts index 5ef8150bd220..eb8dce10d4f2 100644 --- a/app/client/src/git/requests/fetchLocalConfigRequest.ts +++ b/app/client/src/git/requests/fetchLocalConfigRequest.ts @@ -1,10 +1,10 @@ import Api from "api/Api"; import type { AxiosResponse } from "axios"; -import type { FetchGlobalConfigResponse } from "./fetchGlobalConfigRequest.types"; import { GIT_BASE_URL } from "./constants"; +import type { FetchLocalConfigResponse } from "./fetchLocalConfigRequest.types"; export async function fetchLocalConfigRequest( baseApplicationId: string, -): Promise> { +): Promise> { return Api.get(`${GIT_BASE_URL}/profile/app/${baseApplicationId}`); } diff --git a/app/client/src/git/requests/fetchLocalConfigRequest.types.ts b/app/client/src/git/requests/fetchLocalConfigRequest.types.ts index 98619580e009..abc83e1d83ba 100644 --- a/app/client/src/git/requests/fetchLocalConfigRequest.types.ts +++ b/app/client/src/git/requests/fetchLocalConfigRequest.types.ts @@ -1,4 +1,4 @@ -export interface fetchLocalConfigResponse { +export interface FetchLocalConfigResponse { authorName: string; authorEmail: string; useGlobalProfile: boolean; diff --git a/app/client/src/git/requests/fetchSSHKeyRequest.ts b/app/client/src/git/requests/fetchSSHKeyRequest.ts index 80a546cbe6d3..ea6617928055 100644 --- a/app/client/src/git/requests/fetchSSHKeyRequest.ts +++ b/app/client/src/git/requests/fetchSSHKeyRequest.ts @@ -1,9 +1,10 @@ import type { AxiosResponse } from "axios"; import type { FetchSSHKeyResponse } from "./fetchSSHKeyRequest.types"; import Api from "api/Api"; +import { APPLICATION_BASE_URL } from "./constants"; export async function fetchSSHKeyRequest( baseApplicationId: string, ): Promise> { - return Api.get("v1/applications/ssh-keypair/" + baseApplicationId); + return Api.get(`${APPLICATION_BASE_URL}/ssh-keypair/${baseApplicationId}`); } diff --git a/app/client/src/git/requests/fetchStatusRequest.types.ts b/app/client/src/git/requests/fetchStatusRequest.types.ts index 0b1d1d5d3038..9a63fc879487 100644 --- a/app/client/src/git/requests/fetchStatusRequest.types.ts +++ b/app/client/src/git/requests/fetchStatusRequest.types.ts @@ -19,7 +19,7 @@ export interface FetchStatusResponse { jsObjectsModified: string[]; jsObjectsRemoved: string[]; migrationMessage: string; - modified: []; + modified: string[]; modifiedDatasources: number; modifiedJSLibs: number; modifiedJSObjects: number; diff --git a/app/client/src/git/requests/generateSSHKeyRequest.ts b/app/client/src/git/requests/generateSSHKeyRequest.ts index 1a5248d0fc5f..0e10beeb5a10 100644 --- a/app/client/src/git/requests/generateSSHKeyRequest.ts +++ b/app/client/src/git/requests/generateSSHKeyRequest.ts @@ -3,7 +3,7 @@ import type { GenerateSSHKeyRequestParams, GenerateSSHKeyResponse, } from "./generateSSHKeyRequest.types"; -import { GIT_BASE_URL } from "./constants"; +import { APPLICATION_BASE_URL, GIT_BASE_URL } from "./constants"; import Api from "api/Api"; export async function generateSSHKeyRequest( @@ -12,7 +12,7 @@ export async function generateSSHKeyRequest( ): Promise> { const url = params.isImporting ? `${GIT_BASE_URL}/import/keys?keyType=${params.keyType}` - : `v1/applications/ssh-keypair/${baseApplicationId}?keyType=${params.keyType}`; + : `${APPLICATION_BASE_URL}/ssh-keypair/${baseApplicationId}?keyType=${params.keyType}`; return params.isImporting ? Api.get(url) : Api.post(url); } From 146238c47430c11d640c394b5a491d083573fe1c Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Thu, 5 Dec 2024 19:42:29 +0800 Subject: [PATCH 003/143] fix: fixing enum imports --- app/client/src/git/components/QuickActions/index.test.tsx | 2 +- app/client/src/git/components/QuickActions/index.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/client/src/git/components/QuickActions/index.test.tsx b/app/client/src/git/components/QuickActions/index.test.tsx index b920e6b51fde..189b3ea67be9 100644 --- a/app/client/src/git/components/QuickActions/index.test.tsx +++ b/app/client/src/git/components/QuickActions/index.test.tsx @@ -2,7 +2,7 @@ import React from "react"; import { render, screen, fireEvent } from "@testing-library/react"; import AnalyticsUtil from "ee/utils/AnalyticsUtil"; import QuickActions from "."; -import { GitSettingsTab } from "git/enums"; +import { GitSettingsTab } from "../../constants/enums"; import { GitSyncModalTab } from "entities/GitSync"; import { theme } from "constants/DefaultTheme"; import { ThemeProvider } from "styled-components"; diff --git a/app/client/src/git/components/QuickActions/index.tsx b/app/client/src/git/components/QuickActions/index.tsx index cab336ca1e52..21483fb83ad4 100644 --- a/app/client/src/git/components/QuickActions/index.tsx +++ b/app/client/src/git/components/QuickActions/index.tsx @@ -12,7 +12,7 @@ import { GitSyncModalTab } from "entities/GitSync"; import AnalyticsUtil from "ee/utils/AnalyticsUtil"; import type { GitMetadata, GitStatus } from "../../types"; import { getPullBtnStatus } from "./helpers"; -import { GitSettingsTab } from "../../enums"; +import { GitSettingsTab } from "../../constants/enums"; import ConnectButton from "./ConnectButton"; import QuickActionButton from "./QuickActionButton"; import AutocommitStatusbar from "./AutocommitStatusbar"; From e72e02f75e0c58ad1306776b3246c6de2431e9bf Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Fri, 6 Dec 2024 15:16:00 +0800 Subject: [PATCH 004/143] chore: changing named export to default export --- app/client/src/git/requests/checkoutBranchRequest.ts | 2 +- app/client/src/git/requests/commitRequest.ts | 2 +- app/client/src/git/requests/connectRequest.ts | 2 +- app/client/src/git/requests/createBranchRequest.ts | 2 +- app/client/src/git/requests/deleteBranchRequest.ts | 2 +- app/client/src/git/requests/discardRequest.ts | 2 +- app/client/src/git/requests/disconnectRequest.ts | 2 +- app/client/src/git/requests/fetchAutocommitProgressRequest.ts | 2 +- app/client/src/git/requests/fetchBranchesRequest.ts | 2 +- app/client/src/git/requests/fetchGitMetadataRequest.ts | 2 +- app/client/src/git/requests/fetchGlobalConfigRequest.ts | 2 +- app/client/src/git/requests/fetchLocalConfigRequest.ts | 2 +- app/client/src/git/requests/fetchMergeStatusRequest.ts | 2 +- app/client/src/git/requests/fetchProtectedBranchesRequest.ts | 2 +- app/client/src/git/requests/fetchSSHKeyRequest.ts | 2 +- app/client/src/git/requests/fetchStatusRequest.ts | 2 +- app/client/src/git/requests/generateSSHKeyRequest.ts | 2 +- app/client/src/git/requests/importGitRequest.ts | 2 +- app/client/src/git/requests/mergeRequest.ts | 2 +- app/client/src/git/requests/pullRequest.ts | 2 +- app/client/src/git/requests/toggleAutocommitRequest.ts | 2 +- app/client/src/git/requests/triggerAutocommitRequest.ts | 2 +- app/client/src/git/requests/updateGlobalConfigRequest.ts | 2 +- app/client/src/git/requests/updateLocalConfigRequest.ts | 2 +- app/client/src/git/requests/updateProtectedBranchesRequest.ts | 2 +- 25 files changed, 25 insertions(+), 25 deletions(-) diff --git a/app/client/src/git/requests/checkoutBranchRequest.ts b/app/client/src/git/requests/checkoutBranchRequest.ts index 6deb91416dfc..4df5da6112d3 100644 --- a/app/client/src/git/requests/checkoutBranchRequest.ts +++ b/app/client/src/git/requests/checkoutBranchRequest.ts @@ -6,7 +6,7 @@ import type { import { GIT_BASE_URL } from "./constants"; import Api from "api/Api"; -export async function checkoutBranchRequest( +export default async function checkoutBranchRequest( branchedApplicationId: string, params: CheckoutBranchRequestParams, ): Promise> { diff --git a/app/client/src/git/requests/commitRequest.ts b/app/client/src/git/requests/commitRequest.ts index 9c8959214d0d..69541d030368 100644 --- a/app/client/src/git/requests/commitRequest.ts +++ b/app/client/src/git/requests/commitRequest.ts @@ -6,7 +6,7 @@ import type { import { GIT_BASE_URL } from "./constants"; import type { AxiosResponse } from "axios"; -export async function commitRequest( +export default async function commitRequest( branchedApplicationId: string, params: CommitRequestParams, ): Promise> { diff --git a/app/client/src/git/requests/connectRequest.ts b/app/client/src/git/requests/connectRequest.ts index ae40320d7175..b62578361024 100644 --- a/app/client/src/git/requests/connectRequest.ts +++ b/app/client/src/git/requests/connectRequest.ts @@ -6,7 +6,7 @@ import type { } from "./connectRequest.types"; import type { AxiosResponse } from "axios"; -export async function connectRequest( +export default async function connectRequest( baseApplicationId: string, params: ConnectRequestParams, ): Promise> { diff --git a/app/client/src/git/requests/createBranchRequest.ts b/app/client/src/git/requests/createBranchRequest.ts index 5be88477f20d..a67b5ee04099 100644 --- a/app/client/src/git/requests/createBranchRequest.ts +++ b/app/client/src/git/requests/createBranchRequest.ts @@ -6,7 +6,7 @@ import type { import { GIT_BASE_URL } from "./constants"; import Api from "api/Api"; -export async function createBranchRequest( +export default async function createBranchRequest( branchedApplicationId: string, params: CreateBranchRequestParams, ): Promise> { diff --git a/app/client/src/git/requests/deleteBranchRequest.ts b/app/client/src/git/requests/deleteBranchRequest.ts index 3990ec648566..63f718506d48 100644 --- a/app/client/src/git/requests/deleteBranchRequest.ts +++ b/app/client/src/git/requests/deleteBranchRequest.ts @@ -6,7 +6,7 @@ import type { import { GIT_BASE_URL } from "./constants"; import Api from "api/Api"; -export async function deleteBranchRequest( +export default async function deleteBranchRequest( baseApplicationId: string, params: DeleteBranchRequestParams, ): Promise> { diff --git a/app/client/src/git/requests/discardRequest.ts b/app/client/src/git/requests/discardRequest.ts index 9e5849288baf..fda452fc206c 100644 --- a/app/client/src/git/requests/discardRequest.ts +++ b/app/client/src/git/requests/discardRequest.ts @@ -2,7 +2,7 @@ import Api from "api/Api"; import { GIT_BASE_URL } from "./constants"; import type { AxiosResponse } from "axios"; -export async function discardRequest( +export default async function discardRequest( branchedApplicationId: string, ): Promise> { return Api.put(`${GIT_BASE_URL}/discard/app/${branchedApplicationId}`); diff --git a/app/client/src/git/requests/disconnectRequest.ts b/app/client/src/git/requests/disconnectRequest.ts index a27bcb496693..9ec9b3a4e2b9 100644 --- a/app/client/src/git/requests/disconnectRequest.ts +++ b/app/client/src/git/requests/disconnectRequest.ts @@ -3,7 +3,7 @@ import { GIT_BASE_URL } from "./constants"; import type { DisconnectResponse } from "./disconnectRequest.types"; import Api from "api/Api"; -export async function disconnectRequest( +export default async function disconnectRequest( baseApplicationId: string, ): Promise> { return Api.post(`${GIT_BASE_URL}/disconnect/app/${baseApplicationId}`); diff --git a/app/client/src/git/requests/fetchAutocommitProgressRequest.ts b/app/client/src/git/requests/fetchAutocommitProgressRequest.ts index 4d10ad93a1cd..8ad1c71d22c8 100644 --- a/app/client/src/git/requests/fetchAutocommitProgressRequest.ts +++ b/app/client/src/git/requests/fetchAutocommitProgressRequest.ts @@ -3,7 +3,7 @@ import { GIT_BASE_URL } from "./constants"; import type { AxiosResponse } from "axios"; import type { FetchAutocommitProgressResponse } from "./fetchAutocommitProgressRequest.types"; -export async function fetchAutocommitProgressRequest( +export default async function fetchAutocommitProgressRequest( baseApplicationId: string, ): Promise> { return Api.get( diff --git a/app/client/src/git/requests/fetchBranchesRequest.ts b/app/client/src/git/requests/fetchBranchesRequest.ts index 837f81653251..90fdbf73d94a 100644 --- a/app/client/src/git/requests/fetchBranchesRequest.ts +++ b/app/client/src/git/requests/fetchBranchesRequest.ts @@ -6,7 +6,7 @@ import type { } from "./fetchBranchesRequest.types"; import type { AxiosResponse } from "axios"; -export async function fetchBranchesRequest( +export default async function fetchBranchesRequest( branchedApplicationId: string, params?: FetchBranchesRequestParams, ): Promise> { diff --git a/app/client/src/git/requests/fetchGitMetadataRequest.ts b/app/client/src/git/requests/fetchGitMetadataRequest.ts index 155052640918..136f5776f557 100644 --- a/app/client/src/git/requests/fetchGitMetadataRequest.ts +++ b/app/client/src/git/requests/fetchGitMetadataRequest.ts @@ -3,7 +3,7 @@ import { GIT_BASE_URL } from "./constants"; import type { AxiosResponse } from "axios"; import type { FetchGitMetadataResponse } from "./fetchGitMetadataRequest.types"; -export async function fetchGitMetadataRequest( +export default async function fetchGitMetadataRequest( baseApplicationId: string, ): Promise> { return Api.get(`${GIT_BASE_URL}/metadata/app/${baseApplicationId}`); diff --git a/app/client/src/git/requests/fetchGlobalConfigRequest.ts b/app/client/src/git/requests/fetchGlobalConfigRequest.ts index 9fdaa4e7faa2..32b048c0bbf0 100644 --- a/app/client/src/git/requests/fetchGlobalConfigRequest.ts +++ b/app/client/src/git/requests/fetchGlobalConfigRequest.ts @@ -3,7 +3,7 @@ import { GIT_BASE_URL } from "./constants"; import type { AxiosResponse } from "axios"; import type { FetchGlobalConfigResponse } from "./fetchGlobalConfigRequest.types"; -export async function fetchGlobalConfigRequest(): Promise< +export default async function fetchGlobalConfigRequest(): Promise< AxiosResponse > { return Api.get(`${GIT_BASE_URL}/profile/default`); diff --git a/app/client/src/git/requests/fetchLocalConfigRequest.ts b/app/client/src/git/requests/fetchLocalConfigRequest.ts index eb8dce10d4f2..53159fc886f7 100644 --- a/app/client/src/git/requests/fetchLocalConfigRequest.ts +++ b/app/client/src/git/requests/fetchLocalConfigRequest.ts @@ -3,7 +3,7 @@ import type { AxiosResponse } from "axios"; import { GIT_BASE_URL } from "./constants"; import type { FetchLocalConfigResponse } from "./fetchLocalConfigRequest.types"; -export async function fetchLocalConfigRequest( +export default async function fetchLocalConfigRequest( baseApplicationId: string, ): Promise> { return Api.get(`${GIT_BASE_URL}/profile/app/${baseApplicationId}`); diff --git a/app/client/src/git/requests/fetchMergeStatusRequest.ts b/app/client/src/git/requests/fetchMergeStatusRequest.ts index 00bc64c21f8e..95701d5cadc8 100644 --- a/app/client/src/git/requests/fetchMergeStatusRequest.ts +++ b/app/client/src/git/requests/fetchMergeStatusRequest.ts @@ -6,7 +6,7 @@ import type { import Api from "api/Api"; import { GIT_BASE_URL } from "./constants"; -export async function fetchMergeStatusRequest( +export default async function fetchMergeStatusRequest( branchedApplicationId: string, params: FetchMergeStatusRequestParams, ): Promise> { diff --git a/app/client/src/git/requests/fetchProtectedBranchesRequest.ts b/app/client/src/git/requests/fetchProtectedBranchesRequest.ts index ebd72f8e0060..492a23c5eeca 100644 --- a/app/client/src/git/requests/fetchProtectedBranchesRequest.ts +++ b/app/client/src/git/requests/fetchProtectedBranchesRequest.ts @@ -3,7 +3,7 @@ import { GIT_BASE_URL } from "./constants"; import type { AxiosResponse } from "axios"; import type { FetchProtectedBranches } from "./fetchProtectedBranchesRequest.types"; -export async function fetchProtectedBranchesRequest( +export default async function fetchProtectedBranchesRequest( baseApplicationId: string, ): Promise> { return Api.get(`${GIT_BASE_URL}/branch/app/${baseApplicationId}/protected`); diff --git a/app/client/src/git/requests/fetchSSHKeyRequest.ts b/app/client/src/git/requests/fetchSSHKeyRequest.ts index ea6617928055..e61884e28a3b 100644 --- a/app/client/src/git/requests/fetchSSHKeyRequest.ts +++ b/app/client/src/git/requests/fetchSSHKeyRequest.ts @@ -3,7 +3,7 @@ import type { FetchSSHKeyResponse } from "./fetchSSHKeyRequest.types"; import Api from "api/Api"; import { APPLICATION_BASE_URL } from "./constants"; -export async function fetchSSHKeyRequest( +export default async function fetchSSHKeyRequest( baseApplicationId: string, ): Promise> { return Api.get(`${APPLICATION_BASE_URL}/ssh-keypair/${baseApplicationId}`); diff --git a/app/client/src/git/requests/fetchStatusRequest.ts b/app/client/src/git/requests/fetchStatusRequest.ts index ddcd4e0671ef..587b4f66ea0b 100644 --- a/app/client/src/git/requests/fetchStatusRequest.ts +++ b/app/client/src/git/requests/fetchStatusRequest.ts @@ -6,7 +6,7 @@ import type { import { GIT_BASE_URL } from "./constants"; import type { AxiosResponse } from "axios"; -export async function fetchStatusRequest( +export default async function fetchStatusRequest( branchedApplicationId: string, params: FetchStatusRequestParams, ): Promise> { diff --git a/app/client/src/git/requests/generateSSHKeyRequest.ts b/app/client/src/git/requests/generateSSHKeyRequest.ts index 0e10beeb5a10..525c0423a16f 100644 --- a/app/client/src/git/requests/generateSSHKeyRequest.ts +++ b/app/client/src/git/requests/generateSSHKeyRequest.ts @@ -6,7 +6,7 @@ import type { import { APPLICATION_BASE_URL, GIT_BASE_URL } from "./constants"; import Api from "api/Api"; -export async function generateSSHKeyRequest( +export default async function generateSSHKeyRequest( baseApplicationId: string, params: GenerateSSHKeyRequestParams, ): Promise> { diff --git a/app/client/src/git/requests/importGitRequest.ts b/app/client/src/git/requests/importGitRequest.ts index 1bf2d8944644..e9378361da88 100644 --- a/app/client/src/git/requests/importGitRequest.ts +++ b/app/client/src/git/requests/importGitRequest.ts @@ -6,7 +6,7 @@ import type { } from "./importGitRequest.types"; import type { AxiosResponse } from "axios"; -export async function importGitRequest( +export default async function importGitRequest( workspaceId: string, params: ImportGitRequestParams, ): Promise> { diff --git a/app/client/src/git/requests/mergeRequest.ts b/app/client/src/git/requests/mergeRequest.ts index b1623bfcc6d7..ee30566c4936 100644 --- a/app/client/src/git/requests/mergeRequest.ts +++ b/app/client/src/git/requests/mergeRequest.ts @@ -3,7 +3,7 @@ import type { MergeRequestParams, MergeResponse } from "./mergeRequest.types"; import { GIT_BASE_URL } from "./constants"; import type { AxiosResponse } from "axios"; -export async function mergeRequest( +export default async function mergeRequest( branchedApplicationId: string, params: MergeRequestParams, ): Promise> { diff --git a/app/client/src/git/requests/pullRequest.ts b/app/client/src/git/requests/pullRequest.ts index e194df9bf2d0..21bd6f4f2a3c 100644 --- a/app/client/src/git/requests/pullRequest.ts +++ b/app/client/src/git/requests/pullRequest.ts @@ -3,7 +3,7 @@ import { GIT_BASE_URL } from "./constants"; import type { AxiosResponse } from "axios"; import type { PullRequestResponse } from "./pullRequest.types"; -export async function pullRequest( +export default async function pullRequest( branchedApplicationId: string, ): Promise> { return Api.get(`${GIT_BASE_URL}/pull/app/${branchedApplicationId}`); diff --git a/app/client/src/git/requests/toggleAutocommitRequest.ts b/app/client/src/git/requests/toggleAutocommitRequest.ts index 10dea3f94a27..deba662ded3f 100644 --- a/app/client/src/git/requests/toggleAutocommitRequest.ts +++ b/app/client/src/git/requests/toggleAutocommitRequest.ts @@ -3,7 +3,7 @@ import { GIT_BASE_URL } from "./constants"; import type { AxiosResponse } from "axios"; import type { ToggleAutocommitResponse } from "./toggleAutocommitRequest.types"; -export async function toggleAutocommitRequest( +export default async function toggleAutocommitRequest( baseApplicationId: string, ): Promise> { return Api.patch( diff --git a/app/client/src/git/requests/triggerAutocommitRequest.ts b/app/client/src/git/requests/triggerAutocommitRequest.ts index ccba7f2fdacb..01c603cb4ce5 100644 --- a/app/client/src/git/requests/triggerAutocommitRequest.ts +++ b/app/client/src/git/requests/triggerAutocommitRequest.ts @@ -3,7 +3,7 @@ import { GIT_BASE_URL } from "./constants"; import type { AxiosResponse } from "axios"; import type { TriggerAutocommitResponse } from "./triggerAutocommitRequest.types"; -export async function triggerAutocommitRequest( +export default async function triggerAutocommitRequest( branchedApplicationId: string, ): Promise> { return Api.post(`${GIT_BASE_URL}/auto-commit/app/${branchedApplicationId}`); diff --git a/app/client/src/git/requests/updateGlobalConfigRequest.ts b/app/client/src/git/requests/updateGlobalConfigRequest.ts index df3a69f811ef..a20cb5beb877 100644 --- a/app/client/src/git/requests/updateGlobalConfigRequest.ts +++ b/app/client/src/git/requests/updateGlobalConfigRequest.ts @@ -6,7 +6,7 @@ import type { import Api from "api/Api"; import { GIT_BASE_URL } from "./constants"; -export async function updateGlobalConfigRequest( +export default async function updateGlobalConfigRequest( params: UpdateGlobalConfigRequestParams, ): Promise> { return Api.post(`${GIT_BASE_URL}/profile/default`, params); diff --git a/app/client/src/git/requests/updateLocalConfigRequest.ts b/app/client/src/git/requests/updateLocalConfigRequest.ts index 2586826bdeb0..4b69bc72c27d 100644 --- a/app/client/src/git/requests/updateLocalConfigRequest.ts +++ b/app/client/src/git/requests/updateLocalConfigRequest.ts @@ -6,7 +6,7 @@ import type { import Api from "api/Api"; import { GIT_BASE_URL } from "./constants"; -export async function updateLocalConfigRequest( +export default async function updateLocalConfigRequest( baseApplicationId: string, params: UpdateLocalConfigRequestParams, ): Promise> { diff --git a/app/client/src/git/requests/updateProtectedBranchesRequest.ts b/app/client/src/git/requests/updateProtectedBranchesRequest.ts index 957d659e68f8..5af603ecaa7d 100644 --- a/app/client/src/git/requests/updateProtectedBranchesRequest.ts +++ b/app/client/src/git/requests/updateProtectedBranchesRequest.ts @@ -6,7 +6,7 @@ import type { } from "./updateProtectedBranchesRequest.types"; import type { AxiosResponse } from "axios"; -export async function updateProtectedBranchesRequest( +export default async function updateProtectedBranchesRequest( baseApplicationId: string, params: UpdateProtectedBranchesRequestParams, ): Promise> { From 0bb662f6dfc5a714d87a0011931a292174cf02da Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Sat, 7 Dec 2024 15:41:13 +0800 Subject: [PATCH 005/143] fix: adding saga for commit and connect --- app/client/src/git/actions/commitActions.ts | 15 ++-- app/client/src/git/actions/connectActions.ts | 26 ++++--- .../src/git/actions/fetchStatusActions.ts | 14 ++-- .../helpers/singleArtifactInitialState.ts | 3 + .../git/actions/repoLimitErrorModalActions.ts | 16 ++++ app/client/src/git/constants/enums.ts | 5 ++ app/client/src/git/constants/misc.ts | 1 + .../src/git/requests/commitRequest.types.ts | 6 +- app/client/src/git/requests/connectRequest.ts | 4 +- .../src/git/requests/connectRequest.types.ts | 6 +- app/client/src/git/sagas/commitSaga.ts | 66 ++++++++++++++++ app/client/src/git/sagas/connectSaga.ts | 78 +++++++++++++++++++ app/client/src/git/sagas/index.ts | 11 +++ app/client/src/git/store/gitArtifactSlice.ts | 6 +- app/client/src/git/types.ts | 17 +++- 15 files changed, 245 insertions(+), 29 deletions(-) create mode 100644 app/client/src/git/actions/repoLimitErrorModalActions.ts create mode 100644 app/client/src/git/constants/misc.ts create mode 100644 app/client/src/git/sagas/commitSaga.ts create mode 100644 app/client/src/git/sagas/connectSaga.ts create mode 100644 app/client/src/git/sagas/index.ts diff --git a/app/client/src/git/actions/commitActions.ts b/app/client/src/git/actions/commitActions.ts index 1fbe3f90cdea..c0f491d2f6b7 100644 --- a/app/client/src/git/actions/commitActions.ts +++ b/app/client/src/git/actions/commitActions.ts @@ -1,12 +1,17 @@ import { createSingleArtifactAction } from "./helpers/createSingleArtifactAction"; import type { GitArtifactErrorPayloadAction } from "../types"; +import type { CommitRequestParams } from "git/requests/commitRequest.types"; -export const commitInitAction = createSingleArtifactAction((state) => { - state.apiResponses.commit.loading = true; - state.apiResponses.commit.error = null; +export interface CommitInitPayload extends CommitRequestParams {} - return state; -}); +export const commitInitAction = createSingleArtifactAction( + (state) => { + state.apiResponses.commit.loading = true; + state.apiResponses.commit.error = null; + + return state; + }, +); export const commitSuccessAction = createSingleArtifactAction((state) => { state.apiResponses.commit.loading = false; diff --git a/app/client/src/git/actions/connectActions.ts b/app/client/src/git/actions/connectActions.ts index 725b7483924f..ab67587075fc 100644 --- a/app/client/src/git/actions/connectActions.ts +++ b/app/client/src/git/actions/connectActions.ts @@ -1,12 +1,19 @@ import { createSingleArtifactAction } from "./helpers/createSingleArtifactAction"; -import type { GitArtifactErrorPayloadAction } from "../types"; +import type { GitArtifactErrorPayload } from "../types"; +import type { ConnectRequestParams } from "git/requests/connectRequest.types"; -export const connectInitAction = createSingleArtifactAction((state) => { - state.apiResponses.connect.loading = true; - state.apiResponses.connect.error = null; +export interface ConnectInitPayload extends ConnectRequestParams { + branchedPageId?: string; +} - return state; -}); +export const connectInitAction = createSingleArtifactAction( + (state) => { + state.apiResponses.connect.loading = true; + state.apiResponses.connect.error = null; + + return state; + }, +); export const connectSuccessAction = createSingleArtifactAction((state) => { state.apiResponses.connect.loading = false; @@ -14,13 +21,12 @@ export const connectSuccessAction = createSingleArtifactAction((state) => { return state; }); -export const connectErrorAction = createSingleArtifactAction( - (state, action: GitArtifactErrorPayloadAction) => { +export const connectErrorAction = + createSingleArtifactAction((state, action) => { const { error } = action.payload; state.apiResponses.connect.loading = false; state.apiResponses.connect.error = error; return state; - }, -); + }); diff --git a/app/client/src/git/actions/fetchStatusActions.ts b/app/client/src/git/actions/fetchStatusActions.ts index 16b6892c04aa..21633eeb424e 100644 --- a/app/client/src/git/actions/fetchStatusActions.ts +++ b/app/client/src/git/actions/fetchStatusActions.ts @@ -1,3 +1,4 @@ +import type { FetchStatusRequestParams } from "git/requests/fetchStatusRequest.types"; import type { GitArtifactPayloadAction, GitArtifactErrorPayloadAction, @@ -5,12 +6,15 @@ import type { } from "../types"; import { createSingleArtifactAction } from "./helpers/createSingleArtifactAction"; -export const fetchStatusInitAction = createSingleArtifactAction((state) => { - state.apiResponses.status.loading = true; - state.apiResponses.status.error = null; +export interface FetchStatusInitPayload extends FetchStatusRequestParams {} - return state; -}); +export const fetchStatusInitAction = + createSingleArtifactAction((state) => { + state.apiResponses.status.loading = true; + state.apiResponses.status.error = null; + + return state; + }); export const fetchStatusSuccessAction = createSingleArtifactAction( (state, action: GitArtifactPayloadAction<{ status: GitStatus }>) => { diff --git a/app/client/src/git/actions/helpers/singleArtifactInitialState.ts b/app/client/src/git/actions/helpers/singleArtifactInitialState.ts index 26735b772c47..d62c3f65a01e 100644 --- a/app/client/src/git/actions/helpers/singleArtifactInitialState.ts +++ b/app/client/src/git/actions/helpers/singleArtifactInitialState.ts @@ -30,6 +30,9 @@ const gitSingleArtifactInitialUIState: GitSingleArtifactUIReduxState = { open: false, tab: GitSettingsTab.General, }, + repoLimitErrorModal: { + open: false, + }, }; const gitSingleArtifactInitialAPIResponses: GitSingleArtifactAPIResponsesReduxState = diff --git a/app/client/src/git/actions/repoLimitErrorModalActions.ts b/app/client/src/git/actions/repoLimitErrorModalActions.ts new file mode 100644 index 000000000000..96061395e854 --- /dev/null +++ b/app/client/src/git/actions/repoLimitErrorModalActions.ts @@ -0,0 +1,16 @@ +import { createSingleArtifactAction } from "./helpers/createSingleArtifactAction"; + +interface ToggleRepoLimitModalActionPayload { + open: boolean; +} + +export const toggleRepoLimitErrorModalAction = + createSingleArtifactAction( + (state, action) => { + const { open } = action.payload; + + state.ui.repoLimitErrorModal.open = open; + + return state; + }, + ); diff --git a/app/client/src/git/constants/enums.ts b/app/client/src/git/constants/enums.ts index e431e6323ca8..edec972ecfd7 100644 --- a/app/client/src/git/constants/enums.ts +++ b/app/client/src/git/constants/enums.ts @@ -34,3 +34,8 @@ export enum AutocommitStatus { NOT_REQUIRED = "NOT_REQUIRED", NON_GIT_APP = "NON_GIT_APP", } + +export enum GitErrorCodes { + REPO_LIMIT_REACHED = "AE-GIT-4043", + PUSH_FAILED_REMOTE_COUNTERPART_IS_AHEAD = "AE-GIT-4048", +} diff --git a/app/client/src/git/constants/misc.ts b/app/client/src/git/constants/misc.ts new file mode 100644 index 000000000000..41621dc726c8 --- /dev/null +++ b/app/client/src/git/constants/misc.ts @@ -0,0 +1 @@ +export const GIT_BRANCH_QUERY_KEY = "branch"; diff --git a/app/client/src/git/requests/commitRequest.types.ts b/app/client/src/git/requests/commitRequest.types.ts index b9c4bd7d7871..68f8aeb2cedc 100644 --- a/app/client/src/git/requests/commitRequest.types.ts +++ b/app/client/src/git/requests/commitRequest.types.ts @@ -1,6 +1,10 @@ +import type { ApiResponse } from "api/types"; + export interface CommitRequestParams { commitMessage: string; doPush: boolean; } -export type CommitResponse = string; +export type CommitResponseData = string; + +export type CommitResponse = ApiResponse; diff --git a/app/client/src/git/requests/connectRequest.ts b/app/client/src/git/requests/connectRequest.ts index b62578361024..dac70d3030d7 100644 --- a/app/client/src/git/requests/connectRequest.ts +++ b/app/client/src/git/requests/connectRequest.ts @@ -4,11 +4,11 @@ import type { ConnectRequestParams, ConnectResponse, } from "./connectRequest.types"; -import type { AxiosResponse } from "axios"; +import type { AxiosPromise } from "axios"; export default async function connectRequest( baseApplicationId: string, params: ConnectRequestParams, -): Promise> { +): AxiosPromise { return Api.post(`${GIT_BASE_URL}/connect/app/${baseApplicationId}`, params); } diff --git a/app/client/src/git/requests/connectRequest.types.ts b/app/client/src/git/requests/connectRequest.types.ts index ef529d1bc1ff..7e31cf32bf82 100644 --- a/app/client/src/git/requests/connectRequest.types.ts +++ b/app/client/src/git/requests/connectRequest.types.ts @@ -1,3 +1,5 @@ +import type { ApiResponse } from "api/types"; + export interface ConnectRequestParams { remoteUrl: string; gitProfile?: { @@ -7,7 +9,7 @@ export interface ConnectRequestParams { }; } -export interface ConnectResponse { +export interface ConnectResponseData { id: string; baseId: string; gitApplicationMetadata: { @@ -22,3 +24,5 @@ export interface ConnectResponse { repoName: string; }; } + +export type ConnectResponse = ApiResponse; diff --git a/app/client/src/git/sagas/commitSaga.ts b/app/client/src/git/sagas/commitSaga.ts new file mode 100644 index 000000000000..f013bf4375e2 --- /dev/null +++ b/app/client/src/git/sagas/commitSaga.ts @@ -0,0 +1,66 @@ +import { captureException } from "@sentry/react"; +import type { CommitInitPayload } from "../actions/commitActions"; +import { GitArtifactType, GitErrorCodes } from "../constants/enums"; +import commitRequest from "../requests/commitRequest"; +import type { CommitResponse } from "../requests/commitRequest.types"; +import { gitArtifactActions } from "../store/gitArtifactSlice"; +import type { GitArtifactPayloadAction } from "../types"; +import { call, put } from "redux-saga/effects"; + +// internal dependencies +import { validateResponse } from "sagas/ErrorSagas"; + +export default function* commitSaga( + action: GitArtifactPayloadAction, +) { + const { artifactType, baseArtifactId } = action.payload; + const basePayload = { artifactType, baseArtifactId }; + let response: CommitResponse | undefined; + + try { + const params = { + commitMessage: action.payload.commitMessage, + doPush: action.payload.doPush, + }; + + response = yield call(commitRequest, baseArtifactId, params); + + const isValidResponse: boolean = yield validateResponse(response, false); + + if (isValidResponse) { + yield put(gitArtifactActions.commitSuccess(basePayload)); + yield put( + gitArtifactActions.fetchStatusInit({ + ...basePayload, + compareRemote: true, + }), + ); + + if (artifactType === GitArtifactType.Application) { + // ! case for updating lastDeployedAt in application manually? + } + } + } catch (error) { + if ( + GitErrorCodes.REPO_LIMIT_REACHED === response?.responseMeta?.error?.code + ) { + yield put( + gitArtifactActions.toggleRepoLimitErrorModal({ + ...basePayload, + open: true, + }), + ); + } + + if (response?.responseMeta?.error?.message) { + yield put( + gitArtifactActions.connectError({ + ...basePayload, + error: response.responseMeta.error.message, + }), + ); + } else { + captureException(error); + } + } +} diff --git a/app/client/src/git/sagas/connectSaga.ts b/app/client/src/git/sagas/connectSaga.ts new file mode 100644 index 000000000000..049c6620a5cb --- /dev/null +++ b/app/client/src/git/sagas/connectSaga.ts @@ -0,0 +1,78 @@ +import { gitArtifactActions } from "../store/gitArtifactSlice"; +import connectRequest from "../requests/connectRequest"; +import type { ConnectResponse } from "../requests/connectRequest.types"; +import { GitArtifactType, GitErrorCodes } from "../constants/enums"; +import { GIT_BRANCH_QUERY_KEY } from "../constants/misc"; +import type { GitArtifactPayloadAction } from "../types"; +import type { ConnectInitPayload } from "../actions/connectActions"; + +import { call, put } from "redux-saga/effects"; + +// Internal dependencies +import { validateResponse } from "sagas/ErrorSagas"; +import { fetchPageAction } from "actions/pageActions"; +import history from "utils/history"; +import { captureException } from "@sentry/react"; + +export default function* connectSaga( + action: GitArtifactPayloadAction, +) { + const { artifactType, baseArtifactId } = action.payload; + const basePayload = { artifactType, baseArtifactId }; + + let response: ConnectResponse | undefined; + + try { + const params = { + remoteUrl: action.payload.remoteUrl, + gitProfile: action.payload.gitProfile, + }; + + response = yield call(connectRequest, baseArtifactId, params); + + const isValidResponse: boolean = yield validateResponse(response, false); + + if (response && isValidResponse) { + yield put(gitArtifactActions.connectSuccess(basePayload)); + + // needs to happen only when artifactType is application + if (artifactType === GitArtifactType.Application) { + const { branchedPageId } = action.payload; + + if (branchedPageId) { + yield put(fetchPageAction(branchedPageId)); + } + + const branch = response.data.gitApplicationMetadata.branchName; + const url = new URL(window.location.href); + + url.searchParams.set(GIT_BRANCH_QUERY_KEY, encodeURIComponent(branch)); + url.toString().slice(url.origin.length); + history.replace(url); + // ! case for updating lastDeployedAt in application manually? + } + } + } catch (error) { + if ( + GitErrorCodes.REPO_LIMIT_REACHED === response?.responseMeta?.error?.code + ) { + yield put( + gitArtifactActions.toggleRepoLimitErrorModal({ + ...basePayload, + open: true, + }), + ); + } + + if (response?.responseMeta?.error?.message) { + yield put( + gitArtifactActions.connectError({ + ...basePayload, + error: response.responseMeta.error.message, + }), + ); + } else { + captureException(error); + } + } +} diff --git a/app/client/src/git/sagas/index.ts b/app/client/src/git/sagas/index.ts new file mode 100644 index 000000000000..ebc10506a189 --- /dev/null +++ b/app/client/src/git/sagas/index.ts @@ -0,0 +1,11 @@ +import { gitArtifactActions } from "git/store/gitArtifactSlice"; +import { all, takeLatest } from "redux-saga/effects"; +import connectSaga from "./connectSaga"; +import commitSaga from "./commitSaga"; + +export function* gitSagas() { + yield all([ + takeLatest(gitArtifactActions.connectInit, connectSaga), + takeLatest(gitArtifactActions.commitInit, commitSaga), + ]); +} diff --git a/app/client/src/git/store/gitArtifactSlice.ts b/app/client/src/git/store/gitArtifactSlice.ts index 73b50f2c19e9..bc11c17b6edc 100644 --- a/app/client/src/git/store/gitArtifactSlice.ts +++ b/app/client/src/git/store/gitArtifactSlice.ts @@ -32,11 +32,12 @@ import { pullInitAction, pullSuccessAction, } from "../actions/pullActions"; +import { toggleRepoLimitErrorModalAction } from "../actions/repoLimitErrorModalActions"; const initialState: GitArtifactReduxState = {}; export const gitArtifactSlice = createSlice({ - name: "gitArtifact", + name: "git", initialState, reducers: { mount: mountAction, @@ -59,9 +60,10 @@ export const gitArtifactSlice = createSlice({ pullInit: pullInitAction, pullSuccess: pullSuccessAction, pullError: pullErrorAction, + toggleRepoLimitErrorModal: toggleRepoLimitErrorModalAction, }, }); export const gitArtifactActions = gitArtifactSlice.actions; -export default gitArtifactSlice.reducer; +export const gitArtifactReducer = gitArtifactSlice.reducer; diff --git a/app/client/src/git/types.ts b/app/client/src/git/types.ts index af349c168fb8..3962c3665e94 100644 --- a/app/client/src/git/types.ts +++ b/app/client/src/git/types.ts @@ -83,6 +83,9 @@ export interface GitSingleArtifactUIReduxState { open: boolean; tab: keyof typeof GitSettingsTab; }; + repoLimitErrorModal: { + open: boolean; + }; } export interface GitSingleArtifactReduxState { ui: GitSingleArtifactUIReduxState; @@ -98,9 +101,17 @@ export interface GitArtifactBasePayload { baseArtifactId: string; } +export interface GitArtifactErrorPayload { + error: string; +} + export type GitArtifactPayloadAction> = PayloadAction; -export type GitArtifactErrorPayloadAction = GitArtifactPayloadAction<{ - error: string; -}>; +export type GitArtifactSuccessPayloadAction = + GitArtifactPayloadAction<{ + responseData: T; + }>; + +export type GitArtifactErrorPayloadAction = + GitArtifactPayloadAction; From d7e6c7949c2731263a49a8d5d7599f75f0967a4f Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Sat, 7 Dec 2024 17:27:20 +0800 Subject: [PATCH 006/143] chore: adding global profile and config redux slice --- app/client/src/git/actions/commitActions.ts | 9 ++-- app/client/src/git/actions/connectActions.ts | 4 +- .../git/actions/fetchGlobalConfigActions.ts | 38 ----------------- .../git/actions/fetchGlobalProfileActions.ts | 36 ++++++++++++++++ .../helpers/createSingleArtifactAction.ts | 3 +- .../helpers/singleArtifactInitialState.ts | 9 ---- .../git/actions/updateGlobalConfigActions.ts | 30 -------------- .../git/actions/updateGlobalProfileActions.ts | 29 +++++++++++++ .../git/requests/fetchGlobalConfigRequest.ts | 10 ----- .../fetchGlobalConfigRequest.types.ts | 4 -- .../git/requests/fetchGlobalProfileRequest.ts | 8 ++++ .../fetchGlobalProfileRequest.types.ts | 9 ++++ .../git/requests/updateGlobalConfigRequest.ts | 13 ------ .../requests/updateGlobalProfileRequest.ts | 13 ++++++ ...ts => updateGlobalProfileRequest.types.ts} | 4 +- .../src/git/sagas/fetchGlobalProfileSaga.ts | 36 ++++++++++++++++ app/client/src/git/sagas/index.ts | 3 ++ app/client/src/git/store/gitArtifactSlice.ts | 2 +- app/client/src/git/store/gitConfigSlice.ts | 41 +++++++++++++++++++ app/client/src/git/store/index.ts | 8 ++++ app/client/src/git/types.ts | 29 +++++++------ 21 files changed, 211 insertions(+), 127 deletions(-) delete mode 100644 app/client/src/git/actions/fetchGlobalConfigActions.ts create mode 100644 app/client/src/git/actions/fetchGlobalProfileActions.ts delete mode 100644 app/client/src/git/actions/updateGlobalConfigActions.ts create mode 100644 app/client/src/git/actions/updateGlobalProfileActions.ts delete mode 100644 app/client/src/git/requests/fetchGlobalConfigRequest.ts delete mode 100644 app/client/src/git/requests/fetchGlobalConfigRequest.types.ts create mode 100644 app/client/src/git/requests/fetchGlobalProfileRequest.ts create mode 100644 app/client/src/git/requests/fetchGlobalProfileRequest.types.ts delete mode 100644 app/client/src/git/requests/updateGlobalConfigRequest.ts create mode 100644 app/client/src/git/requests/updateGlobalProfileRequest.ts rename app/client/src/git/requests/{updateGlobalConfigRequest.types.ts => updateGlobalProfileRequest.types.ts} (54%) create mode 100644 app/client/src/git/sagas/fetchGlobalProfileSaga.ts create mode 100644 app/client/src/git/store/gitConfigSlice.ts diff --git a/app/client/src/git/actions/commitActions.ts b/app/client/src/git/actions/commitActions.ts index c0f491d2f6b7..eeb80a18984c 100644 --- a/app/client/src/git/actions/commitActions.ts +++ b/app/client/src/git/actions/commitActions.ts @@ -1,5 +1,5 @@ import { createSingleArtifactAction } from "./helpers/createSingleArtifactAction"; -import type { GitArtifactErrorPayloadAction } from "../types"; +import type { GitAsyncErrorPayload } from "../types"; import type { CommitRequestParams } from "git/requests/commitRequest.types"; export interface CommitInitPayload extends CommitRequestParams {} @@ -19,13 +19,12 @@ export const commitSuccessAction = createSingleArtifactAction((state) => { return state; }); -export const commitErrorAction = createSingleArtifactAction( - (state, action: GitArtifactErrorPayloadAction) => { +export const commitErrorAction = + createSingleArtifactAction((state, action) => { const { error } = action.payload; state.apiResponses.commit.loading = false; state.apiResponses.commit.error = error; return state; - }, -); + }); diff --git a/app/client/src/git/actions/connectActions.ts b/app/client/src/git/actions/connectActions.ts index ab67587075fc..5a45872ed2a1 100644 --- a/app/client/src/git/actions/connectActions.ts +++ b/app/client/src/git/actions/connectActions.ts @@ -1,5 +1,5 @@ import { createSingleArtifactAction } from "./helpers/createSingleArtifactAction"; -import type { GitArtifactErrorPayload } from "../types"; +import type { GitAsyncErrorPayload } from "../types"; import type { ConnectRequestParams } from "git/requests/connectRequest.types"; export interface ConnectInitPayload extends ConnectRequestParams { @@ -22,7 +22,7 @@ export const connectSuccessAction = createSingleArtifactAction((state) => { }); export const connectErrorAction = - createSingleArtifactAction((state, action) => { + createSingleArtifactAction((state, action) => { const { error } = action.payload; state.apiResponses.connect.loading = false; diff --git a/app/client/src/git/actions/fetchGlobalConfigActions.ts b/app/client/src/git/actions/fetchGlobalConfigActions.ts deleted file mode 100644 index e30f80644b92..000000000000 --- a/app/client/src/git/actions/fetchGlobalConfigActions.ts +++ /dev/null @@ -1,38 +0,0 @@ -import type { - GitArtifactPayloadAction, - GitArtifactErrorPayloadAction, - GitGlobalConfig, -} from "../types"; -import { createSingleArtifactAction } from "./helpers/createSingleArtifactAction"; - -export const fetchGlobalConfigInitAction = createSingleArtifactAction( - (state) => { - state.apiResponses.globalConfig.loading = true; - state.apiResponses.globalConfig.error = null; - - return state; - }, -); - -export const fetchGlobalConfigSuccessAction = createSingleArtifactAction( - ( - state, - action: GitArtifactPayloadAction<{ globalConfig: GitGlobalConfig }>, - ) => { - state.apiResponses.globalConfig.loading = false; - state.apiResponses.globalConfig.value = action.payload.globalConfig; - - return state; - }, -); - -export const fetchGlobalConfigErrorAction = createSingleArtifactAction( - (state, action: GitArtifactErrorPayloadAction) => { - const { error } = action.payload; - - state.apiResponses.globalConfig.loading = false; - state.apiResponses.globalConfig.error = error; - - return state; - }, -); diff --git a/app/client/src/git/actions/fetchGlobalProfileActions.ts b/app/client/src/git/actions/fetchGlobalProfileActions.ts new file mode 100644 index 000000000000..7cfb2390b021 --- /dev/null +++ b/app/client/src/git/actions/fetchGlobalProfileActions.ts @@ -0,0 +1,36 @@ +import type { FetchGlobalProfileResponseData } from "git/requests/fetchGlobalProfileRequest.types"; +import type { + GitAsyncSuccessPayload, + GitAsyncErrorPayload, + GitConfigReduxState, +} from "../types"; +import type { PayloadAction } from "@reduxjs/toolkit"; + +export const fetchGlobalProfileInitAction = (state: GitConfigReduxState) => { + state.globalProfile.loading = true; + state.globalProfile.error = null; + + return state; +}; + +export const fetchGlobalProfileSuccessAction = ( + state: GitConfigReduxState, + action: PayloadAction>, +) => { + state.globalProfile.loading = false; + state.globalProfile.value = action.payload.responseData; + + return state; +}; + +export const fetchGlobalProfileErrorAction = ( + state: GitConfigReduxState, + action: PayloadAction, +) => { + const { error } = action.payload; + + state.globalProfile.loading = false; + state.globalProfile.error = error; + + return state; +}; diff --git a/app/client/src/git/actions/helpers/createSingleArtifactAction.ts b/app/client/src/git/actions/helpers/createSingleArtifactAction.ts index 2f71dee8ce11..f983f1a27190 100644 --- a/app/client/src/git/actions/helpers/createSingleArtifactAction.ts +++ b/app/client/src/git/actions/helpers/createSingleArtifactAction.ts @@ -1,4 +1,5 @@ import type { + GitArtifactBasePayload, GitArtifactPayloadAction, GitArtifactReduxState, GitSingleArtifactReduxState, @@ -10,7 +11,7 @@ type SingleArtifactStateCb = ( action: GitArtifactPayloadAction, ) => GitSingleArtifactReduxState; -export const createSingleArtifactAction = ( +export const createSingleArtifactAction = ( singleArtifactStateCb: SingleArtifactStateCb, ) => { return ( diff --git a/app/client/src/git/actions/helpers/singleArtifactInitialState.ts b/app/client/src/git/actions/helpers/singleArtifactInitialState.ts index d62c3f65a01e..4e8d75aab493 100644 --- a/app/client/src/git/actions/helpers/singleArtifactInitialState.ts +++ b/app/client/src/git/actions/helpers/singleArtifactInitialState.ts @@ -89,20 +89,11 @@ const gitSingleArtifactInitialAPIResponses: GitSingleArtifactAPIResponsesReduxSt loading: false, error: null, }, - globalConfig: { - value: null, - loading: false, - error: null, - }, localConfig: { value: null, loading: false, error: null, }, - updateGlobalConfig: { - loading: false, - error: null, - }, updateLocalConfig: { loading: false, error: null, diff --git a/app/client/src/git/actions/updateGlobalConfigActions.ts b/app/client/src/git/actions/updateGlobalConfigActions.ts deleted file mode 100644 index a4990e2996b2..000000000000 --- a/app/client/src/git/actions/updateGlobalConfigActions.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { createSingleArtifactAction } from "./helpers/createSingleArtifactAction"; -import type { GitArtifactErrorPayloadAction } from "../types"; - -export const updateGlobalConfigInitAction = createSingleArtifactAction( - (state) => { - state.apiResponses.updateGlobalConfig.loading = true; - state.apiResponses.updateGlobalConfig.error = null; - - return state; - }, -); - -export const updateGlobalConfigSuccessAction = createSingleArtifactAction( - (state) => { - state.apiResponses.updateGlobalConfig.loading = false; - - return state; - }, -); - -export const updateGlobalConfigErrorAction = createSingleArtifactAction( - (state, action: GitArtifactErrorPayloadAction) => { - const { error } = action.payload; - - state.apiResponses.updateGlobalConfig.loading = false; - state.apiResponses.updateGlobalConfig.error = error; - - return state; - }, -); diff --git a/app/client/src/git/actions/updateGlobalProfileActions.ts b/app/client/src/git/actions/updateGlobalProfileActions.ts new file mode 100644 index 000000000000..d3341274aa14 --- /dev/null +++ b/app/client/src/git/actions/updateGlobalProfileActions.ts @@ -0,0 +1,29 @@ +import type { GitAsyncErrorPayload, GitConfigReduxState } from "../types"; +import type { PayloadAction } from "@reduxjs/toolkit"; + +export const updateGlobalProfileInitAction = (state: GitConfigReduxState) => { + state.updateGlobalProfile.loading = true; + state.updateGlobalProfile.error = null; + + return state; +}; + +export const updateGlobalProfileSuccessAction = ( + state: GitConfigReduxState, +) => { + state.updateGlobalProfile.loading = false; + + return state; +}; + +export const updateGlobalProfileErrorAction = ( + state: GitConfigReduxState, + action: PayloadAction, +) => { + const { error } = action.payload; + + state.updateGlobalProfile.loading = false; + state.updateGlobalProfile.error = error; + + return state; +}; diff --git a/app/client/src/git/requests/fetchGlobalConfigRequest.ts b/app/client/src/git/requests/fetchGlobalConfigRequest.ts deleted file mode 100644 index 32b048c0bbf0..000000000000 --- a/app/client/src/git/requests/fetchGlobalConfigRequest.ts +++ /dev/null @@ -1,10 +0,0 @@ -import Api from "api/Api"; -import { GIT_BASE_URL } from "./constants"; -import type { AxiosResponse } from "axios"; -import type { FetchGlobalConfigResponse } from "./fetchGlobalConfigRequest.types"; - -export default async function fetchGlobalConfigRequest(): Promise< - AxiosResponse -> { - return Api.get(`${GIT_BASE_URL}/profile/default`); -} diff --git a/app/client/src/git/requests/fetchGlobalConfigRequest.types.ts b/app/client/src/git/requests/fetchGlobalConfigRequest.types.ts deleted file mode 100644 index 1939b2df65fd..000000000000 --- a/app/client/src/git/requests/fetchGlobalConfigRequest.types.ts +++ /dev/null @@ -1,4 +0,0 @@ -export interface FetchGlobalConfigResponse { - authorName: string; - authorEmail: string; -} diff --git a/app/client/src/git/requests/fetchGlobalProfileRequest.ts b/app/client/src/git/requests/fetchGlobalProfileRequest.ts new file mode 100644 index 000000000000..bd9c200caffd --- /dev/null +++ b/app/client/src/git/requests/fetchGlobalProfileRequest.ts @@ -0,0 +1,8 @@ +import Api from "api/Api"; +import { GIT_BASE_URL } from "./constants"; +import type { AxiosPromise } from "axios"; +import type { FetchGlobalProfileResponse } from "./fetchGlobalProfileRequest.types"; + +export default async function fetchGlobalProfileRequest(): AxiosPromise { + return Api.get(`${GIT_BASE_URL}/profile/default`); +} diff --git a/app/client/src/git/requests/fetchGlobalProfileRequest.types.ts b/app/client/src/git/requests/fetchGlobalProfileRequest.types.ts new file mode 100644 index 000000000000..fb146f133343 --- /dev/null +++ b/app/client/src/git/requests/fetchGlobalProfileRequest.types.ts @@ -0,0 +1,9 @@ +import type { ApiResponse } from "api/types"; + +export interface FetchGlobalProfileResponseData { + authorName: string; + authorEmail: string; +} + +export type FetchGlobalProfileResponse = + ApiResponse; diff --git a/app/client/src/git/requests/updateGlobalConfigRequest.ts b/app/client/src/git/requests/updateGlobalConfigRequest.ts deleted file mode 100644 index a20cb5beb877..000000000000 --- a/app/client/src/git/requests/updateGlobalConfigRequest.ts +++ /dev/null @@ -1,13 +0,0 @@ -import type { AxiosResponse } from "axios"; -import type { - UpdateGlobalConfigRequestParams, - UpdateGlobalConfigResponse, -} from "./updateGlobalConfigRequest.types"; -import Api from "api/Api"; -import { GIT_BASE_URL } from "./constants"; - -export default async function updateGlobalConfigRequest( - params: UpdateGlobalConfigRequestParams, -): Promise> { - return Api.post(`${GIT_BASE_URL}/profile/default`, params); -} diff --git a/app/client/src/git/requests/updateGlobalProfileRequest.ts b/app/client/src/git/requests/updateGlobalProfileRequest.ts new file mode 100644 index 000000000000..647ff15426f7 --- /dev/null +++ b/app/client/src/git/requests/updateGlobalProfileRequest.ts @@ -0,0 +1,13 @@ +import type { AxiosResponse } from "axios"; +import type { + UpdateGlobalProfileRequestParams, + UpdateGlobalProfileResponse, +} from "./updateGlobalProfileRequest.types"; +import Api from "api/Api"; +import { GIT_BASE_URL } from "./constants"; + +export default async function updateGlobalProfileRequest( + params: UpdateGlobalProfileRequestParams, +): Promise> { + return Api.post(`${GIT_BASE_URL}/profile/default`, params); +} diff --git a/app/client/src/git/requests/updateGlobalConfigRequest.types.ts b/app/client/src/git/requests/updateGlobalProfileRequest.types.ts similarity index 54% rename from app/client/src/git/requests/updateGlobalConfigRequest.types.ts rename to app/client/src/git/requests/updateGlobalProfileRequest.types.ts index 10116f7dc991..29f49f519221 100644 --- a/app/client/src/git/requests/updateGlobalConfigRequest.types.ts +++ b/app/client/src/git/requests/updateGlobalProfileRequest.types.ts @@ -1,9 +1,9 @@ -export interface UpdateGlobalConfigRequestParams { +export interface UpdateGlobalProfileRequestParams { authorName: string; authorEmail: string; } -export interface UpdateGlobalConfigResponse { +export interface UpdateGlobalProfileResponse { default: { authorName: string; authorEmail: string; diff --git a/app/client/src/git/sagas/fetchGlobalProfileSaga.ts b/app/client/src/git/sagas/fetchGlobalProfileSaga.ts new file mode 100644 index 000000000000..ae8f91954437 --- /dev/null +++ b/app/client/src/git/sagas/fetchGlobalProfileSaga.ts @@ -0,0 +1,36 @@ +import { captureException } from "@sentry/react"; +import { call, put } from "redux-saga/effects"; +import fetchGlobalProfileRequest from "../requests/fetchGlobalProfileRequest"; +import type { FetchGlobalProfileResponse } from "../requests/fetchGlobalProfileRequest.types"; +import { gitConfigActions } from "../store/gitConfigSlice"; + +// internal dependencies +import { validateResponse } from "sagas/ErrorSagas"; + +export default function* fetchGlobalProfileSaga() { + let response: FetchGlobalProfileResponse | undefined; + + try { + response = yield call(fetchGlobalProfileRequest); + + const isValidResponse: boolean = yield validateResponse(response); + + if (response && isValidResponse) { + yield put( + gitConfigActions.fetchGlobalProfileSuccess({ + responseData: response.data, + }), + ); + } + } catch (error) { + if (response?.responseMeta?.error?.message) { + yield put( + gitConfigActions.fetchGlobalProfileError({ + error: response?.responseMeta?.error?.message, + }), + ); + } else { + captureException(error); + } + } +} diff --git a/app/client/src/git/sagas/index.ts b/app/client/src/git/sagas/index.ts index ebc10506a189..1a888e31eab0 100644 --- a/app/client/src/git/sagas/index.ts +++ b/app/client/src/git/sagas/index.ts @@ -2,10 +2,13 @@ import { gitArtifactActions } from "git/store/gitArtifactSlice"; import { all, takeLatest } from "redux-saga/effects"; import connectSaga from "./connectSaga"; import commitSaga from "./commitSaga"; +import { gitConfigActions } from "git/store/gitConfigSlice"; +import fetchGlobalProfileSaga from "./fetchGlobalProfileSaga"; export function* gitSagas() { yield all([ takeLatest(gitArtifactActions.connectInit, connectSaga), takeLatest(gitArtifactActions.commitInit, commitSaga), + takeLatest(gitConfigActions.fetchGlobalProfileInit, fetchGlobalProfileSaga), ]); } diff --git a/app/client/src/git/store/gitArtifactSlice.ts b/app/client/src/git/store/gitArtifactSlice.ts index bc11c17b6edc..789ba2cefc5b 100644 --- a/app/client/src/git/store/gitArtifactSlice.ts +++ b/app/client/src/git/store/gitArtifactSlice.ts @@ -37,7 +37,7 @@ import { toggleRepoLimitErrorModalAction } from "../actions/repoLimitErrorModalA const initialState: GitArtifactReduxState = {}; export const gitArtifactSlice = createSlice({ - name: "git", + name: "git/artifact", initialState, reducers: { mount: mountAction, diff --git a/app/client/src/git/store/gitConfigSlice.ts b/app/client/src/git/store/gitConfigSlice.ts new file mode 100644 index 000000000000..14cf0971b643 --- /dev/null +++ b/app/client/src/git/store/gitConfigSlice.ts @@ -0,0 +1,41 @@ +import { createSlice } from "@reduxjs/toolkit"; +import { + fetchGlobalProfileErrorAction, + fetchGlobalProfileInitAction, + fetchGlobalProfileSuccessAction, +} from "git/actions/fetchGlobalProfileActions"; +import { + updateGlobalProfileErrorAction, + updateGlobalProfileInitAction, + updateGlobalProfileSuccessAction, +} from "git/actions/updateGlobalProfileActions"; +import type { GitConfigReduxState } from "git/types"; + +const initialState: GitConfigReduxState = { + globalProfile: { + value: null, + loading: false, + error: null, + }, + updateGlobalProfile: { + loading: false, + error: null, + }, +}; + +export const gitConfigSlice = createSlice({ + name: "git/config", + initialState, + reducers: { + fetchGlobalProfileInit: fetchGlobalProfileInitAction, + fetchGlobalProfileSuccess: fetchGlobalProfileSuccessAction, + fetchGlobalProfileError: fetchGlobalProfileErrorAction, + updateGlobalProfileInit: updateGlobalProfileInitAction, + updateGlobalProfileSuccess: updateGlobalProfileSuccessAction, + updateGlobalProfileError: updateGlobalProfileErrorAction, + }, +}); + +export const gitConfigActions = gitConfigSlice.actions; + +export const gitConfigReducer = gitConfigSlice.reducer; diff --git a/app/client/src/git/store/index.ts b/app/client/src/git/store/index.ts index e69de29bb2d1..f5337e564f97 100644 --- a/app/client/src/git/store/index.ts +++ b/app/client/src/git/store/index.ts @@ -0,0 +1,8 @@ +import { combineReducers } from "@reduxjs/toolkit"; +import { gitArtifactReducer } from "./gitArtifactSlice"; +import { gitConfigReducer } from "./gitConfigSlice"; + +export const gitReducer = combineReducers({ + artifacts: gitArtifactReducer, + config: gitConfigReducer, +}); diff --git a/app/client/src/git/types.ts b/app/client/src/git/types.ts index 3962c3665e94..3b943cd3d65c 100644 --- a/app/client/src/git/types.ts +++ b/app/client/src/git/types.ts @@ -6,6 +6,7 @@ import type { GitOpsTab, GitSettingsTab, } from "./constants/enums"; +import type { FetchGlobalProfileResponseData } from "./requests/fetchGlobalProfileRequest.types"; // These will be updated when contracts are finalized export type GitMetadata = Record; @@ -16,8 +17,6 @@ export type GitStatus = Record; export type GitMergeStatus = Record; -export type GitGlobalConfig = Record; - export type GitLocalConfig = Record; export type GitProtectedBranches = Record; @@ -49,9 +48,7 @@ export interface GitSingleArtifactAPIResponsesReduxState { checkoutBranch: AsyncStateWithoutValue; createBranch: AsyncStateWithoutValue; deleteBranch: AsyncStateWithoutValue; - globalConfig: AsyncState; localConfig: AsyncState; - updateGlobalConfig: AsyncStateWithoutValue; updateLocalConfig: AsyncStateWithoutValue; disconnect: AsyncStateWithoutValue; protectedBranches: AsyncState; @@ -96,22 +93,30 @@ export interface GitArtifactReduxState { [key: string]: Record; } +export interface GitConfigReduxState { + globalProfile: AsyncState; + updateGlobalProfile: AsyncStateWithoutValue; +} + export interface GitArtifactBasePayload { artifactType: keyof typeof GitArtifactType; baseArtifactId: string; } -export interface GitArtifactErrorPayload { +export interface GitAsyncErrorPayload { error: string; } -export type GitArtifactPayloadAction> = - PayloadAction; +export interface GitAsyncSuccessPayload { + responseData: T; +} + +export type GitArtifactPayload> = + GitArtifactBasePayload & T; -export type GitArtifactSuccessPayloadAction = - GitArtifactPayloadAction<{ - responseData: T; - }>; +export type GitArtifactPayloadAction> = PayloadAction< + GitArtifactPayload +>; export type GitArtifactErrorPayloadAction = - GitArtifactPayloadAction; + GitArtifactPayloadAction; From 02e128b037ba03cdb612958789f39eb092eb23a3 Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Sat, 7 Dec 2024 17:51:42 +0800 Subject: [PATCH 007/143] chore: adding saga for git profile update --- .../git/actions/updateGlobalProfileActions.ts | 4 +++ .../updateGlobalProfileRequest.types.ts | 7 +++- app/client/src/git/sagas/commitSaga.ts | 17 ++++----- app/client/src/git/sagas/connectSaga.ts | 17 ++++----- .../src/git/sagas/fetchGlobalProfileSaga.ts | 15 +++----- .../src/git/sagas/updateGlobalProfileSaga.ts | 35 +++++++++++++++++++ 6 files changed, 62 insertions(+), 33 deletions(-) create mode 100644 app/client/src/git/sagas/updateGlobalProfileSaga.ts diff --git a/app/client/src/git/actions/updateGlobalProfileActions.ts b/app/client/src/git/actions/updateGlobalProfileActions.ts index d3341274aa14..58dcd8570367 100644 --- a/app/client/src/git/actions/updateGlobalProfileActions.ts +++ b/app/client/src/git/actions/updateGlobalProfileActions.ts @@ -1,6 +1,10 @@ +import type { UpdateGlobalProfileRequestParams } from "git/requests/updateGlobalProfileRequest.types"; import type { GitAsyncErrorPayload, GitConfigReduxState } from "../types"; import type { PayloadAction } from "@reduxjs/toolkit"; +export interface UpdateGlobalProfileInitPayload + extends UpdateGlobalProfileRequestParams {} + export const updateGlobalProfileInitAction = (state: GitConfigReduxState) => { state.updateGlobalProfile.loading = true; state.updateGlobalProfile.error = null; diff --git a/app/client/src/git/requests/updateGlobalProfileRequest.types.ts b/app/client/src/git/requests/updateGlobalProfileRequest.types.ts index 29f49f519221..c66e20fc7c20 100644 --- a/app/client/src/git/requests/updateGlobalProfileRequest.types.ts +++ b/app/client/src/git/requests/updateGlobalProfileRequest.types.ts @@ -1,11 +1,16 @@ +import type { ApiResponse } from "api/types"; + export interface UpdateGlobalProfileRequestParams { authorName: string; authorEmail: string; } -export interface UpdateGlobalProfileResponse { +export interface UpdateGlobalProfileResponseData { default: { authorName: string; authorEmail: string; }; } + +export type UpdateGlobalProfileResponse = + ApiResponse; diff --git a/app/client/src/git/sagas/commitSaga.ts b/app/client/src/git/sagas/commitSaga.ts index f013bf4375e2..bf9aaddcb47f 100644 --- a/app/client/src/git/sagas/commitSaga.ts +++ b/app/client/src/git/sagas/commitSaga.ts @@ -1,4 +1,3 @@ -import { captureException } from "@sentry/react"; import type { CommitInitPayload } from "../actions/commitActions"; import { GitArtifactType, GitErrorCodes } from "../constants/enums"; import commitRequest from "../requests/commitRequest"; @@ -52,15 +51,11 @@ export default function* commitSaga( ); } - if (response?.responseMeta?.error?.message) { - yield put( - gitArtifactActions.connectError({ - ...basePayload, - error: response.responseMeta.error.message, - }), - ); - } else { - captureException(error); - } + yield put( + gitArtifactActions.connectError({ + ...basePayload, + error: error as string, + }), + ); } } diff --git a/app/client/src/git/sagas/connectSaga.ts b/app/client/src/git/sagas/connectSaga.ts index 049c6620a5cb..3fe07e4fd03c 100644 --- a/app/client/src/git/sagas/connectSaga.ts +++ b/app/client/src/git/sagas/connectSaga.ts @@ -12,7 +12,6 @@ import { call, put } from "redux-saga/effects"; import { validateResponse } from "sagas/ErrorSagas"; import { fetchPageAction } from "actions/pageActions"; import history from "utils/history"; -import { captureException } from "@sentry/react"; export default function* connectSaga( action: GitArtifactPayloadAction, @@ -64,15 +63,11 @@ export default function* connectSaga( ); } - if (response?.responseMeta?.error?.message) { - yield put( - gitArtifactActions.connectError({ - ...basePayload, - error: response.responseMeta.error.message, - }), - ); - } else { - captureException(error); - } + yield put( + gitArtifactActions.connectError({ + ...basePayload, + error: error as string, + }), + ); } } diff --git a/app/client/src/git/sagas/fetchGlobalProfileSaga.ts b/app/client/src/git/sagas/fetchGlobalProfileSaga.ts index ae8f91954437..0443703ad0d5 100644 --- a/app/client/src/git/sagas/fetchGlobalProfileSaga.ts +++ b/app/client/src/git/sagas/fetchGlobalProfileSaga.ts @@ -1,4 +1,3 @@ -import { captureException } from "@sentry/react"; import { call, put } from "redux-saga/effects"; import fetchGlobalProfileRequest from "../requests/fetchGlobalProfileRequest"; import type { FetchGlobalProfileResponse } from "../requests/fetchGlobalProfileRequest.types"; @@ -23,14 +22,10 @@ export default function* fetchGlobalProfileSaga() { ); } } catch (error) { - if (response?.responseMeta?.error?.message) { - yield put( - gitConfigActions.fetchGlobalProfileError({ - error: response?.responseMeta?.error?.message, - }), - ); - } else { - captureException(error); - } + yield put( + gitConfigActions.fetchGlobalProfileError({ + error: error as string, + }), + ); } } diff --git a/app/client/src/git/sagas/updateGlobalProfileSaga.ts b/app/client/src/git/sagas/updateGlobalProfileSaga.ts new file mode 100644 index 000000000000..0440295196e6 --- /dev/null +++ b/app/client/src/git/sagas/updateGlobalProfileSaga.ts @@ -0,0 +1,35 @@ +import type { PayloadAction } from "@reduxjs/toolkit"; +import { call, put } from "redux-saga/effects"; +import type { UpdateGlobalProfileInitPayload } from "../actions/updateGlobalProfileActions"; +import updateGlobalProfileRequest from "../requests/updateGlobalProfileRequest"; +import type { UpdateGlobalProfileResponse } from "../requests/updateGlobalProfileRequest.types"; +import { gitConfigActions } from "../store/gitConfigSlice"; + +// internal dependencies +import { validateResponse } from "sagas/ErrorSagas"; + +export default function* updateGlobalGitConfig( + action: PayloadAction, +) { + let response: UpdateGlobalProfileResponse | undefined; + + try { + const params = { + authorName: action.payload.authorName, + authorEmail: action.payload.authorEmail, + }; + + response = yield call(updateGlobalProfileRequest, params); + + const isValidResponse: boolean = yield validateResponse(response, true); + + if (response && isValidResponse) { + yield put(gitConfigActions.updateGlobalProfileSuccess()); + yield put(gitConfigActions.fetchGlobalProfileInit()); + } + } catch (error) { + yield put( + gitConfigActions.updateGlobalProfileError({ error: error as string }), + ); + } +} From 3218b3acbd2d3cb51b6ee95a6b2736efae2de946 Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Sat, 7 Dec 2024 18:47:19 +0800 Subject: [PATCH 008/143] chore: adding fetch branches saga --- .../src/git/actions/fetchBranchesActions.ts | 42 ++++++++++--------- .../src/git/requests/fetchBranchesRequest.ts | 11 ++--- .../requests/fetchBranchesRequest.types.ts | 6 ++- app/client/src/git/sagas/fetchBranchesSaga.ts | 40 ++++++++++++++++++ app/client/src/git/sagas/index.ts | 2 + app/client/src/git/types.ts | 5 +-- 6 files changed, 77 insertions(+), 29 deletions(-) create mode 100644 app/client/src/git/sagas/fetchBranchesSaga.ts diff --git a/app/client/src/git/actions/fetchBranchesActions.ts b/app/client/src/git/actions/fetchBranchesActions.ts index cd85068f6757..30f71574dc52 100644 --- a/app/client/src/git/actions/fetchBranchesActions.ts +++ b/app/client/src/git/actions/fetchBranchesActions.ts @@ -1,33 +1,35 @@ import type { - GitArtifactPayloadAction, - GitArtifactErrorPayloadAction, - GitBranches, -} from "../types"; + FetchBranchesRequestParams, + FetchBranchesResponseData, +} from "../requests/fetchBranchesRequest.types"; +import type { GitAsyncErrorPayload, GitAsyncSuccessPayload } from "../types"; import { createSingleArtifactAction } from "./helpers/createSingleArtifactAction"; -export const fetchBranchesInitAction = createSingleArtifactAction((state) => { - state.apiResponses.branches.loading = true; - state.apiResponses.branches.error = null; +export interface FetchBranchesInitPayload extends FetchBranchesRequestParams {} - return state; -}); - -export const fetchBranchesSuccessAction = createSingleArtifactAction( - (state, action: GitArtifactPayloadAction<{ branches: GitBranches }>) => { - state.apiResponses.branches.loading = false; - state.apiResponses.branches.value = action.payload.branches; +export const fetchBranchesInitAction = + createSingleArtifactAction((state) => { + state.apiResponses.branches.loading = true; + state.apiResponses.branches.error = null; return state; - }, -); + }); + +export const fetchBranchesSuccessAction = createSingleArtifactAction< + GitAsyncSuccessPayload +>((state, action) => { + state.apiResponses.branches.loading = false; + state.apiResponses.branches.value = action.payload.responseData; + + return state; +}); -export const fetchBranchesErrorAction = createSingleArtifactAction( - (state, action: GitArtifactErrorPayloadAction) => { +export const fetchBranchesErrorAction = + createSingleArtifactAction((state, action) => { const { error } = action.payload; state.apiResponses.branches.loading = false; state.apiResponses.branches.error = error; return state; - }, -); + }); diff --git a/app/client/src/git/requests/fetchBranchesRequest.ts b/app/client/src/git/requests/fetchBranchesRequest.ts index 90fdbf73d94a..6dd616e9b0fc 100644 --- a/app/client/src/git/requests/fetchBranchesRequest.ts +++ b/app/client/src/git/requests/fetchBranchesRequest.ts @@ -4,18 +4,19 @@ import type { FetchBranchesRequestParams, FetchBranchesResponse, } from "./fetchBranchesRequest.types"; -import type { AxiosResponse } from "axios"; +import type { AxiosPromise } from "axios"; export default async function fetchBranchesRequest( branchedApplicationId: string, - params?: FetchBranchesRequestParams, -): Promise> { + params: FetchBranchesRequestParams, +): AxiosPromise { const queryParams = {} as FetchBranchesRequestParams; - if (params?.pruneBranches) queryParams.pruneBranches = true; + if (params.pruneBranches) queryParams.pruneBranches = true; return Api.get( `${GIT_BASE_URL}/branch/app/${branchedApplicationId}`, - queryParams, + undefined, + { params: queryParams }, ); } diff --git a/app/client/src/git/requests/fetchBranchesRequest.types.ts b/app/client/src/git/requests/fetchBranchesRequest.types.ts index e86e545b309e..dadab374a03b 100644 --- a/app/client/src/git/requests/fetchBranchesRequest.types.ts +++ b/app/client/src/git/requests/fetchBranchesRequest.types.ts @@ -1,3 +1,5 @@ +import type { ApiResponse } from "api/ApiResponses"; + export interface FetchBranchesRequestParams { pruneBranches: boolean; } @@ -8,4 +10,6 @@ interface SingleBranch { default: boolean; } -export type FetchBranchesResponse = SingleBranch[]; +export type FetchBranchesResponseData = SingleBranch[]; + +export type FetchBranchesResponse = ApiResponse; diff --git a/app/client/src/git/sagas/fetchBranchesSaga.ts b/app/client/src/git/sagas/fetchBranchesSaga.ts new file mode 100644 index 000000000000..fb3fa98c4a54 --- /dev/null +++ b/app/client/src/git/sagas/fetchBranchesSaga.ts @@ -0,0 +1,40 @@ +import type { FetchBranchesInitPayload } from "git/actions/fetchBranchesActions"; +import fetchBranchesRequest from "git/requests/fetchBranchesRequest"; +import type { FetchBranchesResponse } from "git/requests/fetchBranchesRequest.types"; +import { gitArtifactActions } from "git/store/gitArtifactSlice"; +import type { GitArtifactPayloadAction } from "git/types"; +import { call, put } from "redux-saga/effects"; +import { validateResponse } from "sagas/ErrorSagas"; + +export default function* fetchBranchesSaga( + action: GitArtifactPayloadAction, +) { + const { artifactType, baseArtifactId } = action.payload; + const basePayload = { artifactType, baseArtifactId }; + let response: FetchBranchesResponse | undefined; + + try { + const params = { + pruneBranches: action.payload.pruneBranches, + }; + + response = yield call(fetchBranchesRequest, baseArtifactId, params); + const isValidResponse: boolean = yield validateResponse(response, false); + + if (response && isValidResponse) { + yield put( + gitArtifactActions.fetchBranchesSuccess({ + ...basePayload, + responseData: response.data, + }), + ); + } + } catch (error) { + yield put( + gitArtifactActions.fetchBranchesError({ + ...basePayload, + error: error as string, + }), + ); + } +} diff --git a/app/client/src/git/sagas/index.ts b/app/client/src/git/sagas/index.ts index 1a888e31eab0..fce28d6014ae 100644 --- a/app/client/src/git/sagas/index.ts +++ b/app/client/src/git/sagas/index.ts @@ -4,11 +4,13 @@ import connectSaga from "./connectSaga"; import commitSaga from "./commitSaga"; import { gitConfigActions } from "git/store/gitConfigSlice"; import fetchGlobalProfileSaga from "./fetchGlobalProfileSaga"; +import fetchBranchesSaga from "./fetchBranchesSaga"; export function* gitSagas() { yield all([ takeLatest(gitArtifactActions.connectInit, connectSaga), takeLatest(gitArtifactActions.commitInit, commitSaga), + takeLatest(gitArtifactActions.fetchBranchesInit, fetchBranchesSaga), takeLatest(gitConfigActions.fetchGlobalProfileInit, fetchGlobalProfileSaga), ]); } diff --git a/app/client/src/git/types.ts b/app/client/src/git/types.ts index 3b943cd3d65c..adbe873756e3 100644 --- a/app/client/src/git/types.ts +++ b/app/client/src/git/types.ts @@ -7,12 +7,11 @@ import type { GitSettingsTab, } from "./constants/enums"; import type { FetchGlobalProfileResponseData } from "./requests/fetchGlobalProfileRequest.types"; +import type { FetchBranchesResponseData } from "./requests/fetchBranchesRequest.types"; // These will be updated when contracts are finalized export type GitMetadata = Record; -export type GitBranches = Record; - export type GitStatus = Record; export type GitMergeStatus = Record; @@ -44,7 +43,7 @@ export interface GitSingleArtifactAPIResponsesReduxState { discard: AsyncStateWithoutValue; mergeStatus: AsyncState; merge: AsyncStateWithoutValue; - branches: AsyncState; + branches: AsyncState; checkoutBranch: AsyncStateWithoutValue; createBranch: AsyncStateWithoutValue; deleteBranch: AsyncStateWithoutValue; From f9c40307f2f24415b3ab9a90967e13302a66d50c Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Sat, 7 Dec 2024 19:29:17 +0800 Subject: [PATCH 009/143] chore: adding fetch and update local profile --- .../git/actions/fetchLocalConfigActions.ts | 38 ----------------- .../git/actions/fetchLocalProfileActions.ts | 35 ++++++++++++++++ .../helpers/singleArtifactInitialState.ts | 4 +- .../git/actions/updateLocalConfigActions.ts | 30 ------------- .../git/actions/updateLocalProfileActions.ts | 32 ++++++++++++++ .../git/requests/fetchLocalConfigRequest.ts | 10 ----- .../requests/fetchLocalConfigRequest.types.ts | 5 --- .../git/requests/fetchLocalProfileRequest.ts | 10 +++++ .../fetchLocalProfileRequest.types.ts | 10 +++++ .../git/requests/updateLocalConfigRequest.ts | 14 ------- .../updateLocalConfigRequest.types.ts | 13 ------ .../git/requests/updateLocalProfileRequest.ts | 14 +++++++ .../updateLocalProfileRequest.types.ts | 18 ++++++++ app/client/src/git/sagas/commitSaga.ts | 7 +++- app/client/src/git/sagas/connectSaga.ts | 7 +++- app/client/src/git/sagas/fetchBranchesSaga.ts | 7 +++- .../src/git/sagas/fetchLocalProfileSaga.ts | 35 ++++++++++++++++ .../src/git/sagas/updateGlobalProfileSaga.ts | 7 +++- .../src/git/sagas/updateLocalProfileSaga.ts | 42 +++++++++++++++++++ app/client/src/git/store/gitArtifactSlice.ts | 16 +++++++ app/client/src/git/types.ts | 7 ++-- 21 files changed, 238 insertions(+), 123 deletions(-) delete mode 100644 app/client/src/git/actions/fetchLocalConfigActions.ts create mode 100644 app/client/src/git/actions/fetchLocalProfileActions.ts delete mode 100644 app/client/src/git/actions/updateLocalConfigActions.ts create mode 100644 app/client/src/git/actions/updateLocalProfileActions.ts delete mode 100644 app/client/src/git/requests/fetchLocalConfigRequest.ts delete mode 100644 app/client/src/git/requests/fetchLocalConfigRequest.types.ts create mode 100644 app/client/src/git/requests/fetchLocalProfileRequest.ts create mode 100644 app/client/src/git/requests/fetchLocalProfileRequest.types.ts delete mode 100644 app/client/src/git/requests/updateLocalConfigRequest.ts delete mode 100644 app/client/src/git/requests/updateLocalConfigRequest.types.ts create mode 100644 app/client/src/git/requests/updateLocalProfileRequest.ts create mode 100644 app/client/src/git/requests/updateLocalProfileRequest.types.ts create mode 100644 app/client/src/git/sagas/fetchLocalProfileSaga.ts create mode 100644 app/client/src/git/sagas/updateLocalProfileSaga.ts diff --git a/app/client/src/git/actions/fetchLocalConfigActions.ts b/app/client/src/git/actions/fetchLocalConfigActions.ts deleted file mode 100644 index e04dd2135874..000000000000 --- a/app/client/src/git/actions/fetchLocalConfigActions.ts +++ /dev/null @@ -1,38 +0,0 @@ -import type { - GitArtifactPayloadAction, - GitArtifactErrorPayloadAction, - GitLocalConfig, -} from "../types"; -import { createSingleArtifactAction } from "./helpers/createSingleArtifactAction"; - -export const fetchLocalConfigInitAction = createSingleArtifactAction( - (state) => { - state.apiResponses.localConfig.loading = true; - state.apiResponses.localConfig.error = null; - - return state; - }, -); - -export const fetchLocalConfigSuccessAction = createSingleArtifactAction( - ( - state, - action: GitArtifactPayloadAction<{ localConfig: GitLocalConfig }>, - ) => { - state.apiResponses.localConfig.loading = false; - state.apiResponses.localConfig.value = action.payload.localConfig; - - return state; - }, -); - -export const fetchLocalConfigErrorAction = createSingleArtifactAction( - (state, action: GitArtifactErrorPayloadAction) => { - const { error } = action.payload; - - state.apiResponses.localConfig.loading = false; - state.apiResponses.localConfig.error = error; - - return state; - }, -); diff --git a/app/client/src/git/actions/fetchLocalProfileActions.ts b/app/client/src/git/actions/fetchLocalProfileActions.ts new file mode 100644 index 000000000000..c4775f4ab7f5 --- /dev/null +++ b/app/client/src/git/actions/fetchLocalProfileActions.ts @@ -0,0 +1,35 @@ +import type { FetchLocalProfileResponseData } from "git/requests/fetchLocalProfileRequest.types"; +import type { + GitArtifactErrorPayloadAction, + GitAsyncSuccessPayload, +} from "../types"; +import { createSingleArtifactAction } from "./helpers/createSingleArtifactAction"; + +export const fetchLocalProfileInitAction = createSingleArtifactAction( + (state) => { + state.apiResponses.localProfile.loading = true; + state.apiResponses.localProfile.error = null; + + return state; + }, +); + +export const fetchLocalProfileSuccessAction = createSingleArtifactAction< + GitAsyncSuccessPayload +>((state, action) => { + state.apiResponses.localProfile.loading = false; + state.apiResponses.localProfile.value = action.payload.responseData; + + return state; +}); + +export const fetchLocalProfileErrorAction = createSingleArtifactAction( + (state, action: GitArtifactErrorPayloadAction) => { + const { error } = action.payload; + + state.apiResponses.localProfile.loading = false; + state.apiResponses.localProfile.error = error; + + return state; + }, +); diff --git a/app/client/src/git/actions/helpers/singleArtifactInitialState.ts b/app/client/src/git/actions/helpers/singleArtifactInitialState.ts index 4e8d75aab493..d4155ffe3fd6 100644 --- a/app/client/src/git/actions/helpers/singleArtifactInitialState.ts +++ b/app/client/src/git/actions/helpers/singleArtifactInitialState.ts @@ -89,12 +89,12 @@ const gitSingleArtifactInitialAPIResponses: GitSingleArtifactAPIResponsesReduxSt loading: false, error: null, }, - localConfig: { + localProfile: { value: null, loading: false, error: null, }, - updateLocalConfig: { + updateLocalProfile: { loading: false, error: null, }, diff --git a/app/client/src/git/actions/updateLocalConfigActions.ts b/app/client/src/git/actions/updateLocalConfigActions.ts deleted file mode 100644 index 439d284d20af..000000000000 --- a/app/client/src/git/actions/updateLocalConfigActions.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { createSingleArtifactAction } from "./helpers/createSingleArtifactAction"; -import type { GitArtifactErrorPayloadAction } from "../types"; - -export const updateLocalConfigInitAction = createSingleArtifactAction( - (state) => { - state.apiResponses.updateLocalConfig.loading = true; - state.apiResponses.updateLocalConfig.error = null; - - return state; - }, -); - -export const updateLocalConfigSuccessAction = createSingleArtifactAction( - (state) => { - state.apiResponses.updateLocalConfig.loading = false; - - return state; - }, -); - -export const updateLocalConfigErrorAction = createSingleArtifactAction( - (state, action: GitArtifactErrorPayloadAction) => { - const { error } = action.payload; - - state.apiResponses.updateLocalConfig.loading = false; - state.apiResponses.updateLocalConfig.error = error; - - return state; - }, -); diff --git a/app/client/src/git/actions/updateLocalProfileActions.ts b/app/client/src/git/actions/updateLocalProfileActions.ts new file mode 100644 index 000000000000..839175016d2a --- /dev/null +++ b/app/client/src/git/actions/updateLocalProfileActions.ts @@ -0,0 +1,32 @@ +import { createSingleArtifactAction } from "./helpers/createSingleArtifactAction"; +import type { GitAsyncErrorPayload } from "../types"; +import type { UpdateLocalProfileRequestParams } from "git/requests/updateLocalProfileRequest.types"; + +export interface UpdateLocalProfileInitPayload + extends UpdateLocalProfileRequestParams {} + +export const updateLocalProfileInitAction = + createSingleArtifactAction((state) => { + state.apiResponses.updateLocalProfile.loading = true; + state.apiResponses.updateLocalProfile.error = null; + + return state; + }); + +export const updateLocalProfileSuccessAction = createSingleArtifactAction( + (state) => { + state.apiResponses.updateLocalProfile.loading = false; + + return state; + }, +); + +export const updateLocalProfileErrorAction = + createSingleArtifactAction((state, action) => { + const { error } = action.payload; + + state.apiResponses.updateLocalProfile.loading = false; + state.apiResponses.updateLocalProfile.error = error; + + return state; + }); diff --git a/app/client/src/git/requests/fetchLocalConfigRequest.ts b/app/client/src/git/requests/fetchLocalConfigRequest.ts deleted file mode 100644 index 53159fc886f7..000000000000 --- a/app/client/src/git/requests/fetchLocalConfigRequest.ts +++ /dev/null @@ -1,10 +0,0 @@ -import Api from "api/Api"; -import type { AxiosResponse } from "axios"; -import { GIT_BASE_URL } from "./constants"; -import type { FetchLocalConfigResponse } from "./fetchLocalConfigRequest.types"; - -export default async function fetchLocalConfigRequest( - baseApplicationId: string, -): Promise> { - return Api.get(`${GIT_BASE_URL}/profile/app/${baseApplicationId}`); -} diff --git a/app/client/src/git/requests/fetchLocalConfigRequest.types.ts b/app/client/src/git/requests/fetchLocalConfigRequest.types.ts deleted file mode 100644 index abc83e1d83ba..000000000000 --- a/app/client/src/git/requests/fetchLocalConfigRequest.types.ts +++ /dev/null @@ -1,5 +0,0 @@ -export interface FetchLocalConfigResponse { - authorName: string; - authorEmail: string; - useGlobalProfile: boolean; -} diff --git a/app/client/src/git/requests/fetchLocalProfileRequest.ts b/app/client/src/git/requests/fetchLocalProfileRequest.ts new file mode 100644 index 000000000000..2e02a1fecc8d --- /dev/null +++ b/app/client/src/git/requests/fetchLocalProfileRequest.ts @@ -0,0 +1,10 @@ +import Api from "api/Api"; +import type { AxiosPromise } from "axios"; +import { GIT_BASE_URL } from "./constants"; +import type { FetchLocalProfileResponse } from "./fetchLocalProfileRequest.types"; + +export default async function fetchLocalProfileRequest( + baseApplicationId: string, +): AxiosPromise { + return Api.get(`${GIT_BASE_URL}/profile/app/${baseApplicationId}`); +} diff --git a/app/client/src/git/requests/fetchLocalProfileRequest.types.ts b/app/client/src/git/requests/fetchLocalProfileRequest.types.ts new file mode 100644 index 000000000000..c64f89d2bfc7 --- /dev/null +++ b/app/client/src/git/requests/fetchLocalProfileRequest.types.ts @@ -0,0 +1,10 @@ +import type { ApiResponse } from "api/types"; + +export interface FetchLocalProfileResponseData { + authorName: string; + authorEmail: string; + useGlobalProfile: boolean; +} + +export type FetchLocalProfileResponse = + ApiResponse; diff --git a/app/client/src/git/requests/updateLocalConfigRequest.ts b/app/client/src/git/requests/updateLocalConfigRequest.ts deleted file mode 100644 index 4b69bc72c27d..000000000000 --- a/app/client/src/git/requests/updateLocalConfigRequest.ts +++ /dev/null @@ -1,14 +0,0 @@ -import type { AxiosResponse } from "axios"; -import type { - UpdateLocalConfigRequestParams, - UpdateLocalConfigResponse, -} from "./updateLocalConfigRequest.types"; -import Api from "api/Api"; -import { GIT_BASE_URL } from "./constants"; - -export default async function updateLocalConfigRequest( - baseApplicationId: string, - params: UpdateLocalConfigRequestParams, -): Promise> { - return Api.put(`${GIT_BASE_URL}/profile/app/${baseApplicationId}`, params); -} diff --git a/app/client/src/git/requests/updateLocalConfigRequest.types.ts b/app/client/src/git/requests/updateLocalConfigRequest.types.ts deleted file mode 100644 index 5414637a46c8..000000000000 --- a/app/client/src/git/requests/updateLocalConfigRequest.types.ts +++ /dev/null @@ -1,13 +0,0 @@ -export interface UpdateLocalConfigRequestParams { - authorName: string; - authorEmail: string; - useGlobalProfile: boolean; -} - -export interface UpdateLocalConfigResponse { - [baseApplicationId: string]: { - authorName: string; - authorEmail: string; - useGlobalProfile: boolean; - }; -} diff --git a/app/client/src/git/requests/updateLocalProfileRequest.ts b/app/client/src/git/requests/updateLocalProfileRequest.ts new file mode 100644 index 000000000000..7e5dff54932f --- /dev/null +++ b/app/client/src/git/requests/updateLocalProfileRequest.ts @@ -0,0 +1,14 @@ +import type { AxiosPromise } from "axios"; +import type { + UpdateLocalProfileRequestParams, + UpdateLocalProfileResponse, +} from "./updateLocalProfileRequest.types"; +import Api from "api/Api"; +import { GIT_BASE_URL } from "./constants"; + +export default async function updateLocalProfileRequest( + baseApplicationId: string, + params: UpdateLocalProfileRequestParams, +): AxiosPromise { + return Api.put(`${GIT_BASE_URL}/profile/app/${baseApplicationId}`, params); +} diff --git a/app/client/src/git/requests/updateLocalProfileRequest.types.ts b/app/client/src/git/requests/updateLocalProfileRequest.types.ts new file mode 100644 index 000000000000..4d480fb4fad9 --- /dev/null +++ b/app/client/src/git/requests/updateLocalProfileRequest.types.ts @@ -0,0 +1,18 @@ +import type { ApiResponse } from "api/types"; + +export interface UpdateLocalProfileRequestParams { + authorName: string; + authorEmail: string; + useGlobalProfile: boolean; +} + +export interface UpdateLocalProfileResponseData { + [baseApplicationId: string]: { + authorName: string; + authorEmail: string; + useGlobalProfile: boolean; + }; +} + +export type UpdateLocalProfileResponse = + ApiResponse; diff --git a/app/client/src/git/sagas/commitSaga.ts b/app/client/src/git/sagas/commitSaga.ts index bf9aaddcb47f..f1020ddf79b4 100644 --- a/app/client/src/git/sagas/commitSaga.ts +++ b/app/client/src/git/sagas/commitSaga.ts @@ -1,7 +1,10 @@ import type { CommitInitPayload } from "../actions/commitActions"; import { GitArtifactType, GitErrorCodes } from "../constants/enums"; import commitRequest from "../requests/commitRequest"; -import type { CommitResponse } from "../requests/commitRequest.types"; +import type { + CommitRequestParams, + CommitResponse, +} from "../requests/commitRequest.types"; import { gitArtifactActions } from "../store/gitArtifactSlice"; import type { GitArtifactPayloadAction } from "../types"; import { call, put } from "redux-saga/effects"; @@ -17,7 +20,7 @@ export default function* commitSaga( let response: CommitResponse | undefined; try { - const params = { + const params: CommitRequestParams = { commitMessage: action.payload.commitMessage, doPush: action.payload.doPush, }; diff --git a/app/client/src/git/sagas/connectSaga.ts b/app/client/src/git/sagas/connectSaga.ts index 3fe07e4fd03c..af8e7f495473 100644 --- a/app/client/src/git/sagas/connectSaga.ts +++ b/app/client/src/git/sagas/connectSaga.ts @@ -1,6 +1,9 @@ import { gitArtifactActions } from "../store/gitArtifactSlice"; import connectRequest from "../requests/connectRequest"; -import type { ConnectResponse } from "../requests/connectRequest.types"; +import type { + ConnectRequestParams, + ConnectResponse, +} from "../requests/connectRequest.types"; import { GitArtifactType, GitErrorCodes } from "../constants/enums"; import { GIT_BRANCH_QUERY_KEY } from "../constants/misc"; import type { GitArtifactPayloadAction } from "../types"; @@ -22,7 +25,7 @@ export default function* connectSaga( let response: ConnectResponse | undefined; try { - const params = { + const params: ConnectRequestParams = { remoteUrl: action.payload.remoteUrl, gitProfile: action.payload.gitProfile, }; diff --git a/app/client/src/git/sagas/fetchBranchesSaga.ts b/app/client/src/git/sagas/fetchBranchesSaga.ts index fb3fa98c4a54..0a10286f91df 100644 --- a/app/client/src/git/sagas/fetchBranchesSaga.ts +++ b/app/client/src/git/sagas/fetchBranchesSaga.ts @@ -1,6 +1,9 @@ import type { FetchBranchesInitPayload } from "git/actions/fetchBranchesActions"; import fetchBranchesRequest from "git/requests/fetchBranchesRequest"; -import type { FetchBranchesResponse } from "git/requests/fetchBranchesRequest.types"; +import type { + FetchBranchesRequestParams, + FetchBranchesResponse, +} from "git/requests/fetchBranchesRequest.types"; import { gitArtifactActions } from "git/store/gitArtifactSlice"; import type { GitArtifactPayloadAction } from "git/types"; import { call, put } from "redux-saga/effects"; @@ -14,7 +17,7 @@ export default function* fetchBranchesSaga( let response: FetchBranchesResponse | undefined; try { - const params = { + const params: FetchBranchesRequestParams = { pruneBranches: action.payload.pruneBranches, }; diff --git a/app/client/src/git/sagas/fetchLocalProfileSaga.ts b/app/client/src/git/sagas/fetchLocalProfileSaga.ts new file mode 100644 index 000000000000..f0fed2306b75 --- /dev/null +++ b/app/client/src/git/sagas/fetchLocalProfileSaga.ts @@ -0,0 +1,35 @@ +import fetchLocalProfileRequest from "git/requests/fetchLocalProfileRequest"; +import type { FetchLocalProfileResponse } from "git/requests/fetchLocalProfileRequest.types"; +import { gitArtifactActions } from "git/store/gitArtifactSlice"; +import type { GitArtifactPayloadAction } from "git/types"; +import { call, put } from "redux-saga/effects"; +import { validateResponse } from "sagas/ErrorSagas"; + +export default function* fetchLocalProfileSaga( + action: GitArtifactPayloadAction, +) { + const { artifactType, baseArtifactId } = action.payload; + const basePayload = { artifactType, baseArtifactId }; + let response: FetchLocalProfileResponse | undefined; + + try { + response = yield call(fetchLocalProfileRequest, baseArtifactId); + const isValidResponse: boolean = yield validateResponse(response); + + if (response && isValidResponse) { + yield put( + gitArtifactActions.fetchLocalProfileSuccess({ + ...basePayload, + responseData: response.data, + }), + ); + } + } catch (error) { + yield put( + gitArtifactActions.fetchLocalProfileError({ + ...basePayload, + error: error as string, + }), + ); + } +} diff --git a/app/client/src/git/sagas/updateGlobalProfileSaga.ts b/app/client/src/git/sagas/updateGlobalProfileSaga.ts index 0440295196e6..1a7b095812d5 100644 --- a/app/client/src/git/sagas/updateGlobalProfileSaga.ts +++ b/app/client/src/git/sagas/updateGlobalProfileSaga.ts @@ -2,7 +2,10 @@ import type { PayloadAction } from "@reduxjs/toolkit"; import { call, put } from "redux-saga/effects"; import type { UpdateGlobalProfileInitPayload } from "../actions/updateGlobalProfileActions"; import updateGlobalProfileRequest from "../requests/updateGlobalProfileRequest"; -import type { UpdateGlobalProfileResponse } from "../requests/updateGlobalProfileRequest.types"; +import type { + UpdateGlobalProfileRequestParams, + UpdateGlobalProfileResponse, +} from "../requests/updateGlobalProfileRequest.types"; import { gitConfigActions } from "../store/gitConfigSlice"; // internal dependencies @@ -14,7 +17,7 @@ export default function* updateGlobalGitConfig( let response: UpdateGlobalProfileResponse | undefined; try { - const params = { + const params: UpdateGlobalProfileRequestParams = { authorName: action.payload.authorName, authorEmail: action.payload.authorEmail, }; diff --git a/app/client/src/git/sagas/updateLocalProfileSaga.ts b/app/client/src/git/sagas/updateLocalProfileSaga.ts new file mode 100644 index 000000000000..21923693a322 --- /dev/null +++ b/app/client/src/git/sagas/updateLocalProfileSaga.ts @@ -0,0 +1,42 @@ +import type { UpdateLocalProfileInitPayload } from "git/actions/updateLocalProfileActions"; +import updateLocalProfileRequest from "git/requests/updateLocalProfileRequest"; +import type { + UpdateLocalProfileRequestParams, + UpdateLocalProfileResponse, +} from "git/requests/updateLocalProfileRequest.types"; +import { gitArtifactActions } from "git/store/gitArtifactSlice"; +import type { GitArtifactPayloadAction } from "git/types"; +import { call, put } from "redux-saga/effects"; +import { validateResponse } from "sagas/ErrorSagas"; + +export default function* updateLocalProfileSaga( + action: GitArtifactPayloadAction, +) { + const { artifactType, baseArtifactId } = action.payload; + const basePayload = { artifactType, baseArtifactId }; + let response: UpdateLocalProfileResponse | undefined; + + try { + const params: UpdateLocalProfileRequestParams = { + authorName: action.payload.authorName, + authorEmail: action.payload.authorEmail, + useGlobalProfile: action.payload.useGlobalProfile, + }; + + response = yield call(updateLocalProfileRequest, baseArtifactId, params); + + const isValidResponse: boolean = yield validateResponse(response); + + if (isValidResponse) { + yield put(gitArtifactActions.updateLocalProfileSuccess(basePayload)); + yield put(gitArtifactActions.fetchLocalProfileInit(basePayload)); + } + } catch (error) { + yield put( + gitArtifactActions.updateLocalProfileError({ + ...basePayload, + error: error as string, + }), + ); + } +} diff --git a/app/client/src/git/store/gitArtifactSlice.ts b/app/client/src/git/store/gitArtifactSlice.ts index 789ba2cefc5b..343661634d36 100644 --- a/app/client/src/git/store/gitArtifactSlice.ts +++ b/app/client/src/git/store/gitArtifactSlice.ts @@ -33,6 +33,16 @@ import { pullSuccessAction, } from "../actions/pullActions"; import { toggleRepoLimitErrorModalAction } from "../actions/repoLimitErrorModalActions"; +import { + fetchLocalProfileErrorAction, + fetchLocalProfileInitAction, + fetchLocalProfileSuccessAction, +} from "git/actions/fetchLocalProfileActions"; +import { + updateLocalProfileErrorAction, + updateLocalProfileInitAction, + updateLocalProfileSuccessAction, +} from "git/actions/updateLocalProfileActions"; const initialState: GitArtifactReduxState = {}; @@ -60,6 +70,12 @@ export const gitArtifactSlice = createSlice({ pullInit: pullInitAction, pullSuccess: pullSuccessAction, pullError: pullErrorAction, + fetchLocalProfileInit: fetchLocalProfileInitAction, + fetchLocalProfileSuccess: fetchLocalProfileSuccessAction, + fetchLocalProfileError: fetchLocalProfileErrorAction, + updateLocalProfileInit: updateLocalProfileInitAction, + updateLocalProfileSuccess: updateLocalProfileSuccessAction, + updateLocalProfileError: updateLocalProfileErrorAction, toggleRepoLimitErrorModal: toggleRepoLimitErrorModalAction, }, }); diff --git a/app/client/src/git/types.ts b/app/client/src/git/types.ts index adbe873756e3..78d9c69e8ab0 100644 --- a/app/client/src/git/types.ts +++ b/app/client/src/git/types.ts @@ -8,6 +8,7 @@ import type { } from "./constants/enums"; import type { FetchGlobalProfileResponseData } from "./requests/fetchGlobalProfileRequest.types"; import type { FetchBranchesResponseData } from "./requests/fetchBranchesRequest.types"; +import type { FetchLocalProfileResponseData } from "./requests/fetchLocalProfileRequest.types"; // These will be updated when contracts are finalized export type GitMetadata = Record; @@ -16,7 +17,7 @@ export type GitStatus = Record; export type GitMergeStatus = Record; -export type GitLocalConfig = Record; +export type GitLocalProfile = Record; export type GitProtectedBranches = Record; @@ -47,8 +48,8 @@ export interface GitSingleArtifactAPIResponsesReduxState { checkoutBranch: AsyncStateWithoutValue; createBranch: AsyncStateWithoutValue; deleteBranch: AsyncStateWithoutValue; - localConfig: AsyncState; - updateLocalConfig: AsyncStateWithoutValue; + localProfile: AsyncState; + updateLocalProfile: AsyncStateWithoutValue; disconnect: AsyncStateWithoutValue; protectedBranches: AsyncState; updateProtectedBranches: AsyncStateWithoutValue; From adafd145973494528271a0987dbb50f9a2fd98c4 Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Sat, 7 Dec 2024 19:32:35 +0800 Subject: [PATCH 010/143] fix: fixing connectsaga --- app/client/src/git/sagas/connectSaga.ts | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/app/client/src/git/sagas/connectSaga.ts b/app/client/src/git/sagas/connectSaga.ts index af8e7f495473..a3964934253a 100644 --- a/app/client/src/git/sagas/connectSaga.ts +++ b/app/client/src/git/sagas/connectSaga.ts @@ -5,7 +5,6 @@ import type { ConnectResponse, } from "../requests/connectRequest.types"; import { GitArtifactType, GitErrorCodes } from "../constants/enums"; -import { GIT_BRANCH_QUERY_KEY } from "../constants/misc"; import type { GitArtifactPayloadAction } from "../types"; import type { ConnectInitPayload } from "../actions/connectActions"; @@ -15,6 +14,7 @@ import { call, put } from "redux-saga/effects"; import { validateResponse } from "sagas/ErrorSagas"; import { fetchPageAction } from "actions/pageActions"; import history from "utils/history"; +import { addBranchParam } from "constants/routes"; export default function* connectSaga( action: GitArtifactPayloadAction, @@ -46,11 +46,9 @@ export default function* connectSaga( } const branch = response.data.gitApplicationMetadata.branchName; - const url = new URL(window.location.href); + const newUrl = addBranchParam(branch); - url.searchParams.set(GIT_BRANCH_QUERY_KEY, encodeURIComponent(branch)); - url.toString().slice(url.origin.length); - history.replace(url); + history.replace(newUrl); // ! case for updating lastDeployedAt in application manually? } } From 488b3460793b13cc88effd0504a02a33797b4e3e Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Sun, 8 Dec 2024 18:58:22 +0800 Subject: [PATCH 011/143] fix: review changes --- app/client/src/git/sagas/commitSaga.ts | 2 +- app/client/src/git/sagas/index.ts | 26 ++++++++++++++++--- .../src/git/sagas/updateGlobalProfileSaga.ts | 2 +- 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/app/client/src/git/sagas/commitSaga.ts b/app/client/src/git/sagas/commitSaga.ts index f1020ddf79b4..d1926f5b5412 100644 --- a/app/client/src/git/sagas/commitSaga.ts +++ b/app/client/src/git/sagas/commitSaga.ts @@ -55,7 +55,7 @@ export default function* commitSaga( } yield put( - gitArtifactActions.connectError({ + gitArtifactActions.commitError({ ...basePayload, error: error as string, }), diff --git a/app/client/src/git/sagas/index.ts b/app/client/src/git/sagas/index.ts index fce28d6014ae..50517d875efd 100644 --- a/app/client/src/git/sagas/index.ts +++ b/app/client/src/git/sagas/index.ts @@ -5,12 +5,30 @@ import commitSaga from "./commitSaga"; import { gitConfigActions } from "git/store/gitConfigSlice"; import fetchGlobalProfileSaga from "./fetchGlobalProfileSaga"; import fetchBranchesSaga from "./fetchBranchesSaga"; +import fetchLocalProfileSaga from "./fetchLocalProfileSaga"; +import updateLocalProfileSaga from "./updateLocalProfileSaga"; +import updateGlobalProfileSaga from "./updateGlobalProfileSaga"; export function* gitSagas() { yield all([ - takeLatest(gitArtifactActions.connectInit, connectSaga), - takeLatest(gitArtifactActions.commitInit, commitSaga), - takeLatest(gitArtifactActions.fetchBranchesInit, fetchBranchesSaga), - takeLatest(gitConfigActions.fetchGlobalProfileInit, fetchGlobalProfileSaga), + takeLatest(gitArtifactActions.connectInit.type, connectSaga), + takeLatest(gitArtifactActions.commitInit.type, commitSaga), + takeLatest(gitArtifactActions.fetchBranchesInit.type, fetchBranchesSaga), + takeLatest( + gitArtifactActions.fetchLocalProfileInit.type, + fetchLocalProfileSaga, + ), + takeLatest( + gitArtifactActions.updateLocalProfileInit.type, + updateLocalProfileSaga, + ), + takeLatest( + gitConfigActions.fetchGlobalProfileInit.type, + fetchGlobalProfileSaga, + ), + takeLatest( + gitConfigActions.updateGlobalProfileInit.type, + updateGlobalProfileSaga, + ), ]); } diff --git a/app/client/src/git/sagas/updateGlobalProfileSaga.ts b/app/client/src/git/sagas/updateGlobalProfileSaga.ts index 1a7b095812d5..24d22cc144c9 100644 --- a/app/client/src/git/sagas/updateGlobalProfileSaga.ts +++ b/app/client/src/git/sagas/updateGlobalProfileSaga.ts @@ -11,7 +11,7 @@ import { gitConfigActions } from "../store/gitConfigSlice"; // internal dependencies import { validateResponse } from "sagas/ErrorSagas"; -export default function* updateGlobalGitConfig( +export default function* updateGlobalProfileSaga( action: PayloadAction, ) { let response: UpdateGlobalProfileResponse | undefined; From 942193d2bb5149351c1b9c47dd90a867a196be53 Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Mon, 9 Dec 2024 14:31:26 +0800 Subject: [PATCH 012/143] chore: adding branch based sagas --- .../src/git/actions/checkoutBranchActions.ts | 24 ++-- .../src/git/actions/createBranchActions.ts | 23 ++-- .../src/git/actions/deleteBranchActions.ts | 23 ++-- .../helpers/singleArtifactInitialState.ts | 2 +- .../git/actions/repoLimitErrorModalActions.ts | 16 --- app/client/src/git/actions/uiActions.ts | 27 ++++ .../requests/checkoutBranchRequest.types.ts | 10 +- .../git/requests/createBranchRequest.types.ts | 6 +- .../git/requests/deleteBranchRequest.types.ts | 6 +- .../src/git/sagas/checkoutBranchSaga.ts | 121 ++++++++++++++++++ app/client/src/git/sagas/createBranchSaga.ts | 48 +++++++ app/client/src/git/sagas/deleteBranchSaga.ts | 46 +++++++ app/client/src/git/sagas/index.ts | 6 +- app/client/src/git/store/gitArtifactSlice.ts | 42 +++++- app/client/src/git/types.ts | 2 +- 15 files changed, 343 insertions(+), 59 deletions(-) delete mode 100644 app/client/src/git/actions/repoLimitErrorModalActions.ts create mode 100644 app/client/src/git/actions/uiActions.ts create mode 100644 app/client/src/git/sagas/checkoutBranchSaga.ts create mode 100644 app/client/src/git/sagas/createBranchSaga.ts create mode 100644 app/client/src/git/sagas/deleteBranchSaga.ts diff --git a/app/client/src/git/actions/checkoutBranchActions.ts b/app/client/src/git/actions/checkoutBranchActions.ts index 65640d5859cd..8d72e5204ce9 100644 --- a/app/client/src/git/actions/checkoutBranchActions.ts +++ b/app/client/src/git/actions/checkoutBranchActions.ts @@ -1,12 +1,17 @@ import { createSingleArtifactAction } from "./helpers/createSingleArtifactAction"; -import type { GitArtifactErrorPayloadAction } from "../types"; +import type { GitAsyncErrorPayload } from "../types"; +import type { CheckoutBranchRequestParams } from "git/requests/checkoutBranchRequest.types"; -export const checkoutBranchInitAction = createSingleArtifactAction((state) => { - state.apiResponses.checkoutBranch.loading = true; - state.apiResponses.checkoutBranch.error = null; +export interface CheckoutBranchInitPayload + extends CheckoutBranchRequestParams {} - return state; -}); +export const checkoutBranchInitAction = + createSingleArtifactAction((state) => { + state.apiResponses.checkoutBranch.loading = true; + state.apiResponses.checkoutBranch.error = null; + + return state; + }); export const checkoutBranchSuccessAction = createSingleArtifactAction( (state) => { @@ -16,13 +21,12 @@ export const checkoutBranchSuccessAction = createSingleArtifactAction( }, ); -export const checkoutBranchErrorAction = createSingleArtifactAction( - (state, action: GitArtifactErrorPayloadAction) => { +export const checkoutBranchErrorAction = + createSingleArtifactAction((state, action) => { const { error } = action.payload; state.apiResponses.checkoutBranch.loading = false; state.apiResponses.checkoutBranch.error = error; return state; - }, -); + }); diff --git a/app/client/src/git/actions/createBranchActions.ts b/app/client/src/git/actions/createBranchActions.ts index 82963f12d949..77917153ef39 100644 --- a/app/client/src/git/actions/createBranchActions.ts +++ b/app/client/src/git/actions/createBranchActions.ts @@ -1,12 +1,16 @@ import { createSingleArtifactAction } from "./helpers/createSingleArtifactAction"; -import type { GitArtifactErrorPayloadAction } from "../types"; +import type { GitAsyncErrorPayload } from "../types"; +import type { CreateBranchRequestParams } from "git/requests/createBranchRequest.types"; -export const createBranchInitAction = createSingleArtifactAction((state) => { - state.apiResponses.createBranch.loading = true; - state.apiResponses.createBranch.error = null; +export interface CreateBranchInitPayload extends CreateBranchRequestParams {} - return state; -}); +export const createBranchInitAction = + createSingleArtifactAction((state) => { + state.apiResponses.createBranch.loading = true; + state.apiResponses.createBranch.error = null; + + return state; + }); export const createBranchSuccessAction = createSingleArtifactAction((state) => { state.apiResponses.createBranch.loading = false; @@ -14,13 +18,12 @@ export const createBranchSuccessAction = createSingleArtifactAction((state) => { return state; }); -export const createBranchErrorAction = createSingleArtifactAction( - (state, action: GitArtifactErrorPayloadAction) => { +export const createBranchErrorAction = + createSingleArtifactAction((state, action) => { const { error } = action.payload; state.apiResponses.createBranch.loading = false; state.apiResponses.createBranch.error = error; return state; - }, -); + }); diff --git a/app/client/src/git/actions/deleteBranchActions.ts b/app/client/src/git/actions/deleteBranchActions.ts index 5d3ae8293ae4..a09552373b75 100644 --- a/app/client/src/git/actions/deleteBranchActions.ts +++ b/app/client/src/git/actions/deleteBranchActions.ts @@ -1,12 +1,16 @@ import { createSingleArtifactAction } from "./helpers/createSingleArtifactAction"; -import type { GitArtifactErrorPayloadAction } from "../types"; +import type { GitAsyncErrorPayload } from "../types"; +import type { DeleteBranchRequestParams } from "git/requests/deleteBranchRequest.types"; -export const deleteBranchInitAction = createSingleArtifactAction((state) => { - state.apiResponses.deleteBranch.loading = true; - state.apiResponses.deleteBranch.error = null; +export interface DeleteBranchInitPayload extends DeleteBranchRequestParams {} - return state; -}); +export const deleteBranchInitAction = + createSingleArtifactAction((state) => { + state.apiResponses.deleteBranch.loading = true; + state.apiResponses.deleteBranch.error = null; + + return state; + }); export const deleteBranchSuccessAction = createSingleArtifactAction((state) => { state.apiResponses.deleteBranch.loading = false; @@ -14,13 +18,12 @@ export const deleteBranchSuccessAction = createSingleArtifactAction((state) => { return state; }); -export const deleteBranchErrorAction = createSingleArtifactAction( - (state, action: GitArtifactErrorPayloadAction) => { +export const deleteBranchErrorAction = + createSingleArtifactAction((state, action) => { const { error } = action.payload; state.apiResponses.deleteBranch.loading = false; state.apiResponses.deleteBranch.error = error; return state; - }, -); + }); diff --git a/app/client/src/git/actions/helpers/singleArtifactInitialState.ts b/app/client/src/git/actions/helpers/singleArtifactInitialState.ts index d4155ffe3fd6..1dd40332ff60 100644 --- a/app/client/src/git/actions/helpers/singleArtifactInitialState.ts +++ b/app/client/src/git/actions/helpers/singleArtifactInitialState.ts @@ -19,7 +19,7 @@ const gitSingleArtifactInitialUIState: GitSingleArtifactUIReduxState = { open: false, step: GitImportStep.Provider, }, - branchList: { + branchListPopup: { open: false, }, opsModal: { diff --git a/app/client/src/git/actions/repoLimitErrorModalActions.ts b/app/client/src/git/actions/repoLimitErrorModalActions.ts deleted file mode 100644 index 96061395e854..000000000000 --- a/app/client/src/git/actions/repoLimitErrorModalActions.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { createSingleArtifactAction } from "./helpers/createSingleArtifactAction"; - -interface ToggleRepoLimitModalActionPayload { - open: boolean; -} - -export const toggleRepoLimitErrorModalAction = - createSingleArtifactAction( - (state, action) => { - const { open } = action.payload; - - state.ui.repoLimitErrorModal.open = open; - - return state; - }, - ); diff --git a/app/client/src/git/actions/uiActions.ts b/app/client/src/git/actions/uiActions.ts new file mode 100644 index 000000000000..7da558996e87 --- /dev/null +++ b/app/client/src/git/actions/uiActions.ts @@ -0,0 +1,27 @@ +import { createSingleArtifactAction } from "./helpers/createSingleArtifactAction"; + +interface ToggleRepoLimitModalPayload { + open: boolean; +} + +export const toggleRepoLimitErrorModalAction = + createSingleArtifactAction((state, action) => { + const { open } = action.payload; + + state.ui.repoLimitErrorModal.open = open; + + return state; + }); + +interface BranchListPopupPayload { + open: boolean; +} + +export const toggleBranchListPopupAction = + createSingleArtifactAction((state, action) => { + const { open } = action.payload; + + state.ui.branchListPopup.open = open; + + return state; + }); diff --git a/app/client/src/git/requests/checkoutBranchRequest.types.ts b/app/client/src/git/requests/checkoutBranchRequest.types.ts index 8c465fc624ee..38932b20de5f 100644 --- a/app/client/src/git/requests/checkoutBranchRequest.types.ts +++ b/app/client/src/git/requests/checkoutBranchRequest.types.ts @@ -1,8 +1,10 @@ +import type { ApiResponse } from "api/types"; +import type { ApplicationPayload } from "entities/Application"; + export interface CheckoutBranchRequestParams { branchName: string; } -export interface CheckoutBranchResponse { - id: string; // applicationId - baseId: string; // baseApplicationId -} +export interface CheckoutBranchResponseData extends ApplicationPayload {} + +export type CheckoutBranchResponse = ApiResponse; diff --git a/app/client/src/git/requests/createBranchRequest.types.ts b/app/client/src/git/requests/createBranchRequest.types.ts index 28735db75183..2366bd17b4cf 100644 --- a/app/client/src/git/requests/createBranchRequest.types.ts +++ b/app/client/src/git/requests/createBranchRequest.types.ts @@ -1,8 +1,12 @@ +import type { ApiResponse } from "api/types"; + export interface CreateBranchRequestParams { branchName: string; } -export interface CreateBranchResponse { +export interface CreateBranchResponseData { id: string; // applicationId baseId: string; // baseApplicationId } + +export type CreateBranchResponse = ApiResponse; diff --git a/app/client/src/git/requests/deleteBranchRequest.types.ts b/app/client/src/git/requests/deleteBranchRequest.types.ts index f7db6f834859..c3f168303e49 100644 --- a/app/client/src/git/requests/deleteBranchRequest.types.ts +++ b/app/client/src/git/requests/deleteBranchRequest.types.ts @@ -1,8 +1,12 @@ +import type { ApiResponse } from "api/types"; + export interface DeleteBranchRequestParams { branchName: string; } -export interface DeleteBranchResponse { +export interface DeleteBranchResponseData { id: string; // applicationId baseId: string; // baseApplicationId } + +export type DeleteBranchResponse = ApiResponse; diff --git a/app/client/src/git/sagas/checkoutBranchSaga.ts b/app/client/src/git/sagas/checkoutBranchSaga.ts new file mode 100644 index 000000000000..3af5dc252698 --- /dev/null +++ b/app/client/src/git/sagas/checkoutBranchSaga.ts @@ -0,0 +1,121 @@ +import { call, put, select, take } from "redux-saga/effects"; +import type { CheckoutBranchInitPayload } from "../actions/checkoutBranchActions"; +import { GitArtifactType } from "../constants/enums"; +import checkoutBranchRequest from "../requests/checkoutBranchRequest"; +import type { + CheckoutBranchRequestParams, + CheckoutBranchResponse, +} from "../requests/checkoutBranchRequest.types"; +import { gitArtifactActions } from "../store/gitArtifactSlice"; +import type { GitArtifactPayloadAction } from "../types"; + +// internal dependencies +import { builderURL } from "ee/RouteBuilder"; +import { ReduxActionTypes } from "ee/constants/ReduxActionConstants"; +import { getActions, getJSCollections } from "ee/selectors/entitiesSelector"; +import { addBranchParam } from "constants/routes"; +import type { Action } from "entities/Action"; +import { FocusEntity, identifyEntityFromPath } from "navigation/FocusEntity"; +import { validateResponse } from "sagas/ErrorSagas"; +import history from "utils/history"; +import type { JSCollectionDataState } from "ee/reducers/entityReducers/jsActionsReducer"; + +export default function* checkoutBranchSaga( + action: GitArtifactPayloadAction, +) { + const { artifactType, baseArtifactId, branchName } = action.payload; + const basePayload = { artifactType, baseArtifactId }; + let response: CheckoutBranchResponse | undefined; + + try { + const params: CheckoutBranchRequestParams = { + branchName, + }; + + response = yield call(checkoutBranchRequest, baseArtifactId, params); + const isValidResponse: boolean = yield validateResponse(response); + + if (response && isValidResponse) { + if (artifactType === GitArtifactType.Application) { + yield put(gitArtifactActions.checkoutBranchSuccess(basePayload)); + const trimmedBranch = branchName.replace(/^origin\//, ""); + const destinationHref = addBranchParam(trimmedBranch); + + const entityInfo = identifyEntityFromPath( + destinationHref.slice(0, destinationHref.indexOf("?")), + ); + + yield put( + gitArtifactActions.toggleBranchListPopup({ + ...basePayload, + open: false, + }), + ); + // Check if page exists in the branch. If not, instead of 404, take them to + // the app home page + const existingPage = response.data.pages.find( + (page) => page.baseId === entityInfo.params.basePageId, + ); + const defaultPage = response.data.pages.find((page) => page.isDefault); + + if (!existingPage && defaultPage) { + history.push( + builderURL({ + basePageId: defaultPage.baseId, + branch: trimmedBranch, + }), + ); + + return; + } + + // Page exists, so we will try to go to the destination + history.push(destinationHref); + + let shouldGoToHomePage = false; + + // It is possible that the action does not exist in the incoming branch + // so here instead of showing the 404 page, we will navigate them to the + // home page + if ([FocusEntity.API, FocusEntity.QUERY].includes(entityInfo.entity)) { + // Wait for fetch actions success, check if action id in actions state + // or else navigate to home + yield take(ReduxActionTypes.FETCH_ACTIONS_SUCCESS); + const actions: Action[] = yield select(getActions); + + if (!actions.find((action) => action.id === entityInfo.id)) { + shouldGoToHomePage = true; + } + } + + // Same for JS Objects + if (entityInfo.entity === FocusEntity.JS_OBJECT) { + yield take(ReduxActionTypes.FETCH_JS_ACTIONS_SUCCESS); + const jsActions: JSCollectionDataState = + yield select(getJSCollections); + + if (!jsActions.find((action) => action.config.id === entityInfo.id)) { + shouldGoToHomePage = true; + } + } + + if (shouldGoToHomePage && defaultPage) { + // We will replace so that the user does not go back to the 404 url + history.replace( + builderURL({ + basePageId: defaultPage.baseId, + persistExistingParams: true, + }), + ); + } + } + } + } catch (error) { + yield put( + gitArtifactActions.checkoutBranchError({ + ...basePayload, + error: error as string, + }), + ); + } +} diff --git a/app/client/src/git/sagas/createBranchSaga.ts b/app/client/src/git/sagas/createBranchSaga.ts new file mode 100644 index 000000000000..16a7fd8ca3f6 --- /dev/null +++ b/app/client/src/git/sagas/createBranchSaga.ts @@ -0,0 +1,48 @@ +import { call, put } from "redux-saga/effects"; +import type { CreateBranchInitPayload } from "../actions/createBranchActions"; +import createBranchRequest from "../requests/createBranchRequest"; +import type { + CreateBranchRequestParams, + CreateBranchResponse, +} from "../requests/createBranchRequest.types"; +import { gitArtifactActions } from "../store/gitArtifactSlice"; +import type { GitArtifactPayloadAction } from "../types"; + +// internal dependencies +import { validateResponse } from "sagas/ErrorSagas"; + +export default function* createBranchSaga( + action: GitArtifactPayloadAction, +) { + const { artifactType, baseArtifactId } = action.payload; + const basePayload = { artifactType, baseArtifactId }; + let response: CreateBranchResponse | undefined; + + try { + const params: CreateBranchRequestParams = { + branchName: action.payload.branchName, + }; + + response = yield call(createBranchRequest, baseArtifactId, params); + const isValidResponse: boolean = yield validateResponse(response); + + if (isValidResponse) { + yield put(gitArtifactActions.createBranchSuccess(basePayload)); + yield put( + gitArtifactActions.fetchBranchesInit({ + ...basePayload, + pruneBranches: true, + }), + ); + + // ! case to switch to the new branch + } + } catch (error) { + yield put( + gitArtifactActions.createBranchError({ + ...basePayload, + error: error as string, + }), + ); + } +} diff --git a/app/client/src/git/sagas/deleteBranchSaga.ts b/app/client/src/git/sagas/deleteBranchSaga.ts new file mode 100644 index 000000000000..d9e7dcd51891 --- /dev/null +++ b/app/client/src/git/sagas/deleteBranchSaga.ts @@ -0,0 +1,46 @@ +import type { DeleteBranchInitPayload } from "../actions/deleteBranchActions"; +import deleteBranchRequest from "../requests/deleteBranchRequest"; +import type { + DeleteBranchRequestParams, + DeleteBranchResponse, +} from "../requests/deleteBranchRequest.types"; +import { gitArtifactActions } from "../store/gitArtifactSlice"; +import type { GitArtifactPayloadAction } from "../types"; +import { call, put } from "redux-saga/effects"; + +// internal dependencies +import { validateResponse } from "sagas/ErrorSagas"; + +export default function* deleteBranchSaga( + action: GitArtifactPayloadAction, +) { + const { artifactType, baseArtifactId } = action.payload; + const basePayload = { artifactType, baseArtifactId }; + let response: DeleteBranchResponse | undefined; + + try { + const params: DeleteBranchRequestParams = { + branchName: action.payload.branchName, + }; + + response = yield call(deleteBranchRequest, baseArtifactId, params); + const isValidResponse: boolean = yield validateResponse(response); + + if (isValidResponse) { + yield put(gitArtifactActions.deleteBranchSuccess(basePayload)); + yield put( + gitArtifactActions.fetchBranchesInit({ + ...basePayload, + pruneBranches: true, + }), + ); + } + } catch (error) { + yield put( + gitArtifactActions.deleteBranchError({ + ...basePayload, + error: error as string, + }), + ); + } +} diff --git a/app/client/src/git/sagas/index.ts b/app/client/src/git/sagas/index.ts index 50517d875efd..ed4f54f25a67 100644 --- a/app/client/src/git/sagas/index.ts +++ b/app/client/src/git/sagas/index.ts @@ -12,8 +12,12 @@ import updateGlobalProfileSaga from "./updateGlobalProfileSaga"; export function* gitSagas() { yield all([ takeLatest(gitArtifactActions.connectInit.type, connectSaga), - takeLatest(gitArtifactActions.commitInit.type, commitSaga), + + // branches + takeLatest(gitArtifactActions.fetchBranchesInit.type, fetchBranchesSaga), takeLatest(gitArtifactActions.fetchBranchesInit.type, fetchBranchesSaga), + + takeLatest(gitArtifactActions.commitInit.type, commitSaga), takeLatest( gitArtifactActions.fetchLocalProfileInit.type, fetchLocalProfileSaga, diff --git a/app/client/src/git/store/gitArtifactSlice.ts b/app/client/src/git/store/gitArtifactSlice.ts index 343661634d36..898b8a1de575 100644 --- a/app/client/src/git/store/gitArtifactSlice.ts +++ b/app/client/src/git/store/gitArtifactSlice.ts @@ -32,7 +32,6 @@ import { pullInitAction, pullSuccessAction, } from "../actions/pullActions"; -import { toggleRepoLimitErrorModalAction } from "../actions/repoLimitErrorModalActions"; import { fetchLocalProfileErrorAction, fetchLocalProfileInitAction, @@ -43,6 +42,25 @@ import { updateLocalProfileInitAction, updateLocalProfileSuccessAction, } from "git/actions/updateLocalProfileActions"; +import { + createBranchErrorAction, + createBranchInitAction, + createBranchSuccessAction, +} from "git/actions/createBranchActions"; +import { + deleteBranchErrorAction, + deleteBranchInitAction, + deleteBranchSuccessAction, +} from "git/actions/deleteBranchActions"; +import { + toggleBranchListPopupAction, + toggleRepoLimitErrorModalAction, +} from "git/actions/uiActions"; +import { + checkoutBranchErrorAction, + checkoutBranchInitAction, + checkoutBranchSuccessAction, +} from "git/actions/checkoutBranchActions"; const initialState: GitArtifactReduxState = {}; @@ -55,12 +73,25 @@ export const gitArtifactSlice = createSlice({ connectInit: connectInitAction, connectSuccess: connectSuccessAction, connectError: connectErrorAction, - fetchMetadataInit: fetchMetadataInitAction, - fetchMetadataSuccess: fetchMetadataSuccessAction, - fetchMetadataError: fetchMetadataErrorAction, + + // branches fetchBranchesInit: fetchBranchesInitAction, fetchBranchesSuccess: fetchBranchesSuccessAction, fetchBranchesError: fetchBranchesErrorAction, + createBranchInit: createBranchInitAction, + createBranchSuccess: createBranchSuccessAction, + createBranchError: createBranchErrorAction, + deleteBranchInit: deleteBranchInitAction, + deleteBranchSuccess: deleteBranchSuccessAction, + deleteBranchError: deleteBranchErrorAction, + checkoutBranchInit: checkoutBranchInitAction, + checkoutBranchSuccess: checkoutBranchSuccessAction, + checkoutBranchError: checkoutBranchErrorAction, + + // metadata + fetchMetadataInit: fetchMetadataInitAction, + fetchMetadataSuccess: fetchMetadataSuccessAction, + fetchMetadataError: fetchMetadataErrorAction, fetchStatusInit: fetchStatusInitAction, fetchStatusSuccess: fetchStatusSuccessAction, fetchStatusError: fetchStatusErrorAction, @@ -76,6 +107,9 @@ export const gitArtifactSlice = createSlice({ updateLocalProfileInit: updateLocalProfileInitAction, updateLocalProfileSuccess: updateLocalProfileSuccessAction, updateLocalProfileError: updateLocalProfileErrorAction, + + // ui actions + toggleBranchListPopup: toggleBranchListPopupAction, toggleRepoLimitErrorModal: toggleRepoLimitErrorModalAction, }, }); diff --git a/app/client/src/git/types.ts b/app/client/src/git/types.ts index 78d9c69e8ab0..3a1b6c27b4b7 100644 --- a/app/client/src/git/types.ts +++ b/app/client/src/git/types.ts @@ -69,7 +69,7 @@ export interface GitSingleArtifactUIReduxState { open: boolean; step: keyof typeof GitImportStep; }; - branchList: { + branchListPopup: { open: boolean; }; opsModal: { From e9167f2bd9a1b266855f649b36ca6487747e7a4f Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Mon, 9 Dec 2024 15:10:43 +0800 Subject: [PATCH 013/143] fix: moving things around --- .../src/git/sagas/checkoutBranchSaga.ts | 4 +-- app/client/src/git/sagas/commitSaga.ts | 4 +-- app/client/src/git/sagas/connectSaga.ts | 4 +-- app/client/src/git/sagas/createBranchSaga.ts | 4 +-- app/client/src/git/sagas/deleteBranchSaga.ts | 4 +-- app/client/src/git/sagas/fetchBranchesSaga.ts | 4 +-- .../src/git/sagas/updateGlobalProfileSaga.ts | 2 +- .../src/git/sagas/updateLocalProfileSaga.ts | 6 ++-- .../actions/checkoutBranchActions.ts | 0 .../git/{ => store}/actions/commitActions.ts | 0 .../git/{ => store}/actions/connectActions.ts | 0 .../actions/createBranchActions.ts | 0 .../actions/deleteBranchActions.ts | 2 +- .../git/{ => store}/actions/discardActions.ts | 0 .../{ => store}/actions/disconnectActions.ts | 0 .../actions/fetchAutocommitProgressActions.ts | 0 .../actions/fetchBranchesActions.ts | 2 +- .../actions/fetchGlobalProfileActions.ts | 0 .../actions/fetchLocalProfileActions.ts | 0 .../actions/fetchMergeStatusActions.ts | 0 .../actions/fetchMetadataActions.ts | 0 .../actions/fetchProtectedBranchesActions.ts | 0 .../{ => store}/actions/fetchSSHKeyActions.ts | 0 .../{ => store}/actions/fetchStatusActions.ts | 0 .../git/{ => store}/actions/generateSSHKey.ts | 0 .../helpers/createSingleArtifactAction.ts | 0 .../helpers/singleArtifactInitialState.ts | 2 +- .../git/{ => store}/actions/mergeActions.ts | 0 .../git/{ => store}/actions/mountActions.ts | 0 .../git/{ => store}/actions/pullActions.ts | 0 .../actions/toggleAutocommitActions.ts | 0 .../actions/triggerAutocommitActions.ts | 0 .../src/git/{ => store}/actions/uiActions.ts | 0 .../actions/updateGlobalProfileActions.ts | 0 .../actions/updateLocalProfileActions.ts | 0 .../actions/updateProtectedBranchesActions.ts | 0 app/client/src/git/store/gitArtifactSlice.ts | 34 +++++++++++-------- app/client/src/git/store/gitConfigSlice.ts | 6 ++-- app/client/src/git/{ => store}/types.ts | 8 ++--- 39 files changed, 46 insertions(+), 40 deletions(-) rename app/client/src/git/{ => store}/actions/checkoutBranchActions.ts (100%) rename app/client/src/git/{ => store}/actions/commitActions.ts (100%) rename app/client/src/git/{ => store}/actions/connectActions.ts (100%) rename app/client/src/git/{ => store}/actions/createBranchActions.ts (100%) rename app/client/src/git/{ => store}/actions/deleteBranchActions.ts (90%) rename app/client/src/git/{ => store}/actions/discardActions.ts (100%) rename app/client/src/git/{ => store}/actions/disconnectActions.ts (100%) rename app/client/src/git/{ => store}/actions/fetchAutocommitProgressActions.ts (100%) rename app/client/src/git/{ => store}/actions/fetchBranchesActions.ts (95%) rename app/client/src/git/{ => store}/actions/fetchGlobalProfileActions.ts (100%) rename app/client/src/git/{ => store}/actions/fetchLocalProfileActions.ts (100%) rename app/client/src/git/{ => store}/actions/fetchMergeStatusActions.ts (100%) rename app/client/src/git/{ => store}/actions/fetchMetadataActions.ts (100%) rename app/client/src/git/{ => store}/actions/fetchProtectedBranchesActions.ts (100%) rename app/client/src/git/{ => store}/actions/fetchSSHKeyActions.ts (100%) rename app/client/src/git/{ => store}/actions/fetchStatusActions.ts (100%) rename app/client/src/git/{ => store}/actions/generateSSHKey.ts (100%) rename app/client/src/git/{ => store}/actions/helpers/createSingleArtifactAction.ts (100%) rename app/client/src/git/{ => store}/actions/helpers/singleArtifactInitialState.ts (98%) rename app/client/src/git/{ => store}/actions/mergeActions.ts (100%) rename app/client/src/git/{ => store}/actions/mountActions.ts (100%) rename app/client/src/git/{ => store}/actions/pullActions.ts (100%) rename app/client/src/git/{ => store}/actions/toggleAutocommitActions.ts (100%) rename app/client/src/git/{ => store}/actions/triggerAutocommitActions.ts (100%) rename app/client/src/git/{ => store}/actions/uiActions.ts (100%) rename app/client/src/git/{ => store}/actions/updateGlobalProfileActions.ts (100%) rename app/client/src/git/{ => store}/actions/updateLocalProfileActions.ts (100%) rename app/client/src/git/{ => store}/actions/updateProtectedBranchesActions.ts (100%) rename app/client/src/git/{ => store}/types.ts (90%) diff --git a/app/client/src/git/sagas/checkoutBranchSaga.ts b/app/client/src/git/sagas/checkoutBranchSaga.ts index 3af5dc252698..bacb2a283c38 100644 --- a/app/client/src/git/sagas/checkoutBranchSaga.ts +++ b/app/client/src/git/sagas/checkoutBranchSaga.ts @@ -1,5 +1,5 @@ import { call, put, select, take } from "redux-saga/effects"; -import type { CheckoutBranchInitPayload } from "../actions/checkoutBranchActions"; +import type { CheckoutBranchInitPayload } from "../store/actions/checkoutBranchActions"; import { GitArtifactType } from "../constants/enums"; import checkoutBranchRequest from "../requests/checkoutBranchRequest"; import type { @@ -7,7 +7,7 @@ import type { CheckoutBranchResponse, } from "../requests/checkoutBranchRequest.types"; import { gitArtifactActions } from "../store/gitArtifactSlice"; -import type { GitArtifactPayloadAction } from "../types"; +import type { GitArtifactPayloadAction } from "../store/types"; // internal dependencies import { builderURL } from "ee/RouteBuilder"; diff --git a/app/client/src/git/sagas/commitSaga.ts b/app/client/src/git/sagas/commitSaga.ts index d1926f5b5412..e609a8f5145a 100644 --- a/app/client/src/git/sagas/commitSaga.ts +++ b/app/client/src/git/sagas/commitSaga.ts @@ -1,4 +1,4 @@ -import type { CommitInitPayload } from "../actions/commitActions"; +import type { CommitInitPayload } from "../store/actions/commitActions"; import { GitArtifactType, GitErrorCodes } from "../constants/enums"; import commitRequest from "../requests/commitRequest"; import type { @@ -6,7 +6,7 @@ import type { CommitResponse, } from "../requests/commitRequest.types"; import { gitArtifactActions } from "../store/gitArtifactSlice"; -import type { GitArtifactPayloadAction } from "../types"; +import type { GitArtifactPayloadAction } from "../store/types"; import { call, put } from "redux-saga/effects"; // internal dependencies diff --git a/app/client/src/git/sagas/connectSaga.ts b/app/client/src/git/sagas/connectSaga.ts index a3964934253a..16d4ba1cbe0e 100644 --- a/app/client/src/git/sagas/connectSaga.ts +++ b/app/client/src/git/sagas/connectSaga.ts @@ -5,8 +5,8 @@ import type { ConnectResponse, } from "../requests/connectRequest.types"; import { GitArtifactType, GitErrorCodes } from "../constants/enums"; -import type { GitArtifactPayloadAction } from "../types"; -import type { ConnectInitPayload } from "../actions/connectActions"; +import type { GitArtifactPayloadAction } from "../store/types"; +import type { ConnectInitPayload } from "../store/actions/connectActions"; import { call, put } from "redux-saga/effects"; diff --git a/app/client/src/git/sagas/createBranchSaga.ts b/app/client/src/git/sagas/createBranchSaga.ts index 16a7fd8ca3f6..37ce2de1afaf 100644 --- a/app/client/src/git/sagas/createBranchSaga.ts +++ b/app/client/src/git/sagas/createBranchSaga.ts @@ -1,12 +1,12 @@ import { call, put } from "redux-saga/effects"; -import type { CreateBranchInitPayload } from "../actions/createBranchActions"; +import type { CreateBranchInitPayload } from "../store/actions/createBranchActions"; import createBranchRequest from "../requests/createBranchRequest"; import type { CreateBranchRequestParams, CreateBranchResponse, } from "../requests/createBranchRequest.types"; import { gitArtifactActions } from "../store/gitArtifactSlice"; -import type { GitArtifactPayloadAction } from "../types"; +import type { GitArtifactPayloadAction } from "../store/types"; // internal dependencies import { validateResponse } from "sagas/ErrorSagas"; diff --git a/app/client/src/git/sagas/deleteBranchSaga.ts b/app/client/src/git/sagas/deleteBranchSaga.ts index d9e7dcd51891..7b138685e6a9 100644 --- a/app/client/src/git/sagas/deleteBranchSaga.ts +++ b/app/client/src/git/sagas/deleteBranchSaga.ts @@ -1,11 +1,11 @@ -import type { DeleteBranchInitPayload } from "../actions/deleteBranchActions"; +import type { DeleteBranchInitPayload } from "../store/actions/deleteBranchActions"; import deleteBranchRequest from "../requests/deleteBranchRequest"; import type { DeleteBranchRequestParams, DeleteBranchResponse, } from "../requests/deleteBranchRequest.types"; import { gitArtifactActions } from "../store/gitArtifactSlice"; -import type { GitArtifactPayloadAction } from "../types"; +import type { GitArtifactPayloadAction } from "../store/types"; import { call, put } from "redux-saga/effects"; // internal dependencies diff --git a/app/client/src/git/sagas/fetchBranchesSaga.ts b/app/client/src/git/sagas/fetchBranchesSaga.ts index 0a10286f91df..5909b62e0c45 100644 --- a/app/client/src/git/sagas/fetchBranchesSaga.ts +++ b/app/client/src/git/sagas/fetchBranchesSaga.ts @@ -1,11 +1,11 @@ -import type { FetchBranchesInitPayload } from "git/actions/fetchBranchesActions"; +import type { FetchBranchesInitPayload } from "../store/actions/fetchBranchesActions"; import fetchBranchesRequest from "git/requests/fetchBranchesRequest"; import type { FetchBranchesRequestParams, FetchBranchesResponse, } from "git/requests/fetchBranchesRequest.types"; import { gitArtifactActions } from "git/store/gitArtifactSlice"; -import type { GitArtifactPayloadAction } from "git/types"; +import type { GitArtifactPayloadAction } from "../store/types"; import { call, put } from "redux-saga/effects"; import { validateResponse } from "sagas/ErrorSagas"; diff --git a/app/client/src/git/sagas/updateGlobalProfileSaga.ts b/app/client/src/git/sagas/updateGlobalProfileSaga.ts index 24d22cc144c9..967d6228a0a0 100644 --- a/app/client/src/git/sagas/updateGlobalProfileSaga.ts +++ b/app/client/src/git/sagas/updateGlobalProfileSaga.ts @@ -1,6 +1,6 @@ import type { PayloadAction } from "@reduxjs/toolkit"; import { call, put } from "redux-saga/effects"; -import type { UpdateGlobalProfileInitPayload } from "../actions/updateGlobalProfileActions"; +import type { UpdateGlobalProfileInitPayload } from "../store/actions/updateGlobalProfileActions"; import updateGlobalProfileRequest from "../requests/updateGlobalProfileRequest"; import type { UpdateGlobalProfileRequestParams, diff --git a/app/client/src/git/sagas/updateLocalProfileSaga.ts b/app/client/src/git/sagas/updateLocalProfileSaga.ts index 21923693a322..d2a9c0243a15 100644 --- a/app/client/src/git/sagas/updateLocalProfileSaga.ts +++ b/app/client/src/git/sagas/updateLocalProfileSaga.ts @@ -1,11 +1,11 @@ -import type { UpdateLocalProfileInitPayload } from "git/actions/updateLocalProfileActions"; +import type { UpdateLocalProfileInitPayload } from "../store/actions/updateLocalProfileActions"; import updateLocalProfileRequest from "git/requests/updateLocalProfileRequest"; import type { UpdateLocalProfileRequestParams, UpdateLocalProfileResponse, } from "git/requests/updateLocalProfileRequest.types"; -import { gitArtifactActions } from "git/store/gitArtifactSlice"; -import type { GitArtifactPayloadAction } from "git/types"; +import { gitArtifactActions } from "../store/gitArtifactSlice"; +import type { GitArtifactPayloadAction } from "../store/types"; import { call, put } from "redux-saga/effects"; import { validateResponse } from "sagas/ErrorSagas"; diff --git a/app/client/src/git/actions/checkoutBranchActions.ts b/app/client/src/git/store/actions/checkoutBranchActions.ts similarity index 100% rename from app/client/src/git/actions/checkoutBranchActions.ts rename to app/client/src/git/store/actions/checkoutBranchActions.ts diff --git a/app/client/src/git/actions/commitActions.ts b/app/client/src/git/store/actions/commitActions.ts similarity index 100% rename from app/client/src/git/actions/commitActions.ts rename to app/client/src/git/store/actions/commitActions.ts diff --git a/app/client/src/git/actions/connectActions.ts b/app/client/src/git/store/actions/connectActions.ts similarity index 100% rename from app/client/src/git/actions/connectActions.ts rename to app/client/src/git/store/actions/connectActions.ts diff --git a/app/client/src/git/actions/createBranchActions.ts b/app/client/src/git/store/actions/createBranchActions.ts similarity index 100% rename from app/client/src/git/actions/createBranchActions.ts rename to app/client/src/git/store/actions/createBranchActions.ts diff --git a/app/client/src/git/actions/deleteBranchActions.ts b/app/client/src/git/store/actions/deleteBranchActions.ts similarity index 90% rename from app/client/src/git/actions/deleteBranchActions.ts rename to app/client/src/git/store/actions/deleteBranchActions.ts index a09552373b75..c90ca96b1669 100644 --- a/app/client/src/git/actions/deleteBranchActions.ts +++ b/app/client/src/git/store/actions/deleteBranchActions.ts @@ -1,6 +1,6 @@ import { createSingleArtifactAction } from "./helpers/createSingleArtifactAction"; import type { GitAsyncErrorPayload } from "../types"; -import type { DeleteBranchRequestParams } from "git/requests/deleteBranchRequest.types"; +import type { DeleteBranchRequestParams } from "../../requests/deleteBranchRequest.types"; export interface DeleteBranchInitPayload extends DeleteBranchRequestParams {} diff --git a/app/client/src/git/actions/discardActions.ts b/app/client/src/git/store/actions/discardActions.ts similarity index 100% rename from app/client/src/git/actions/discardActions.ts rename to app/client/src/git/store/actions/discardActions.ts diff --git a/app/client/src/git/actions/disconnectActions.ts b/app/client/src/git/store/actions/disconnectActions.ts similarity index 100% rename from app/client/src/git/actions/disconnectActions.ts rename to app/client/src/git/store/actions/disconnectActions.ts diff --git a/app/client/src/git/actions/fetchAutocommitProgressActions.ts b/app/client/src/git/store/actions/fetchAutocommitProgressActions.ts similarity index 100% rename from app/client/src/git/actions/fetchAutocommitProgressActions.ts rename to app/client/src/git/store/actions/fetchAutocommitProgressActions.ts diff --git a/app/client/src/git/actions/fetchBranchesActions.ts b/app/client/src/git/store/actions/fetchBranchesActions.ts similarity index 95% rename from app/client/src/git/actions/fetchBranchesActions.ts rename to app/client/src/git/store/actions/fetchBranchesActions.ts index 30f71574dc52..956bde6e92f3 100644 --- a/app/client/src/git/actions/fetchBranchesActions.ts +++ b/app/client/src/git/store/actions/fetchBranchesActions.ts @@ -1,7 +1,7 @@ import type { FetchBranchesRequestParams, FetchBranchesResponseData, -} from "../requests/fetchBranchesRequest.types"; +} from "../../requests/fetchBranchesRequest.types"; import type { GitAsyncErrorPayload, GitAsyncSuccessPayload } from "../types"; import { createSingleArtifactAction } from "./helpers/createSingleArtifactAction"; diff --git a/app/client/src/git/actions/fetchGlobalProfileActions.ts b/app/client/src/git/store/actions/fetchGlobalProfileActions.ts similarity index 100% rename from app/client/src/git/actions/fetchGlobalProfileActions.ts rename to app/client/src/git/store/actions/fetchGlobalProfileActions.ts diff --git a/app/client/src/git/actions/fetchLocalProfileActions.ts b/app/client/src/git/store/actions/fetchLocalProfileActions.ts similarity index 100% rename from app/client/src/git/actions/fetchLocalProfileActions.ts rename to app/client/src/git/store/actions/fetchLocalProfileActions.ts diff --git a/app/client/src/git/actions/fetchMergeStatusActions.ts b/app/client/src/git/store/actions/fetchMergeStatusActions.ts similarity index 100% rename from app/client/src/git/actions/fetchMergeStatusActions.ts rename to app/client/src/git/store/actions/fetchMergeStatusActions.ts diff --git a/app/client/src/git/actions/fetchMetadataActions.ts b/app/client/src/git/store/actions/fetchMetadataActions.ts similarity index 100% rename from app/client/src/git/actions/fetchMetadataActions.ts rename to app/client/src/git/store/actions/fetchMetadataActions.ts diff --git a/app/client/src/git/actions/fetchProtectedBranchesActions.ts b/app/client/src/git/store/actions/fetchProtectedBranchesActions.ts similarity index 100% rename from app/client/src/git/actions/fetchProtectedBranchesActions.ts rename to app/client/src/git/store/actions/fetchProtectedBranchesActions.ts diff --git a/app/client/src/git/actions/fetchSSHKeyActions.ts b/app/client/src/git/store/actions/fetchSSHKeyActions.ts similarity index 100% rename from app/client/src/git/actions/fetchSSHKeyActions.ts rename to app/client/src/git/store/actions/fetchSSHKeyActions.ts diff --git a/app/client/src/git/actions/fetchStatusActions.ts b/app/client/src/git/store/actions/fetchStatusActions.ts similarity index 100% rename from app/client/src/git/actions/fetchStatusActions.ts rename to app/client/src/git/store/actions/fetchStatusActions.ts diff --git a/app/client/src/git/actions/generateSSHKey.ts b/app/client/src/git/store/actions/generateSSHKey.ts similarity index 100% rename from app/client/src/git/actions/generateSSHKey.ts rename to app/client/src/git/store/actions/generateSSHKey.ts diff --git a/app/client/src/git/actions/helpers/createSingleArtifactAction.ts b/app/client/src/git/store/actions/helpers/createSingleArtifactAction.ts similarity index 100% rename from app/client/src/git/actions/helpers/createSingleArtifactAction.ts rename to app/client/src/git/store/actions/helpers/createSingleArtifactAction.ts diff --git a/app/client/src/git/actions/helpers/singleArtifactInitialState.ts b/app/client/src/git/store/actions/helpers/singleArtifactInitialState.ts similarity index 98% rename from app/client/src/git/actions/helpers/singleArtifactInitialState.ts rename to app/client/src/git/store/actions/helpers/singleArtifactInitialState.ts index 1dd40332ff60..5c210b925a67 100644 --- a/app/client/src/git/actions/helpers/singleArtifactInitialState.ts +++ b/app/client/src/git/store/actions/helpers/singleArtifactInitialState.ts @@ -3,7 +3,7 @@ import { GitImportStep, GitOpsTab, GitSettingsTab, -} from "../../constants/enums"; +} from "../../../constants/enums"; import type { GitSingleArtifactAPIResponsesReduxState, GitSingleArtifactUIReduxState, diff --git a/app/client/src/git/actions/mergeActions.ts b/app/client/src/git/store/actions/mergeActions.ts similarity index 100% rename from app/client/src/git/actions/mergeActions.ts rename to app/client/src/git/store/actions/mergeActions.ts diff --git a/app/client/src/git/actions/mountActions.ts b/app/client/src/git/store/actions/mountActions.ts similarity index 100% rename from app/client/src/git/actions/mountActions.ts rename to app/client/src/git/store/actions/mountActions.ts diff --git a/app/client/src/git/actions/pullActions.ts b/app/client/src/git/store/actions/pullActions.ts similarity index 100% rename from app/client/src/git/actions/pullActions.ts rename to app/client/src/git/store/actions/pullActions.ts diff --git a/app/client/src/git/actions/toggleAutocommitActions.ts b/app/client/src/git/store/actions/toggleAutocommitActions.ts similarity index 100% rename from app/client/src/git/actions/toggleAutocommitActions.ts rename to app/client/src/git/store/actions/toggleAutocommitActions.ts diff --git a/app/client/src/git/actions/triggerAutocommitActions.ts b/app/client/src/git/store/actions/triggerAutocommitActions.ts similarity index 100% rename from app/client/src/git/actions/triggerAutocommitActions.ts rename to app/client/src/git/store/actions/triggerAutocommitActions.ts diff --git a/app/client/src/git/actions/uiActions.ts b/app/client/src/git/store/actions/uiActions.ts similarity index 100% rename from app/client/src/git/actions/uiActions.ts rename to app/client/src/git/store/actions/uiActions.ts diff --git a/app/client/src/git/actions/updateGlobalProfileActions.ts b/app/client/src/git/store/actions/updateGlobalProfileActions.ts similarity index 100% rename from app/client/src/git/actions/updateGlobalProfileActions.ts rename to app/client/src/git/store/actions/updateGlobalProfileActions.ts diff --git a/app/client/src/git/actions/updateLocalProfileActions.ts b/app/client/src/git/store/actions/updateLocalProfileActions.ts similarity index 100% rename from app/client/src/git/actions/updateLocalProfileActions.ts rename to app/client/src/git/store/actions/updateLocalProfileActions.ts diff --git a/app/client/src/git/actions/updateProtectedBranchesActions.ts b/app/client/src/git/store/actions/updateProtectedBranchesActions.ts similarity index 100% rename from app/client/src/git/actions/updateProtectedBranchesActions.ts rename to app/client/src/git/store/actions/updateProtectedBranchesActions.ts diff --git a/app/client/src/git/store/gitArtifactSlice.ts b/app/client/src/git/store/gitArtifactSlice.ts index 898b8a1de575..000d665f73c3 100644 --- a/app/client/src/git/store/gitArtifactSlice.ts +++ b/app/client/src/git/store/gitArtifactSlice.ts @@ -1,66 +1,66 @@ /* eslint-disable padding-line-between-statements */ import { createSlice } from "@reduxjs/toolkit"; -import type { GitArtifactReduxState } from "../types"; -import { mountAction, unmountAction } from "../actions/mountActions"; +import type { GitArtifactReduxState } from "./types"; +import { mountAction, unmountAction } from "./actions/mountActions"; import { connectErrorAction, connectInitAction, connectSuccessAction, -} from "../actions/connectActions"; +} from "./actions/connectActions"; import { fetchMetadataErrorAction, fetchMetadataInitAction, fetchMetadataSuccessAction, -} from "../actions/fetchMetadataActions"; +} from "./actions/fetchMetadataActions"; import { fetchBranchesErrorAction, fetchBranchesInitAction, fetchBranchesSuccessAction, -} from "../actions/fetchBranchesActions"; +} from "./actions/fetchBranchesActions"; import { fetchStatusErrorAction, fetchStatusInitAction, fetchStatusSuccessAction, -} from "../actions/fetchStatusActions"; +} from "./actions/fetchStatusActions"; import { commitErrorAction, commitInitAction, commitSuccessAction, -} from "../actions/commitActions"; +} from "./actions/commitActions"; import { pullErrorAction, pullInitAction, pullSuccessAction, -} from "../actions/pullActions"; +} from "./actions/pullActions"; import { fetchLocalProfileErrorAction, fetchLocalProfileInitAction, fetchLocalProfileSuccessAction, -} from "git/actions/fetchLocalProfileActions"; +} from "./actions/fetchLocalProfileActions"; import { updateLocalProfileErrorAction, updateLocalProfileInitAction, updateLocalProfileSuccessAction, -} from "git/actions/updateLocalProfileActions"; +} from "./actions/updateLocalProfileActions"; import { createBranchErrorAction, createBranchInitAction, createBranchSuccessAction, -} from "git/actions/createBranchActions"; +} from "./actions/createBranchActions"; import { deleteBranchErrorAction, deleteBranchInitAction, deleteBranchSuccessAction, -} from "git/actions/deleteBranchActions"; +} from "./actions/deleteBranchActions"; import { toggleBranchListPopupAction, toggleRepoLimitErrorModalAction, -} from "git/actions/uiActions"; +} from "./actions/uiActions"; import { checkoutBranchErrorAction, checkoutBranchInitAction, checkoutBranchSuccessAction, -} from "git/actions/checkoutBranchActions"; +} from "./actions/checkoutBranchActions"; const initialState: GitArtifactReduxState = {}; @@ -112,6 +112,12 @@ export const gitArtifactSlice = createSlice({ toggleBranchListPopup: toggleBranchListPopupAction, toggleRepoLimitErrorModal: toggleRepoLimitErrorModalAction, }, + selectors: { + branches: (state, artifactType, baseArtifactId) => + state[artifactType][baseArtifactId].apiResponses.branches, + createBranch: (state, artifactType, baseArtifactId) => + state[artifactType][baseArtifactId].apiResponses.createBranch, + }, }); export const gitArtifactActions = gitArtifactSlice.actions; diff --git a/app/client/src/git/store/gitConfigSlice.ts b/app/client/src/git/store/gitConfigSlice.ts index 14cf0971b643..6bb28607b3bf 100644 --- a/app/client/src/git/store/gitConfigSlice.ts +++ b/app/client/src/git/store/gitConfigSlice.ts @@ -3,13 +3,13 @@ import { fetchGlobalProfileErrorAction, fetchGlobalProfileInitAction, fetchGlobalProfileSuccessAction, -} from "git/actions/fetchGlobalProfileActions"; +} from "./actions/fetchGlobalProfileActions"; import { updateGlobalProfileErrorAction, updateGlobalProfileInitAction, updateGlobalProfileSuccessAction, -} from "git/actions/updateGlobalProfileActions"; -import type { GitConfigReduxState } from "git/types"; +} from "./actions/updateGlobalProfileActions"; +import type { GitConfigReduxState } from "./types"; const initialState: GitConfigReduxState = { globalProfile: { diff --git a/app/client/src/git/types.ts b/app/client/src/git/store/types.ts similarity index 90% rename from app/client/src/git/types.ts rename to app/client/src/git/store/types.ts index 3a1b6c27b4b7..b6502ebf699f 100644 --- a/app/client/src/git/types.ts +++ b/app/client/src/git/store/types.ts @@ -5,10 +5,10 @@ import type { GitImportStep, GitOpsTab, GitSettingsTab, -} from "./constants/enums"; -import type { FetchGlobalProfileResponseData } from "./requests/fetchGlobalProfileRequest.types"; -import type { FetchBranchesResponseData } from "./requests/fetchBranchesRequest.types"; -import type { FetchLocalProfileResponseData } from "./requests/fetchLocalProfileRequest.types"; +} from "../constants/enums"; +import type { FetchGlobalProfileResponseData } from "../requests/fetchGlobalProfileRequest.types"; +import type { FetchBranchesResponseData } from "../requests/fetchBranchesRequest.types"; +import type { FetchLocalProfileResponseData } from "../requests/fetchLocalProfileRequest.types"; // These will be updated when contracts are finalized export type GitMetadata = Record; From d024160b83074cbd1d214762472b4c36080acdb1 Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Mon, 9 Dec 2024 21:19:45 +0800 Subject: [PATCH 014/143] chore: adding ctx --- .../ads/src/Icon/Icon.provider.tsx | 5 + app/client/src/components/BottomBar/index.tsx | 2 + .../CtxAwareGitQuickActions/index.tsx | 1 + .../hooks/useGitBranches.ts | 118 +++++++++++ .../components/GitContextProvider/index.tsx | 40 ++++ .../AutocommitStatusbar.test.tsx | 0 .../AutocommitStatusbar.tsx | 0 .../BranchButton/BranchList.tsx | 5 + .../GitQuickActions/BranchButton/index.tsx | 109 ++++++++++ .../ConnectButton.test.tsx | 19 +- .../ConnectButton.tsx | 32 +-- .../QuickActionButton.test.tsx | 0 .../QuickActionButton.tsx | 2 +- .../helpers/getPullButtonStatus.test.ts | 140 +++++++++++++ .../helpers/getPullButtonStatus.ts | 43 ++++ .../index.test.tsx | 40 ++-- .../git/components/GitQuickActions/index.tsx | 192 ++++++++++++++++++ .../components/QuickActions/helper.test.ts | 191 ----------------- .../git/components/QuickActions/helpers.ts | 45 ---- .../src/git/components/QuickActions/index.tsx | 183 ----------------- .../git/requests/fetchStatusRequest.types.ts | 7 +- .../src/git/sagas/fetchLocalProfileSaga.ts | 2 +- .../store/actions/checkoutBranchActions.ts | 2 +- .../src/git/store/actions/commitActions.ts | 2 +- .../src/git/store/actions/connectActions.ts | 2 +- .../git/store/actions/createBranchActions.ts | 2 +- .../git/store/actions/deleteBranchActions.ts | 2 +- .../src/git/store/actions/discardActions.ts | 2 +- .../git/store/actions/disconnectActions.ts | 2 +- .../actions/fetchAutocommitProgressActions.ts | 2 +- .../git/store/actions/fetchBranchesActions.ts | 2 +- .../store/actions/fetchLocalProfileActions.ts | 2 +- .../store/actions/fetchMergeStatusActions.ts | 2 +- .../git/store/actions/fetchMetadataActions.ts | 2 +- .../actions/fetchProtectedBranchesActions.ts | 2 +- .../git/store/actions/fetchSSHKeyActions.ts | 2 +- .../git/store/actions/fetchStatusActions.ts | 2 +- .../src/git/store/actions/generateSSHKey.ts | 2 +- .../src/git/store/actions/mergeActions.ts | 2 +- .../src/git/store/actions/mountActions.ts | 2 +- .../src/git/store/actions/pullActions.ts | 2 +- .../store/actions/toggleAutocommitActions.ts | 2 +- .../store/actions/triggerAutocommitActions.ts | 2 +- app/client/src/git/store/actions/uiActions.ts | 46 ++++- .../actions/updateLocalProfileActions.ts | 2 +- .../actions/updateProtectedBranchesActions.ts | 2 +- app/client/src/git/store/gitArtifactSlice.ts | 7 +- app/client/src/git/store/gitConfigSlice.ts | 16 +- .../helpers/createSingleArtifactAction.ts | 4 +- .../store/helpers/gitConfigInitialState.ts | 13 ++ .../gitSingleArtifactInitialState.ts} | 4 +- .../selectors/gitSingleArtifactSelectors.ts | 36 ++++ app/client/src/git/store/types.ts | 9 +- 53 files changed, 828 insertions(+), 529 deletions(-) create mode 100644 app/client/src/git/components/CtxAwareGitQuickActions/index.tsx create mode 100644 app/client/src/git/components/GitContextProvider/hooks/useGitBranches.ts create mode 100644 app/client/src/git/components/GitContextProvider/index.tsx rename app/client/src/git/components/{QuickActions => GitQuickActions}/AutocommitStatusbar.test.tsx (100%) rename app/client/src/git/components/{QuickActions => GitQuickActions}/AutocommitStatusbar.tsx (100%) create mode 100644 app/client/src/git/components/GitQuickActions/BranchButton/BranchList.tsx create mode 100644 app/client/src/git/components/GitQuickActions/BranchButton/index.tsx rename app/client/src/git/components/{QuickActions => GitQuickActions}/ConnectButton.test.tsx (90%) rename app/client/src/git/components/{QuickActions => GitQuickActions}/ConnectButton.tsx (72%) rename app/client/src/git/components/{QuickActions => GitQuickActions}/QuickActionButton.test.tsx (100%) rename app/client/src/git/components/{QuickActions => GitQuickActions}/QuickActionButton.tsx (97%) create mode 100644 app/client/src/git/components/GitQuickActions/helpers/getPullButtonStatus.test.ts create mode 100644 app/client/src/git/components/GitQuickActions/helpers/getPullButtonStatus.ts rename app/client/src/git/components/{QuickActions => GitQuickActions}/index.test.tsx (93%) create mode 100644 app/client/src/git/components/GitQuickActions/index.tsx delete mode 100644 app/client/src/git/components/QuickActions/helper.test.ts delete mode 100644 app/client/src/git/components/QuickActions/helpers.ts delete mode 100644 app/client/src/git/components/QuickActions/index.tsx rename app/client/src/git/store/{actions => }/helpers/createSingleArtifactAction.ts (89%) create mode 100644 app/client/src/git/store/helpers/gitConfigInitialState.ts rename app/client/src/git/store/{actions/helpers/singleArtifactInitialState.ts => helpers/gitSingleArtifactInitialState.ts} (97%) create mode 100644 app/client/src/git/store/selectors/gitSingleArtifactSelectors.ts diff --git a/app/client/packages/design-system/ads/src/Icon/Icon.provider.tsx b/app/client/packages/design-system/ads/src/Icon/Icon.provider.tsx index 5a5ff05eb1e0..065dd990a8fb 100644 --- a/app/client/packages/design-system/ads/src/Icon/Icon.provider.tsx +++ b/app/client/packages/design-system/ads/src/Icon/Icon.provider.tsx @@ -572,6 +572,10 @@ const AppsLineIcon = importRemixIcon( async () => import("remixicon-react/AppsLineIcon"), ); +const ProtectedIcon = importRemixIcon( + async () => import("remixicon-react/ShieldKeyholeLineIcon"), +); + const CornerDownLeftLineIcon = importSvg( async () => import("../__assets__/icons/ads/corner-down-left-line.svg"), ); @@ -1379,6 +1383,7 @@ const ICON_LOOKUP = { "warning-triangle": WarningTriangleIcon, "widgets-v3": WidgetsV3Icon, "workflows-mono": WorkflowsMonochromeIcon, + "protected-icon": ProtectedIcon, billing: BillingIcon, binding: Binding, book: BookIcon, diff --git a/app/client/src/components/BottomBar/index.tsx b/app/client/src/components/BottomBar/index.tsx index c40dbca3fc34..da11a533102d 100644 --- a/app/client/src/components/BottomBar/index.tsx +++ b/app/client/src/components/BottomBar/index.tsx @@ -15,6 +15,7 @@ import { useDispatch } from "react-redux"; import { softRefreshActions } from "actions/pluginActionActions"; import { START_SWITCH_ENVIRONMENT } from "ee/constants/messages"; import { getIsAnvilEnabledInCurrentApplication } from "layoutSystems/anvil/integrations/selectors"; +import GitTest from "git/components/connect/GitTest"; export default function BottomBar() { const appId = useSelector(getCurrentApplicationId) || ""; @@ -41,6 +42,7 @@ export default function BottomBar() { /> )} {!isPreviewMode && !isAnvilEnabled && } + {!isPreviewMode && ( diff --git a/app/client/src/git/components/CtxAwareGitQuickActions/index.tsx b/app/client/src/git/components/CtxAwareGitQuickActions/index.tsx new file mode 100644 index 000000000000..ff8b4c56321a --- /dev/null +++ b/app/client/src/git/components/CtxAwareGitQuickActions/index.tsx @@ -0,0 +1 @@ +export default {}; diff --git a/app/client/src/git/components/GitContextProvider/hooks/useGitBranches.ts b/app/client/src/git/components/GitContextProvider/hooks/useGitBranches.ts new file mode 100644 index 000000000000..2eb9f40a6d38 --- /dev/null +++ b/app/client/src/git/components/GitContextProvider/hooks/useGitBranches.ts @@ -0,0 +1,118 @@ +import type { GitArtifactType } from "git/constants/enums"; +import type { FetchBranchesResponseData } from "git/requests/fetchBranchesRequest.types"; +import { gitArtifactActions } from "git/store/gitArtifactSlice"; +import { + selectBranches, + selectCheckoutBranch, + selectCreateBranch, + selectDeleteBranch, +} from "git/store/selectors/gitSingleArtifactSelectors"; +import type { GitRootState } from "git/store/types"; +import { useCallback } from "react"; +import { useDispatch, useSelector } from "react-redux"; + +interface UseGitBranchesParams { + artifactType: keyof typeof GitArtifactType; + baseArtifactId: string; +} + +export interface UseGitBranchesReturns { + branches: FetchBranchesResponseData | null; + fetchBranchesLoading: boolean; + fetchBranchesError: string | null; + fetchBranches: () => void; + createBranchLoading: boolean; + createBranchError: string | null; + createBranch: (branchName: string) => void; + deleteBranchLoading: boolean; + deleteBranchError: string | null; + deleteBranch: (branchName: string) => void; + checkoutBranchLoading: boolean; + checkoutBranchError: string | null; + checkoutBranch: (branchName: string) => void; +} + +export default function useGitBranches({ + artifactType, + baseArtifactId, +}: UseGitBranchesParams): UseGitBranchesReturns { + const basePayload = { artifactType, baseArtifactId }; + const dispatch = useDispatch(); + // fetch branches + const branchesState = useSelector((state: GitRootState) => + selectBranches(state, basePayload), + ); + const fetchBranches = useCallback(() => { + dispatch( + gitArtifactActions.fetchBranchesInit({ + artifactType, + baseArtifactId, + pruneBranches: true, + }), + ); + }, [artifactType, baseArtifactId, dispatch]); + // create branch + const createBranchState = useSelector((state: GitRootState) => + selectCreateBranch(state, basePayload), + ); + const createBranch = useCallback( + (branchName: string) => { + dispatch( + gitArtifactActions.createBranchInit({ + artifactType, + baseArtifactId, + branchName, + }), + ); + }, + [artifactType, baseArtifactId, dispatch], + ); + // delete branch + const deleteBranchState = useSelector((state: GitRootState) => + selectDeleteBranch(state, basePayload), + ); + const deleteBranch = useCallback( + (branchName: string) => { + dispatch( + gitArtifactActions.deleteBranchInit({ + artifactType, + baseArtifactId, + branchName, + }), + ); + }, + [artifactType, baseArtifactId, dispatch], + ); + // checkout branch + const checkoutBranchState = useSelector((state: GitRootState) => + selectCheckoutBranch(state, basePayload), + ); + const checkoutBranch = useCallback( + (branchName: string) => { + dispatch( + gitArtifactActions.checkoutBranchInit({ + artifactType, + baseArtifactId, + branchName, + }), + ); + }, + [artifactType, baseArtifactId, dispatch], + ); + + return { + branches: branchesState?.value ?? null, + fetchBranchesLoading: branchesState?.loading ?? false, + fetchBranchesError: branchesState?.error ?? null, + fetchBranches, + createBranchLoading: createBranchState?.loading ?? false, + createBranchError: createBranchState?.error ?? null, + createBranch, + deleteBranchLoading: deleteBranchState?.loading ?? false, + deleteBranchError: deleteBranchState?.error ?? null, + deleteBranch, + checkoutBranchLoading: checkoutBranchState?.loading ?? false, + checkoutBranchError: checkoutBranchState?.error ?? null, + checkoutBranch, + }; +} diff --git a/app/client/src/git/components/GitContextProvider/index.tsx b/app/client/src/git/components/GitContextProvider/index.tsx new file mode 100644 index 000000000000..6deab437d947 --- /dev/null +++ b/app/client/src/git/components/GitContextProvider/index.tsx @@ -0,0 +1,40 @@ +import React, { createContext, useEffect } from "react"; +import useGitBranches from "./hooks/useGitBranches"; +import type { UseGitBranchesReturns } from "./hooks/useGitBranches"; +import type { GitArtifactType } from "git/constants/enums"; + +interface GitContextValue extends UseGitBranchesReturns {} + +const gitContextInitialValue = {} as GitContextValue; + +export const GitContext = createContext(gitContextInitialValue); + +interface GitContextProviderProps { + artifactType: keyof typeof GitArtifactType; + baseArtifactId: string; + children: React.ReactNode; +} + +export default function GitContextProvider({ + artifactType, + baseArtifactId, + children, +}: GitContextProviderProps) { + const useGitBranchesReturns = useGitBranches({ + artifactType, + baseArtifactId, + }); + + useEffect(function gitInitEffect() { + useGitBranchesReturns.fetchBranches(); + }, []); + + // eslint-disable-next-line react-perf/jsx-no-new-object-as-prop + const contextValue = { + ...useGitBranchesReturns, + } as GitContextValue; + + return ( + {children} + ); +} diff --git a/app/client/src/git/components/QuickActions/AutocommitStatusbar.test.tsx b/app/client/src/git/components/GitQuickActions/AutocommitStatusbar.test.tsx similarity index 100% rename from app/client/src/git/components/QuickActions/AutocommitStatusbar.test.tsx rename to app/client/src/git/components/GitQuickActions/AutocommitStatusbar.test.tsx diff --git a/app/client/src/git/components/QuickActions/AutocommitStatusbar.tsx b/app/client/src/git/components/GitQuickActions/AutocommitStatusbar.tsx similarity index 100% rename from app/client/src/git/components/QuickActions/AutocommitStatusbar.tsx rename to app/client/src/git/components/GitQuickActions/AutocommitStatusbar.tsx diff --git a/app/client/src/git/components/GitQuickActions/BranchButton/BranchList.tsx b/app/client/src/git/components/GitQuickActions/BranchButton/BranchList.tsx new file mode 100644 index 000000000000..4a582fc0ed47 --- /dev/null +++ b/app/client/src/git/components/GitQuickActions/BranchButton/BranchList.tsx @@ -0,0 +1,5 @@ +import React from "react"; + +export default function BranchList() { + return
Test
; +} diff --git a/app/client/src/git/components/GitQuickActions/BranchButton/index.tsx b/app/client/src/git/components/GitQuickActions/BranchButton/index.tsx new file mode 100644 index 000000000000..466b8f961e5d --- /dev/null +++ b/app/client/src/git/components/GitQuickActions/BranchButton/index.tsx @@ -0,0 +1,109 @@ +import { Button, Icon, Tooltip } from "@appsmith/ads"; +import React, { useCallback } from "react"; +import styled from "styled-components"; +import noop from "lodash/noop"; +import BranchList from "./BranchList"; +import { Popover2 } from "@blueprintjs/popover2"; + +// internal dependencies +import { isEllipsisActive } from "utils/helpers"; +import AnalyticsUtil from "ee/utils/AnalyticsUtil"; + +interface BranchButtonProps { + currentBranch?: string; + isOpen?: boolean; + setIsOpen?: (isOpen: boolean) => void; + isDisabled?: boolean; + isProtectedMode?: false; + isStatusClean?: boolean; +} + +const ButtonContainer = styled(Button)` + display: flex; + align-items: center; + margin: 0 ${(props) => props.theme.spaces[4]}px; + max-width: 122px; + min-width: unset !important; + + :active { + border: 1px solid var(--ads-v2-color-border-muted); + } +`; + +const BranchButtonIcon = styled(Icon)` + margin-right: 4px; +`; + +const BranchButtonLabel = styled.span` + max-width: 82px; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +`; + +export default function BranchButton({ + currentBranch = "", + isDisabled = false, + isOpen = false, + isProtectedMode = false, + isStatusClean = false, + setIsOpen = noop, +}: BranchButtonProps) { + const labelTarget = React.useRef(null); + + const onPopoverInteraction = useCallback( + (nextState: boolean) => { + setIsOpen(nextState); + + if (nextState) { + AnalyticsUtil.logEvent("GS_OPEN_BRANCH_LIST_POPUP", { + source: "BOTTOM_BAR_ACTIVE_BRANCH_NAME", + }); + } + }, + [setIsOpen], + ); + + const renderContent = useCallback(() => { + return ; + }, []); + + return ( + + + + {isProtectedMode ? ( + + ) : ( + + )} + + {currentBranch} + + {!isStatusClean && !isProtectedMode && "*"} + + + + ); +} diff --git a/app/client/src/git/components/QuickActions/ConnectButton.test.tsx b/app/client/src/git/components/GitQuickActions/ConnectButton.test.tsx similarity index 90% rename from app/client/src/git/components/QuickActions/ConnectButton.test.tsx rename to app/client/src/git/components/GitQuickActions/ConnectButton.test.tsx index 3b017c0c018f..71406cd399c4 100644 --- a/app/client/src/git/components/QuickActions/ConnectButton.test.tsx +++ b/app/client/src/git/components/GitQuickActions/ConnectButton.test.tsx @@ -36,10 +36,7 @@ describe("ConnectButton Component", () => { it("should render correctly when isConnectPermitted is true", () => { render( - + , ); @@ -64,10 +61,7 @@ describe("ConnectButton Component", () => { it("should handle click when isConnectPermitted is true", () => { render( - + , ); @@ -92,7 +86,7 @@ describe("ConnectButton Component", () => { , ); @@ -123,7 +117,7 @@ describe("ConnectButton Component", () => { , ); @@ -139,10 +133,7 @@ describe("ConnectButton Component", () => { it("should display correct tooltip content when isConnectPermitted is true", () => { render( - + , ); diff --git a/app/client/src/git/components/QuickActions/ConnectButton.tsx b/app/client/src/git/components/GitQuickActions/ConnectButton.tsx similarity index 72% rename from app/client/src/git/components/QuickActions/ConnectButton.tsx rename to app/client/src/git/components/GitQuickActions/ConnectButton.tsx index 426b2a05ec85..4ea835d79a2e 100644 --- a/app/client/src/git/components/QuickActions/ConnectButton.tsx +++ b/app/client/src/git/components/GitQuickActions/ConnectButton.tsx @@ -1,5 +1,4 @@ -import React, { useCallback, useMemo } from "react"; -import { GitSyncModalTab } from "entities/GitSync"; +import React, { useMemo } from "react"; import styled from "styled-components"; import { COMING_SOON, @@ -8,13 +7,8 @@ import { createMessage, NOT_LIVE_FOR_YOU_YET, } from "ee/constants/messages"; -import AnalyticsUtil from "ee/utils/AnalyticsUtil"; -import { Button, Icon, Tooltip } from "@appsmith/ads"; -interface ConnectButtonProps { - isConnectPermitted: boolean; - openGitSyncModal: (options: { tab: GitSyncModalTab }) => void; -} +import { Button, Icon, Tooltip } from "@appsmith/ads"; const CenterDiv = styled.div` text-align: center; @@ -38,10 +32,12 @@ const OuterContainer = styled.div` height: 100%; `; -function ConnectButton({ - isConnectPermitted, - openGitSyncModal, -}: ConnectButtonProps) { +interface ConnectButtonProps { + isConnectPermitted: boolean; + onClick: () => void; +} + +function ConnectButton({ isConnectPermitted, onClick }: ConnectButtonProps) { const isTooltipEnabled = !isConnectPermitted; const tooltipContent = useMemo(() => { if (!isConnectPermitted) { @@ -56,16 +52,6 @@ function ConnectButton({ ); }, [isConnectPermitted]); - const handleClickOnGitConnect = useCallback(() => { - AnalyticsUtil.logEvent("GS_CONNECT_GIT_CLICK", { - source: "BOTTOM_BAR_GIT_CONNECT_BUTTON", - }); - - openGitSyncModal({ - tab: GitSyncModalTab.GIT_CONNECTION, - }); - }, [openGitSyncModal]); - return ( @@ -79,7 +65,7 @@ function ConnectButton({ className="t--connect-git-bottom-bar" isDisabled={!isConnectPermitted} kind="secondary" - onClick={handleClickOnGitConnect} + onClick={onClick} size="sm" > {createMessage(CONNECT_GIT_BETA)} diff --git a/app/client/src/git/components/QuickActions/QuickActionButton.test.tsx b/app/client/src/git/components/GitQuickActions/QuickActionButton.test.tsx similarity index 100% rename from app/client/src/git/components/QuickActions/QuickActionButton.test.tsx rename to app/client/src/git/components/GitQuickActions/QuickActionButton.test.tsx diff --git a/app/client/src/git/components/QuickActions/QuickActionButton.tsx b/app/client/src/git/components/GitQuickActions/QuickActionButton.tsx similarity index 97% rename from app/client/src/git/components/QuickActions/QuickActionButton.tsx rename to app/client/src/git/components/GitQuickActions/QuickActionButton.tsx index 42d7721ab297..c22306b748fa 100644 --- a/app/client/src/git/components/QuickActions/QuickActionButton.tsx +++ b/app/client/src/git/components/GitQuickActions/QuickActionButton.tsx @@ -1,9 +1,9 @@ import React from "react"; import styled from "styled-components"; -import { capitalizeFirstLetter } from "./helpers"; import SpinnerLoader from "pages/common/SpinnerLoader"; import { Button, Tooltip, Text } from "@appsmith/ads"; import { getTypographyByKey } from "@appsmith/ads-old"; +import { capitalizeFirstLetter } from "utils/helpers"; interface QuickActionButtonProps { className?: string; diff --git a/app/client/src/git/components/GitQuickActions/helpers/getPullButtonStatus.test.ts b/app/client/src/git/components/GitQuickActions/helpers/getPullButtonStatus.test.ts new file mode 100644 index 000000000000..6a221fe2ea9b --- /dev/null +++ b/app/client/src/git/components/GitQuickActions/helpers/getPullButtonStatus.test.ts @@ -0,0 +1,140 @@ +import getPullBtnStatus from "./getPullButtonStatus"; +import type { GetPullButtonStatusParams } from "./getPullButtonStatus"; + +describe("getPullBtnStatus", () => { + afterEach(() => { + jest.clearAllMocks(); + }); + + it('should return disabled with message "No commits to pull" when behindCount is 0', () => { + const params: GetPullButtonStatusParams = { + isProtectedMode: false, + isPullFailing: false, + isStatusClean: true, + statusBehindCount: 0, + }; + + const result = getPullBtnStatus(params); + + expect(result).toEqual({ + isDisabled: true, + message: + "No commits to pull. This branch is in sync with the remote repository", + }); + }); + + it('should return disabled with message "Cannot pull with local uncommitted changes" when isClean is false and isProtectedMode is false', () => { + const params: GetPullButtonStatusParams = { + isProtectedMode: false, + isPullFailing: false, + isStatusClean: false, + statusBehindCount: 5, + }; + + const result = getPullBtnStatus(params); + + expect(result).toEqual({ + isDisabled: true, + message: + "You have uncommitted changes. Please commit or discard before pulling the remote changes.", + }); + }); + + it('should return enabled with message "Pull changes" when isClean is false, isProtectedMode is true, and behindCount > 0', () => { + const params: GetPullButtonStatusParams = { + isProtectedMode: true, + isPullFailing: false, + isStatusClean: false, + statusBehindCount: 3, + }; + + const result = getPullBtnStatus(params); + + expect(result).toEqual({ + isDisabled: false, + message: "Pull changes", + }); + }); + + it('should return message "Conflicts found" when pullFailed is true', () => { + const params: GetPullButtonStatusParams = { + isProtectedMode: false, + isPullFailing: true, + isStatusClean: true, + statusBehindCount: 2, + }; + + const result = getPullBtnStatus(params); + + expect(result).toEqual({ + isDisabled: false, + message: "Conflicts found. Please resolve them and pull again.", + }); + }); + + it('should return enabled with message "Pull changes" when behindCount > 0 and no other conditions met', () => { + const params: GetPullButtonStatusParams = { + isProtectedMode: false, + isPullFailing: false, + isStatusClean: true, + statusBehindCount: 1, + }; + + const result = getPullBtnStatus(params); + + expect(result).toEqual({ + isDisabled: false, + message: "Pull changes", + }); + }); + + it('should return disabled with message "No commits to pull" when behindCount is 0 regardless of isClean and isProtectedMode', () => { + const params: GetPullButtonStatusParams = { + isProtectedMode: true, + isPullFailing: false, + isStatusClean: false, + statusBehindCount: 0, + }; + + const result = getPullBtnStatus(params); + + expect(result).toEqual({ + disabled: true, + message: + "No commits to pull. This branch is in sync with the remote repository", + }); + }); + + it("should prioritize pullFailed over other conditions", () => { + const params: GetPullButtonStatusParams = { + isProtectedMode: false, + isPullFailing: true, + isStatusClean: true, + statusBehindCount: 0, + }; + + const result = getPullBtnStatus(params); + + expect(result).toEqual({ + isDisabled: true, + message: "Conflicts found. Please resolve them and pull again.", + }); + }); + + it("should handle edge case when isClean is false, isProtectedMode is true, behindCount is 0", () => { + const params: GetPullButtonStatusParams = { + isProtectedMode: true, + isPullFailing: false, + isStatusClean: false, + statusBehindCount: 0, + }; + + const result = getPullBtnStatus(params); + + expect(result).toEqual({ + isDisabled: true, + message: + "No commits to pull. This branch is in sync with the remote repository", + }); + }); +}); diff --git a/app/client/src/git/components/GitQuickActions/helpers/getPullButtonStatus.ts b/app/client/src/git/components/GitQuickActions/helpers/getPullButtonStatus.ts new file mode 100644 index 000000000000..ad300d8f6685 --- /dev/null +++ b/app/client/src/git/components/GitQuickActions/helpers/getPullButtonStatus.ts @@ -0,0 +1,43 @@ +import { + CANNOT_PULL_WITH_LOCAL_UNCOMMITTED_CHANGES, + CONFLICTS_FOUND, + createMessage, + NO_COMMITS_TO_PULL, + PULL_CHANGES, +} from "ee/constants/messages"; + +export interface GetPullButtonStatusParams { + isProtectedMode: boolean; + isStatusClean: boolean; + isPullFailing: boolean; + statusBehindCount: number; +} + +const getPullBtnStatus = ({ + isProtectedMode = false, + isPullFailing = false, + isStatusClean = false, + statusBehindCount = 0, +}: GetPullButtonStatusParams) => { + let message = createMessage(NO_COMMITS_TO_PULL); + let isDisabled = statusBehindCount === 0; + + if (!isStatusClean && !isProtectedMode) { + isDisabled = true; + message = createMessage(CANNOT_PULL_WITH_LOCAL_UNCOMMITTED_CHANGES); + } else if (!isStatusClean && isProtectedMode && statusBehindCount > 0) { + isDisabled = false; + message = createMessage(PULL_CHANGES); + } else if (isPullFailing) { + message = createMessage(CONFLICTS_FOUND); + } else if (statusBehindCount > 0) { + message = createMessage(PULL_CHANGES); + } + + return { + isDisabled, + message, + }; +}; + +export default getPullBtnStatus; diff --git a/app/client/src/git/components/QuickActions/index.test.tsx b/app/client/src/git/components/GitQuickActions/index.test.tsx similarity index 93% rename from app/client/src/git/components/QuickActions/index.test.tsx rename to app/client/src/git/components/GitQuickActions/index.test.tsx index 189b3ea67be9..498f9887a994 100644 --- a/app/client/src/git/components/QuickActions/index.test.tsx +++ b/app/client/src/git/components/GitQuickActions/index.test.tsx @@ -22,25 +22,23 @@ jest.mock("./AutocommitStatusbar", () => () => ( describe("QuickActions Component", () => { const defaultProps = { - isGitConnected: false, - gitStatus: { - behindCount: 0, - isClean: true, - }, - pullFailed: false, - isProtectedMode: false, - isDiscardInProgress: false, - isPollingAutocommit: false, - isPullInProgress: false, - isFetchingGitStatus: false, - changesToCommit: 0, - gitMetadata: {}, + discard: jest.fn(), isAutocommitEnabled: false, + isAutocommitPolling: false, isConnectPermitted: true, - openGitSyncModal: jest.fn(), - openGitSettingsModal: jest.fn(), - discardChanges: jest.fn(), + isDiscardLoading: false, + isFetchStatusLoading: false, + isGitConnected: false, + isProtectedMode: false, + isPullFailing: false, + isPullLoading: false, + isStatusClean: true, pull: jest.fn(), + statusBehindCount: 0, + statusChangesCount: 0, + toggleGitConnectModal: jest.fn(), + toggleGitOpsModal: jest.fn(), + toggleGitSettingsModal: jest.fn(), }; afterEach(() => { @@ -122,7 +120,8 @@ describe("QuickActions Component", () => { )[0]; fireEvent.click(commitButton); - expect(props.openGitSyncModal).toHaveBeenCalledWith({ + expect(props.toggleGitOpsModal).toHaveBeenCalledWith({ + open: true, tab: GitSyncModalTab.DEPLOY, }); expect(AnalyticsUtil.logEvent).toHaveBeenCalledWith( @@ -184,9 +183,9 @@ describe("QuickActions Component", () => { source: "BOTTOM_BAR_GIT_MERGE_BUTTON", }, ); - expect(props.openGitSyncModal).toHaveBeenCalledWith({ + expect(props.toggleGitOpsModal).toHaveBeenCalledWith({ + open: true, tab: GitSyncModalTab.MERGE, - isDeploying: true, }); }); @@ -209,7 +208,8 @@ describe("QuickActions Component", () => { expect(AnalyticsUtil.logEvent).toHaveBeenCalledWith("GS_SETTING_CLICK", { source: "BOTTOM_BAR_GIT_SETTING_BUTTON", }); - expect(props.openGitSettingsModal).toHaveBeenCalledWith({ + expect(props.toggleGitSettingsModal).toHaveBeenCalledWith({ + open: true, tab: GitSettingsTab.General, }); }); diff --git a/app/client/src/git/components/GitQuickActions/index.tsx b/app/client/src/git/components/GitQuickActions/index.tsx new file mode 100644 index 000000000000..64de7e619600 --- /dev/null +++ b/app/client/src/git/components/GitQuickActions/index.tsx @@ -0,0 +1,192 @@ +import React, { useCallback } from "react"; +import styled from "styled-components"; + +import { + COMMIT_CHANGES, + createMessage, + GIT_SETTINGS, + MERGE, +} from "ee/constants/messages"; + +import AnalyticsUtil from "ee/utils/AnalyticsUtil"; +import { GitOpsTab } from "../../constants/enums"; +import { GitSettingsTab } from "../../constants/enums"; +import ConnectButton from "./ConnectButton"; +import QuickActionButton from "./QuickActionButton"; +import AutocommitStatusbar from "./AutocommitStatusbar"; +import getPullBtnStatus from "./helpers/getPullButtonStatus"; +import noop from "lodash/noop"; +import type { + ToggleGitConnectModalPayload, + ToggleGitOpsModalPayload, + ToggleGitSettingsModalPayload, +} from "git/store/actions/uiActions"; + +const Container = styled.div` + height: 100%; + display: flex; + align-items: center; +`; + +interface GitQuickActionsProps { + discard: () => void; + isAutocommitEnabled: boolean; + isAutocommitPolling: boolean; + isConnectPermitted: boolean; + isDiscardLoading: boolean; + isFetchStatusLoading: boolean; + isGitConnected: boolean; + isProtectedMode: boolean; + isPullFailing: boolean; + isPullLoading: boolean; + isStatusClean: boolean; + pull: () => void; + statusBehindCount: number; + statusChangesCount: number; + toggleGitConnectModal: (params: ToggleGitConnectModalPayload) => void; + toggleGitOpsModal: (params: ToggleGitOpsModalPayload) => void; + toggleGitSettingsModal: (params: ToggleGitSettingsModalPayload) => void; +} + +function GitQuickActions({ + discard = noop, + isAutocommitEnabled = false, + isAutocommitPolling = false, + isConnectPermitted = false, + isDiscardLoading = false, + isFetchStatusLoading = false, + isGitConnected = false, + isProtectedMode = false, + isPullFailing = false, + isPullLoading = false, + isStatusClean = false, + pull = noop, + statusBehindCount = 0, + statusChangesCount = 0, + toggleGitConnectModal = noop, + toggleGitOpsModal = noop, + toggleGitSettingsModal = noop, +}: GitQuickActionsProps) { + const { isDisabled: isPullDisabled, message: pullTooltipMessage } = + getPullBtnStatus({ + isStatusClean, + isProtectedMode, + isPullFailing, + statusBehindCount, + }); + + const isPullButtonLoading = + isDiscardLoading || isPullLoading || isFetchStatusLoading; + + const onCommitBtnClick = useCallback(() => { + if (!isFetchStatusLoading && !isProtectedMode) { + toggleGitOpsModal({ + open: true, + tab: GitOpsTab.Deploy, + }); + + AnalyticsUtil.logEvent("GS_DEPLOY_GIT_MODAL_TRIGGERED", { + source: "BOTTOM_BAR_GIT_COMMIT_BUTTON", + }); + } + }, [isFetchStatusLoading, isProtectedMode, toggleGitOpsModal]); + + const onPullBtnClick = useCallback(() => { + if (!isPullButtonLoading && !isPullDisabled) { + AnalyticsUtil.logEvent("GS_PULL_GIT_CLICK", { + source: "BOTTOM_BAR_GIT_PULL_BUTTON", + }); + + if (isProtectedMode) { + discard(); + } else { + // pull({ triggeredFromBottomBar: true }); + pull(); + } + } + }, [discard, isProtectedMode, pull, isPullDisabled, isPullButtonLoading]); + + const onMergeBtnClick = useCallback(() => { + AnalyticsUtil.logEvent("GS_MERGE_GIT_MODAL_TRIGGERED", { + source: "BOTTOM_BAR_GIT_MERGE_BUTTON", + }); + toggleGitOpsModal({ + open: true, + tab: GitOpsTab.Merge, + }); + }, [toggleGitOpsModal]); + + const onSettingsClick = useCallback(() => { + toggleGitSettingsModal({ + open: true, + tab: GitSettingsTab.General, + }); + AnalyticsUtil.logEvent("GS_SETTING_CLICK", { + source: "BOTTOM_BAR_GIT_SETTING_BUTTON", + }); + }, [toggleGitSettingsModal]); + + const onConnectBtnClick = useCallback(() => { + AnalyticsUtil.logEvent("GS_CONNECT_GIT_CLICK", { + source: "BOTTOM_BAR_GIT_CONNECT_BUTTON", + }); + + toggleGitConnectModal({ + open: true, + }); + }, [toggleGitConnectModal]); + + return isGitConnected ? ( + + {/* */} + {isAutocommitEnabled && isAutocommitPolling ? ( + + ) : ( + <> + + + + + + )} + + ) : ( + + ); +} + +export default GitQuickActions; diff --git a/app/client/src/git/components/QuickActions/helper.test.ts b/app/client/src/git/components/QuickActions/helper.test.ts deleted file mode 100644 index a7b3a6d30204..000000000000 --- a/app/client/src/git/components/QuickActions/helper.test.ts +++ /dev/null @@ -1,191 +0,0 @@ -import { getPullBtnStatus, capitalizeFirstLetter } from "./helpers"; - -describe("getPullBtnStatus", () => { - afterEach(() => { - jest.clearAllMocks(); - }); - - it('should return disabled with message "No commits to pull" when behindCount is 0', () => { - const gitStatus: Record = { - behindCount: 0, - isClean: true, - }; - const pullFailed = false; - const isProtected = false; - - const result = getPullBtnStatus(gitStatus, pullFailed, isProtected); - - expect(result).toEqual({ - disabled: true, - message: - "No commits to pull. This branch is in sync with the remote repository", - }); - }); - - it('should return disabled with message "Cannot pull with local uncommitted changes" when isClean is false and isProtected is false', () => { - const gitStatus: Record = { - behindCount: 5, - isClean: false, - }; - const pullFailed = false; - const isProtected = false; - - const result = getPullBtnStatus(gitStatus, pullFailed, isProtected); - - expect(result).toEqual({ - disabled: true, - message: - "You have uncommitted changes. Please commit or discard before pulling the remote changes.", - }); - }); - - it('should return enabled with message "Pull changes" when isClean is false, isProtected is true, and behindCount > 0', () => { - const gitStatus: Record = { - behindCount: 3, - isClean: false, - }; - const pullFailed = false; - const isProtected = true; - - const result = getPullBtnStatus(gitStatus, pullFailed, isProtected); - - expect(result).toEqual({ - disabled: false, - message: "Pull changes", - }); - }); - - it('should return message "Conflicts found" when pullFailed is true', () => { - const gitStatus: Record = { - behindCount: 2, - isClean: true, - }; - const pullFailed = true; - const isProtected = false; - - const result = getPullBtnStatus(gitStatus, pullFailed, isProtected); - - expect(result).toEqual({ - disabled: false, - message: "Conflicts found. Please resolve them and pull again.", - }); - }); - - it('should return enabled with message "Pull changes" when behindCount > 0 and no other conditions met', () => { - const gitStatus: Record = { - behindCount: 1, - isClean: true, - }; - const pullFailed = false; - const isProtected = false; - - const result = getPullBtnStatus(gitStatus, pullFailed, isProtected); - - expect(result).toEqual({ - disabled: false, - message: "Pull changes", - }); - }); - - it('should return disabled with message "No commits to pull" when behindCount is 0 regardless of isClean and isProtected', () => { - const gitStatus: Record = { - behindCount: 0, - isClean: false, - }; - const pullFailed = false; - const isProtected = true; - - const result = getPullBtnStatus(gitStatus, pullFailed, isProtected); - - expect(result).toEqual({ - disabled: true, - message: - "No commits to pull. This branch is in sync with the remote repository", - }); - }); - - it("should prioritize pullFailed over other conditions", () => { - const gitStatus: Record = { - behindCount: 0, - isClean: true, - }; - const pullFailed = true; - const isProtected = false; - - const result = getPullBtnStatus(gitStatus, pullFailed, isProtected); - - expect(result).toEqual({ - disabled: true, - message: "Conflicts found. Please resolve them and pull again.", - }); - }); - - it("should handle edge case when isClean is false, isProtected is true, behindCount is 0", () => { - const gitStatus: Record = { - behindCount: 0, - isClean: false, - }; - const pullFailed = false; - const isProtected = true; - - const result = getPullBtnStatus(gitStatus, pullFailed, isProtected); - - expect(result).toEqual({ - disabled: true, - message: - "No commits to pull. This branch is in sync with the remote repository", - }); - }); -}); - -describe("capitalizeFirstLetter", () => { - it("should capitalize the first letter of a lowercase word", () => { - const result = capitalizeFirstLetter("hello"); - - expect(result).toBe("Hello"); - }); - - it("should capitalize the first letter of an uppercase word", () => { - const result = capitalizeFirstLetter("WORLD"); - - expect(result).toBe("World"); - }); - - it("should handle empty string", () => { - const result = capitalizeFirstLetter(""); - - expect(result).toBe(""); - }); - - it("should handle single character", () => { - const result = capitalizeFirstLetter("a"); - - expect(result).toBe("A"); - }); - - it("should handle strings with spaces", () => { - const result = capitalizeFirstLetter("multiple words here"); - - expect(result).toBe("Multiple words here"); - }); - - it("should handle undefined input", () => { - // The function provides a default value of " " when input is undefined - // So we expect the output to be a single space with capitalized first letter - const result = capitalizeFirstLetter(); - - expect(result).toBe(" "); - }); - - it("should handle strings with special characters", () => { - const result = capitalizeFirstLetter("123abc"); - - expect(result).toBe("123abc"); - }); - - it("should not modify strings where the first character is not a letter", () => { - const result = capitalizeFirstLetter("!test"); - - expect(result).toBe("!test"); - }); -}); diff --git a/app/client/src/git/components/QuickActions/helpers.ts b/app/client/src/git/components/QuickActions/helpers.ts deleted file mode 100644 index 109197264899..000000000000 --- a/app/client/src/git/components/QuickActions/helpers.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { - CANNOT_PULL_WITH_LOCAL_UNCOMMITTED_CHANGES, - CONFLICTS_FOUND, - createMessage, - NO_COMMITS_TO_PULL, - PULL_CHANGES, -} from "ee/constants/messages"; -import type { GitStatus } from "../../types"; - -export const getPullBtnStatus = ( - gitStatus: GitStatus, - pullFailed: boolean, - isProtected: boolean, -) => { - const { behindCount, isClean } = gitStatus; - let message = createMessage(NO_COMMITS_TO_PULL); - let disabled = behindCount === 0; - - if (!isClean && !isProtected) { - disabled = true; - message = createMessage(CANNOT_PULL_WITH_LOCAL_UNCOMMITTED_CHANGES); - // TODO: Remove this when gitStatus typings are finalized - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - //@ts-ignore - } else if (!isClean && isProtected && behindCount > 0) { - disabled = false; - message = createMessage(PULL_CHANGES); - } else if (pullFailed) { - message = createMessage(CONFLICTS_FOUND); - // TODO: Remove this when gitStatus typings are finalized - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - //@ts-ignore - } else if (behindCount > 0) { - message = createMessage(PULL_CHANGES); - } - - return { - disabled, - message, - }; -}; - -export const capitalizeFirstLetter = (string = " ") => { - return string.charAt(0).toUpperCase() + string.toLowerCase().slice(1); -}; diff --git a/app/client/src/git/components/QuickActions/index.tsx b/app/client/src/git/components/QuickActions/index.tsx deleted file mode 100644 index 21483fb83ad4..000000000000 --- a/app/client/src/git/components/QuickActions/index.tsx +++ /dev/null @@ -1,183 +0,0 @@ -import React, { useCallback } from "react"; -import styled from "styled-components"; - -import { - COMMIT_CHANGES, - createMessage, - GIT_SETTINGS, - MERGE, -} from "ee/constants/messages"; - -import { GitSyncModalTab } from "entities/GitSync"; -import AnalyticsUtil from "ee/utils/AnalyticsUtil"; -import type { GitMetadata, GitStatus } from "../../types"; -import { getPullBtnStatus } from "./helpers"; -import { GitSettingsTab } from "../../constants/enums"; -import ConnectButton from "./ConnectButton"; -import QuickActionButton from "./QuickActionButton"; -import AutocommitStatusbar from "./AutocommitStatusbar"; - -interface QuickActionsProps { - isGitConnected: boolean; - gitStatus: GitStatus; - pullFailed: boolean; - isProtectedMode: boolean; - isDiscardInProgress: boolean; - isPollingAutocommit: boolean; - isPullInProgress: boolean; - isFetchingGitStatus: boolean; - changesToCommit: number; - gitMetadata: GitMetadata; - isAutocommitEnabled: boolean; - isConnectPermitted: boolean; - openGitSyncModal: (options: { - tab: GitSyncModalTab; - isDeploying?: boolean; - }) => void; - openGitSettingsModal: (options: { tab: GitSettingsTab }) => void; - discardChanges: () => void; - pull: (options: { triggeredFromBottomBar: boolean }) => void; -} - -const Container = styled.div` - height: 100%; - display: flex; - align-items: center; -`; - -function QuickActions({ - changesToCommit, - discardChanges, - gitMetadata, - gitStatus, - isConnectPermitted, - isDiscardInProgress, - isFetchingGitStatus, - isGitConnected, - isPollingAutocommit, - isProtectedMode, - isPullInProgress, - openGitSettingsModal, - openGitSyncModal, - pull, - pullFailed, -}: QuickActionsProps) { - const { disabled: pullDisabled, message: pullTooltipMessage } = - getPullBtnStatus(gitStatus, !!pullFailed, isProtectedMode); - - const showPullLoadingState = - isDiscardInProgress || isPullInProgress || isFetchingGitStatus; - - // TODO - Update once the gitMetadata typing is added - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - const isAutocommitEnabled: boolean = gitMetadata?.autoCommitConfig?.enabled; - const onCommitClick = useCallback(() => { - if (!isFetchingGitStatus && !isProtectedMode) { - openGitSyncModal({ - tab: GitSyncModalTab.DEPLOY, - }); - - AnalyticsUtil.logEvent("GS_DEPLOY_GIT_MODAL_TRIGGERED", { - source: "BOTTOM_BAR_GIT_COMMIT_BUTTON", - }); - } - }, [isFetchingGitStatus, isProtectedMode, openGitSyncModal]); - - const onPullClick = useCallback(() => { - if (!showPullLoadingState && !pullDisabled) { - AnalyticsUtil.logEvent("GS_PULL_GIT_CLICK", { - source: "BOTTOM_BAR_GIT_PULL_BUTTON", - }); - - if (isProtectedMode) { - discardChanges(); - } else { - pull({ triggeredFromBottomBar: true }); - } - } - }, [ - discardChanges, - isProtectedMode, - pull, - pullDisabled, - showPullLoadingState, - ]); - - const onMerge = useCallback(() => { - AnalyticsUtil.logEvent("GS_MERGE_GIT_MODAL_TRIGGERED", { - source: "BOTTOM_BAR_GIT_MERGE_BUTTON", - }); - openGitSyncModal({ - tab: GitSyncModalTab.MERGE, - isDeploying: true, - }); - }, [openGitSyncModal]); - - const onSettingsClick = useCallback(() => { - openGitSettingsModal({ - tab: GitSettingsTab.General, - }); - AnalyticsUtil.logEvent("GS_SETTING_CLICK", { - source: "BOTTOM_BAR_GIT_SETTING_BUTTON", - }); - }, [openGitSettingsModal]); - - return isGitConnected ? ( - - {/* */} - {isAutocommitEnabled && isPollingAutocommit ? ( - - ) : ( - <> - - - - - - )} - - ) : ( - - ); -} - -export default QuickActions; diff --git a/app/client/src/git/requests/fetchStatusRequest.types.ts b/app/client/src/git/requests/fetchStatusRequest.types.ts index 9a63fc879487..975f94b2b483 100644 --- a/app/client/src/git/requests/fetchStatusRequest.types.ts +++ b/app/client/src/git/requests/fetchStatusRequest.types.ts @@ -1,8 +1,9 @@ +import type { ApiResponse } from "api/types"; + export interface FetchStatusRequestParams { compareRemote: boolean; } - -export interface FetchStatusResponse { +export interface FetchStatusResponseData { added: string[]; aheadCount: number; behindCount: number; @@ -36,3 +37,5 @@ export interface FetchStatusResponse { remoteBranch: string; removed: string[]; } + +export type FetchStatusResponse = ApiResponse; diff --git a/app/client/src/git/sagas/fetchLocalProfileSaga.ts b/app/client/src/git/sagas/fetchLocalProfileSaga.ts index f0fed2306b75..a284b7e21d57 100644 --- a/app/client/src/git/sagas/fetchLocalProfileSaga.ts +++ b/app/client/src/git/sagas/fetchLocalProfileSaga.ts @@ -1,7 +1,7 @@ import fetchLocalProfileRequest from "git/requests/fetchLocalProfileRequest"; import type { FetchLocalProfileResponse } from "git/requests/fetchLocalProfileRequest.types"; import { gitArtifactActions } from "git/store/gitArtifactSlice"; -import type { GitArtifactPayloadAction } from "git/types"; +import type { GitArtifactPayloadAction } from "../store/types"; import { call, put } from "redux-saga/effects"; import { validateResponse } from "sagas/ErrorSagas"; diff --git a/app/client/src/git/store/actions/checkoutBranchActions.ts b/app/client/src/git/store/actions/checkoutBranchActions.ts index 8d72e5204ce9..c46edf84baff 100644 --- a/app/client/src/git/store/actions/checkoutBranchActions.ts +++ b/app/client/src/git/store/actions/checkoutBranchActions.ts @@ -1,4 +1,4 @@ -import { createSingleArtifactAction } from "./helpers/createSingleArtifactAction"; +import { createSingleArtifactAction } from "../helpers/createSingleArtifactAction"; import type { GitAsyncErrorPayload } from "../types"; import type { CheckoutBranchRequestParams } from "git/requests/checkoutBranchRequest.types"; diff --git a/app/client/src/git/store/actions/commitActions.ts b/app/client/src/git/store/actions/commitActions.ts index eeb80a18984c..24c5b17267f4 100644 --- a/app/client/src/git/store/actions/commitActions.ts +++ b/app/client/src/git/store/actions/commitActions.ts @@ -1,4 +1,4 @@ -import { createSingleArtifactAction } from "./helpers/createSingleArtifactAction"; +import { createSingleArtifactAction } from "../helpers/createSingleArtifactAction"; import type { GitAsyncErrorPayload } from "../types"; import type { CommitRequestParams } from "git/requests/commitRequest.types"; diff --git a/app/client/src/git/store/actions/connectActions.ts b/app/client/src/git/store/actions/connectActions.ts index 5a45872ed2a1..7fed98500000 100644 --- a/app/client/src/git/store/actions/connectActions.ts +++ b/app/client/src/git/store/actions/connectActions.ts @@ -1,4 +1,4 @@ -import { createSingleArtifactAction } from "./helpers/createSingleArtifactAction"; +import { createSingleArtifactAction } from "../helpers/createSingleArtifactAction"; import type { GitAsyncErrorPayload } from "../types"; import type { ConnectRequestParams } from "git/requests/connectRequest.types"; diff --git a/app/client/src/git/store/actions/createBranchActions.ts b/app/client/src/git/store/actions/createBranchActions.ts index 77917153ef39..be0e08445de2 100644 --- a/app/client/src/git/store/actions/createBranchActions.ts +++ b/app/client/src/git/store/actions/createBranchActions.ts @@ -1,4 +1,4 @@ -import { createSingleArtifactAction } from "./helpers/createSingleArtifactAction"; +import { createSingleArtifactAction } from "../helpers/createSingleArtifactAction"; import type { GitAsyncErrorPayload } from "../types"; import type { CreateBranchRequestParams } from "git/requests/createBranchRequest.types"; diff --git a/app/client/src/git/store/actions/deleteBranchActions.ts b/app/client/src/git/store/actions/deleteBranchActions.ts index c90ca96b1669..09296625f0d6 100644 --- a/app/client/src/git/store/actions/deleteBranchActions.ts +++ b/app/client/src/git/store/actions/deleteBranchActions.ts @@ -1,4 +1,4 @@ -import { createSingleArtifactAction } from "./helpers/createSingleArtifactAction"; +import { createSingleArtifactAction } from "../helpers/createSingleArtifactAction"; import type { GitAsyncErrorPayload } from "../types"; import type { DeleteBranchRequestParams } from "../../requests/deleteBranchRequest.types"; diff --git a/app/client/src/git/store/actions/discardActions.ts b/app/client/src/git/store/actions/discardActions.ts index a0863c79e638..c12b236f06ef 100644 --- a/app/client/src/git/store/actions/discardActions.ts +++ b/app/client/src/git/store/actions/discardActions.ts @@ -1,4 +1,4 @@ -import { createSingleArtifactAction } from "./helpers/createSingleArtifactAction"; +import { createSingleArtifactAction } from "../helpers/createSingleArtifactAction"; import type { GitArtifactErrorPayloadAction } from "../types"; export const discardInitAction = createSingleArtifactAction((state) => { diff --git a/app/client/src/git/store/actions/disconnectActions.ts b/app/client/src/git/store/actions/disconnectActions.ts index f911eefec631..dba26c0de629 100644 --- a/app/client/src/git/store/actions/disconnectActions.ts +++ b/app/client/src/git/store/actions/disconnectActions.ts @@ -1,4 +1,4 @@ -import { createSingleArtifactAction } from "./helpers/createSingleArtifactAction"; +import { createSingleArtifactAction } from "../helpers/createSingleArtifactAction"; import type { GitArtifactErrorPayloadAction } from "../types"; export const disconnectInitAction = createSingleArtifactAction((state) => { diff --git a/app/client/src/git/store/actions/fetchAutocommitProgressActions.ts b/app/client/src/git/store/actions/fetchAutocommitProgressActions.ts index caa054318f5f..2736b0c72cc4 100644 --- a/app/client/src/git/store/actions/fetchAutocommitProgressActions.ts +++ b/app/client/src/git/store/actions/fetchAutocommitProgressActions.ts @@ -3,7 +3,7 @@ import type { GitArtifactErrorPayloadAction, GitAutocommitProgress, } from "../types"; -import { createSingleArtifactAction } from "./helpers/createSingleArtifactAction"; +import { createSingleArtifactAction } from "../helpers/createSingleArtifactAction"; export const fetchAutocommitProgressInitAction = createSingleArtifactAction( (state) => { diff --git a/app/client/src/git/store/actions/fetchBranchesActions.ts b/app/client/src/git/store/actions/fetchBranchesActions.ts index 956bde6e92f3..e83ce0325e59 100644 --- a/app/client/src/git/store/actions/fetchBranchesActions.ts +++ b/app/client/src/git/store/actions/fetchBranchesActions.ts @@ -3,7 +3,7 @@ import type { FetchBranchesResponseData, } from "../../requests/fetchBranchesRequest.types"; import type { GitAsyncErrorPayload, GitAsyncSuccessPayload } from "../types"; -import { createSingleArtifactAction } from "./helpers/createSingleArtifactAction"; +import { createSingleArtifactAction } from "../helpers/createSingleArtifactAction"; export interface FetchBranchesInitPayload extends FetchBranchesRequestParams {} diff --git a/app/client/src/git/store/actions/fetchLocalProfileActions.ts b/app/client/src/git/store/actions/fetchLocalProfileActions.ts index c4775f4ab7f5..3559a2814c35 100644 --- a/app/client/src/git/store/actions/fetchLocalProfileActions.ts +++ b/app/client/src/git/store/actions/fetchLocalProfileActions.ts @@ -3,7 +3,7 @@ import type { GitArtifactErrorPayloadAction, GitAsyncSuccessPayload, } from "../types"; -import { createSingleArtifactAction } from "./helpers/createSingleArtifactAction"; +import { createSingleArtifactAction } from "../helpers/createSingleArtifactAction"; export const fetchLocalProfileInitAction = createSingleArtifactAction( (state) => { diff --git a/app/client/src/git/store/actions/fetchMergeStatusActions.ts b/app/client/src/git/store/actions/fetchMergeStatusActions.ts index e81a387fe675..e911daaa224d 100644 --- a/app/client/src/git/store/actions/fetchMergeStatusActions.ts +++ b/app/client/src/git/store/actions/fetchMergeStatusActions.ts @@ -3,7 +3,7 @@ import type { GitArtifactErrorPayloadAction, GitMergeStatus, } from "../types"; -import { createSingleArtifactAction } from "./helpers/createSingleArtifactAction"; +import { createSingleArtifactAction } from "../helpers/createSingleArtifactAction"; export const fetchMergeStatusInitAction = createSingleArtifactAction( (state) => { diff --git a/app/client/src/git/store/actions/fetchMetadataActions.ts b/app/client/src/git/store/actions/fetchMetadataActions.ts index a11914c8200a..f4d1fd9da2cb 100644 --- a/app/client/src/git/store/actions/fetchMetadataActions.ts +++ b/app/client/src/git/store/actions/fetchMetadataActions.ts @@ -3,7 +3,7 @@ import type { GitArtifactErrorPayloadAction, GitMetadata, } from "../types"; -import { createSingleArtifactAction } from "./helpers/createSingleArtifactAction"; +import { createSingleArtifactAction } from "../helpers/createSingleArtifactAction"; export const fetchMetadataInitAction = createSingleArtifactAction((state) => { state.apiResponses.metadata.loading = true; diff --git a/app/client/src/git/store/actions/fetchProtectedBranchesActions.ts b/app/client/src/git/store/actions/fetchProtectedBranchesActions.ts index 32026a1ed285..223952a3962b 100644 --- a/app/client/src/git/store/actions/fetchProtectedBranchesActions.ts +++ b/app/client/src/git/store/actions/fetchProtectedBranchesActions.ts @@ -3,7 +3,7 @@ import type { GitArtifactErrorPayloadAction, GitProtectedBranches, } from "../types"; -import { createSingleArtifactAction } from "./helpers/createSingleArtifactAction"; +import { createSingleArtifactAction } from "../helpers/createSingleArtifactAction"; export const fetchProtectedBranchesInitAction = createSingleArtifactAction( (state) => { diff --git a/app/client/src/git/store/actions/fetchSSHKeyActions.ts b/app/client/src/git/store/actions/fetchSSHKeyActions.ts index 516adf758f44..b802160ce0af 100644 --- a/app/client/src/git/store/actions/fetchSSHKeyActions.ts +++ b/app/client/src/git/store/actions/fetchSSHKeyActions.ts @@ -3,7 +3,7 @@ import type { GitArtifactErrorPayloadAction, GitSSHKey, } from "../types"; -import { createSingleArtifactAction } from "./helpers/createSingleArtifactAction"; +import { createSingleArtifactAction } from "../helpers/createSingleArtifactAction"; export const fetchSSHKeyInitAction = createSingleArtifactAction((state) => { state.apiResponses.sshKey.loading = true; diff --git a/app/client/src/git/store/actions/fetchStatusActions.ts b/app/client/src/git/store/actions/fetchStatusActions.ts index 21633eeb424e..734c26a52abb 100644 --- a/app/client/src/git/store/actions/fetchStatusActions.ts +++ b/app/client/src/git/store/actions/fetchStatusActions.ts @@ -4,7 +4,7 @@ import type { GitArtifactErrorPayloadAction, GitStatus, } from "../types"; -import { createSingleArtifactAction } from "./helpers/createSingleArtifactAction"; +import { createSingleArtifactAction } from "../helpers/createSingleArtifactAction"; export interface FetchStatusInitPayload extends FetchStatusRequestParams {} diff --git a/app/client/src/git/store/actions/generateSSHKey.ts b/app/client/src/git/store/actions/generateSSHKey.ts index c2a82f94e8f3..52698c65a8e1 100644 --- a/app/client/src/git/store/actions/generateSSHKey.ts +++ b/app/client/src/git/store/actions/generateSSHKey.ts @@ -1,4 +1,4 @@ -import { createSingleArtifactAction } from "./helpers/createSingleArtifactAction"; +import { createSingleArtifactAction } from "../helpers/createSingleArtifactAction"; import type { GitArtifactErrorPayloadAction } from "../types"; export const generateSSHKeyInitAction = createSingleArtifactAction((state) => { diff --git a/app/client/src/git/store/actions/mergeActions.ts b/app/client/src/git/store/actions/mergeActions.ts index dab2d21ed4c3..5bb17a351ce6 100644 --- a/app/client/src/git/store/actions/mergeActions.ts +++ b/app/client/src/git/store/actions/mergeActions.ts @@ -1,4 +1,4 @@ -import { createSingleArtifactAction } from "./helpers/createSingleArtifactAction"; +import { createSingleArtifactAction } from "../helpers/createSingleArtifactAction"; import type { GitArtifactErrorPayloadAction } from "../types"; export const mergeInitAction = createSingleArtifactAction((state) => { diff --git a/app/client/src/git/store/actions/mountActions.ts b/app/client/src/git/store/actions/mountActions.ts index 556aae44a483..07a08ee2b566 100644 --- a/app/client/src/git/store/actions/mountActions.ts +++ b/app/client/src/git/store/actions/mountActions.ts @@ -1,6 +1,6 @@ import type { PayloadAction } from "@reduxjs/toolkit"; import type { GitArtifactBasePayload, GitArtifactReduxState } from "../types"; -import { gitSingleArtifactInitialState } from "./helpers/singleArtifactInitialState"; +import { gitSingleArtifactInitialState } from "../helpers/gitSingleArtifactInitialState"; // ! This might be removed later diff --git a/app/client/src/git/store/actions/pullActions.ts b/app/client/src/git/store/actions/pullActions.ts index 04f2dfcd31fe..5acb7dc30f98 100644 --- a/app/client/src/git/store/actions/pullActions.ts +++ b/app/client/src/git/store/actions/pullActions.ts @@ -1,4 +1,4 @@ -import { createSingleArtifactAction } from "./helpers/createSingleArtifactAction"; +import { createSingleArtifactAction } from "../helpers/createSingleArtifactAction"; import type { GitArtifactErrorPayloadAction } from "../types"; export const pullInitAction = createSingleArtifactAction((state) => { diff --git a/app/client/src/git/store/actions/toggleAutocommitActions.ts b/app/client/src/git/store/actions/toggleAutocommitActions.ts index 129011c50143..96721698196f 100644 --- a/app/client/src/git/store/actions/toggleAutocommitActions.ts +++ b/app/client/src/git/store/actions/toggleAutocommitActions.ts @@ -1,4 +1,4 @@ -import { createSingleArtifactAction } from "./helpers/createSingleArtifactAction"; +import { createSingleArtifactAction } from "../helpers/createSingleArtifactAction"; import type { GitArtifactErrorPayloadAction } from "../types"; export const toggleAutocommitInitAction = createSingleArtifactAction( diff --git a/app/client/src/git/store/actions/triggerAutocommitActions.ts b/app/client/src/git/store/actions/triggerAutocommitActions.ts index 1ea785bdaeb7..414de9ed68c8 100644 --- a/app/client/src/git/store/actions/triggerAutocommitActions.ts +++ b/app/client/src/git/store/actions/triggerAutocommitActions.ts @@ -1,4 +1,4 @@ -import { createSingleArtifactAction } from "./helpers/createSingleArtifactAction"; +import { createSingleArtifactAction } from "../helpers/createSingleArtifactAction"; import type { GitArtifactErrorPayloadAction } from "../types"; export const triggerAutocommitInitAction = createSingleArtifactAction( diff --git a/app/client/src/git/store/actions/uiActions.ts b/app/client/src/git/store/actions/uiActions.ts index 7da558996e87..fcb69ae73653 100644 --- a/app/client/src/git/store/actions/uiActions.ts +++ b/app/client/src/git/store/actions/uiActions.ts @@ -1,4 +1,5 @@ -import { createSingleArtifactAction } from "./helpers/createSingleArtifactAction"; +import type { GitOpsTab, GitSettingsTab } from "git/constants/enums"; +import { createSingleArtifactAction } from "../helpers/createSingleArtifactAction"; interface ToggleRepoLimitModalPayload { open: boolean; @@ -25,3 +26,46 @@ export const toggleBranchListPopupAction = return state; }); + +export interface ToggleGitOpsModalPayload { + open: boolean; + tab: keyof typeof GitOpsTab; +} + +export const toggleGitOpsModalAction = + createSingleArtifactAction((state, action) => { + const { open, tab } = action.payload; + + state.ui.opsModal.open = open; + state.ui.opsModal.tab = tab; + + return state; + }); + +export interface ToggleGitSettingsModalPayload { + open: boolean; + tab: keyof typeof GitSettingsTab; +} + +export const toggleGitSettingsModalAction = + createSingleArtifactAction((state, action) => { + const { open, tab } = action.payload; + + state.ui.settingsModal.open = open; + state.ui.settingsModal.tab = tab; + + return state; + }); + +export interface ToggleGitConnectModalPayload { + open: boolean; +} + +export const toggleGitConnectModalAction = + createSingleArtifactAction((state, action) => { + const { open } = action.payload; + + state.ui.connectModal.open = open; + + return state; + }); diff --git a/app/client/src/git/store/actions/updateLocalProfileActions.ts b/app/client/src/git/store/actions/updateLocalProfileActions.ts index 839175016d2a..717bb388cb9b 100644 --- a/app/client/src/git/store/actions/updateLocalProfileActions.ts +++ b/app/client/src/git/store/actions/updateLocalProfileActions.ts @@ -1,4 +1,4 @@ -import { createSingleArtifactAction } from "./helpers/createSingleArtifactAction"; +import { createSingleArtifactAction } from "../helpers/createSingleArtifactAction"; import type { GitAsyncErrorPayload } from "../types"; import type { UpdateLocalProfileRequestParams } from "git/requests/updateLocalProfileRequest.types"; diff --git a/app/client/src/git/store/actions/updateProtectedBranchesActions.ts b/app/client/src/git/store/actions/updateProtectedBranchesActions.ts index d20fb52cd591..8a90e5889d8d 100644 --- a/app/client/src/git/store/actions/updateProtectedBranchesActions.ts +++ b/app/client/src/git/store/actions/updateProtectedBranchesActions.ts @@ -1,4 +1,4 @@ -import { createSingleArtifactAction } from "./helpers/createSingleArtifactAction"; +import { createSingleArtifactAction } from "../helpers/createSingleArtifactAction"; import type { GitArtifactErrorPayloadAction } from "../types"; export const updateProtectedBranchesInitAction = createSingleArtifactAction( diff --git a/app/client/src/git/store/gitArtifactSlice.ts b/app/client/src/git/store/gitArtifactSlice.ts index 000d665f73c3..ab2e2dfd780a 100644 --- a/app/client/src/git/store/gitArtifactSlice.ts +++ b/app/client/src/git/store/gitArtifactSlice.ts @@ -66,6 +66,7 @@ const initialState: GitArtifactReduxState = {}; export const gitArtifactSlice = createSlice({ name: "git/artifact", + reducerPath: "git.artifact", initialState, reducers: { mount: mountAction, @@ -112,12 +113,6 @@ export const gitArtifactSlice = createSlice({ toggleBranchListPopup: toggleBranchListPopupAction, toggleRepoLimitErrorModal: toggleRepoLimitErrorModalAction, }, - selectors: { - branches: (state, artifactType, baseArtifactId) => - state[artifactType][baseArtifactId].apiResponses.branches, - createBranch: (state, artifactType, baseArtifactId) => - state[artifactType][baseArtifactId].apiResponses.createBranch, - }, }); export const gitArtifactActions = gitArtifactSlice.actions; diff --git a/app/client/src/git/store/gitConfigSlice.ts b/app/client/src/git/store/gitConfigSlice.ts index 6bb28607b3bf..a07a45d9730b 100644 --- a/app/client/src/git/store/gitConfigSlice.ts +++ b/app/client/src/git/store/gitConfigSlice.ts @@ -9,23 +9,11 @@ import { updateGlobalProfileInitAction, updateGlobalProfileSuccessAction, } from "./actions/updateGlobalProfileActions"; -import type { GitConfigReduxState } from "./types"; - -const initialState: GitConfigReduxState = { - globalProfile: { - value: null, - loading: false, - error: null, - }, - updateGlobalProfile: { - loading: false, - error: null, - }, -}; +import { gitConfigInitialState } from "./helpers/gitConfigInitialState"; export const gitConfigSlice = createSlice({ name: "git/config", - initialState, + initialState: gitConfigInitialState, reducers: { fetchGlobalProfileInit: fetchGlobalProfileInitAction, fetchGlobalProfileSuccess: fetchGlobalProfileSuccessAction, diff --git a/app/client/src/git/store/actions/helpers/createSingleArtifactAction.ts b/app/client/src/git/store/helpers/createSingleArtifactAction.ts similarity index 89% rename from app/client/src/git/store/actions/helpers/createSingleArtifactAction.ts rename to app/client/src/git/store/helpers/createSingleArtifactAction.ts index f983f1a27190..2e0642959be8 100644 --- a/app/client/src/git/store/actions/helpers/createSingleArtifactAction.ts +++ b/app/client/src/git/store/helpers/createSingleArtifactAction.ts @@ -3,8 +3,8 @@ import type { GitArtifactPayloadAction, GitArtifactReduxState, GitSingleArtifactReduxState, -} from "../../types"; -import { gitSingleArtifactInitialState } from "./singleArtifactInitialState"; +} from "../types"; +import { gitSingleArtifactInitialState } from "./gitSingleArtifactInitialState"; type SingleArtifactStateCb = ( singleArtifactState: GitSingleArtifactReduxState, diff --git a/app/client/src/git/store/helpers/gitConfigInitialState.ts b/app/client/src/git/store/helpers/gitConfigInitialState.ts new file mode 100644 index 000000000000..7017399dfb16 --- /dev/null +++ b/app/client/src/git/store/helpers/gitConfigInitialState.ts @@ -0,0 +1,13 @@ +import type { GitConfigReduxState } from "../types"; + +export const gitConfigInitialState: GitConfigReduxState = { + globalProfile: { + value: null, + loading: false, + error: null, + }, + updateGlobalProfile: { + loading: false, + error: null, + }, +}; diff --git a/app/client/src/git/store/actions/helpers/singleArtifactInitialState.ts b/app/client/src/git/store/helpers/gitSingleArtifactInitialState.ts similarity index 97% rename from app/client/src/git/store/actions/helpers/singleArtifactInitialState.ts rename to app/client/src/git/store/helpers/gitSingleArtifactInitialState.ts index 5c210b925a67..a194106914a3 100644 --- a/app/client/src/git/store/actions/helpers/singleArtifactInitialState.ts +++ b/app/client/src/git/store/helpers/gitSingleArtifactInitialState.ts @@ -3,12 +3,12 @@ import { GitImportStep, GitOpsTab, GitSettingsTab, -} from "../../../constants/enums"; +} from "../../constants/enums"; import type { GitSingleArtifactAPIResponsesReduxState, GitSingleArtifactUIReduxState, GitSingleArtifactReduxState, -} from "../../types"; +} from "../types"; const gitSingleArtifactInitialUIState: GitSingleArtifactUIReduxState = { connectModal: { diff --git a/app/client/src/git/store/selectors/gitSingleArtifactSelectors.ts b/app/client/src/git/store/selectors/gitSingleArtifactSelectors.ts new file mode 100644 index 000000000000..bff95a870171 --- /dev/null +++ b/app/client/src/git/store/selectors/gitSingleArtifactSelectors.ts @@ -0,0 +1,36 @@ +import type { GitArtifactType } from "git/constants/enums"; +import type { GitRootState } from "../types"; + +interface GitArtifactDef { + artifactType: keyof typeof GitArtifactType; + baseArtifactId: string; +} + +export const selectSingleArtifact = ( + state: GitRootState, + artifactDef: GitArtifactDef, +) => { + return state.git.artifacts[artifactDef.artifactType]?.[ + artifactDef.baseArtifactId + ]; +}; + +export const selectBranches = ( + state: GitRootState, + artifactDef: GitArtifactDef, +) => selectSingleArtifact(state, artifactDef)?.apiResponses?.branches; + +export const selectCreateBranch = ( + state: GitRootState, + artifactDef: GitArtifactDef, +) => selectSingleArtifact(state, artifactDef)?.apiResponses?.createBranch; + +export const selectDeleteBranch = ( + state: GitRootState, + artifactDef: GitArtifactDef, +) => selectSingleArtifact(state, artifactDef)?.apiResponses?.deleteBranch; + +export const selectCheckoutBranch = ( + state: GitRootState, + artifactDef: GitArtifactDef, +) => selectSingleArtifact(state, artifactDef)?.apiResponses.checkoutBranch; diff --git a/app/client/src/git/store/types.ts b/app/client/src/git/store/types.ts index b6502ebf699f..9e6b8833b7b7 100644 --- a/app/client/src/git/store/types.ts +++ b/app/client/src/git/store/types.ts @@ -25,7 +25,7 @@ export type GitAutocommitProgress = Record; export type GitSSHKey = Record; -interface AsyncState { +export interface AsyncState { value: T | null; loading: boolean; error: string | null; @@ -98,6 +98,13 @@ export interface GitConfigReduxState { updateGlobalProfile: AsyncStateWithoutValue; } +export interface GitRootState { + git: { + artifacts: GitArtifactReduxState; + config: GitConfigReduxState; + }; +} + export interface GitArtifactBasePayload { artifactType: keyof typeof GitArtifactType; baseArtifactId: string; From ef34582a02a42184a874c9c72e185621ebf3aad8 Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Tue, 10 Dec 2024 00:12:14 +0800 Subject: [PATCH 015/143] chore: expanding context provider and making contextaware comps --- .../hooks/useStatusChangeCount.ts | 40 +++++ .../CtxAwareGitQuickActions/index.tsx | 55 +++++- .../hooks/useGitBranches.ts | 45 +++-- .../GitContextProvider/hooks/useGitConnect.ts | 37 +++++ .../GitContextProvider/hooks/useGitOps.ts | 157 ++++++++++++++++++ .../hooks/useGitSettings.ts | 44 +++++ .../components/GitContextProvider/index.tsx | 50 ++++-- .../components/GitQuickActions/index.test.tsx | 2 +- .../git/components/GitQuickActions/index.tsx | 39 ++--- .../requests/fetchMergeStatusRequest.types.ts | 7 +- .../src/git/sagas/checkoutBranchSaga.ts | 2 +- app/client/src/git/sagas/index.ts | 1 - .../store/actions/fetchMergeStatusActions.ts | 31 ++-- .../git/store/actions/fetchStatusActions.ts | 30 ++-- app/client/src/git/store/actions/uiActions.ts | 2 +- app/client/src/git/store/gitArtifactSlice.ts | 62 +++++-- .../selectors/gitSingleArtifactSelectors.ts | 28 ++++ app/client/src/git/store/types.ts | 12 +- 18 files changed, 527 insertions(+), 117 deletions(-) create mode 100644 app/client/src/git/components/CtxAwareGitQuickActions/hooks/useStatusChangeCount.ts create mode 100644 app/client/src/git/components/GitContextProvider/hooks/useGitConnect.ts create mode 100644 app/client/src/git/components/GitContextProvider/hooks/useGitOps.ts create mode 100644 app/client/src/git/components/GitContextProvider/hooks/useGitSettings.ts diff --git a/app/client/src/git/components/CtxAwareGitQuickActions/hooks/useStatusChangeCount.ts b/app/client/src/git/components/CtxAwareGitQuickActions/hooks/useStatusChangeCount.ts new file mode 100644 index 000000000000..bcc59083c7f3 --- /dev/null +++ b/app/client/src/git/components/CtxAwareGitQuickActions/hooks/useStatusChangeCount.ts @@ -0,0 +1,40 @@ +import type { FetchStatusResponseData } from "git/requests/fetchStatusRequest.types"; +import { useMemo } from "react"; + +// does not include modules or moduleinstances +export const calcStatusChangeCount = (status: FetchStatusResponseData) => { + const { + modified = [], + modifiedDatasources = 0, + modifiedJSLibs = 0, + modifiedJSObjects = 0, + modifiedModules = 0, + modifiedPages = 0, + modifiedQueries = 0, + } = status || {}; + const themeCount = modified.includes("theme.json") ? 1 : 0; + const settingsCount = modified.includes("application.json") ? 1 : 0; + + // does not include ahead and behind remote counts + return ( + modifiedDatasources + + modifiedJSLibs + + modifiedJSObjects + + modifiedModules + + modifiedPages + + modifiedQueries + + themeCount + + settingsCount + ); +}; + +export default function useStatusChangeCount( + status: FetchStatusResponseData | null, +) { + const statusChangeCount = useMemo( + () => (status ? calcStatusChangeCount(status) : 0), + [status], + ); + + return statusChangeCount; +} diff --git a/app/client/src/git/components/CtxAwareGitQuickActions/index.tsx b/app/client/src/git/components/CtxAwareGitQuickActions/index.tsx index ff8b4c56321a..9deb2f2d7a55 100644 --- a/app/client/src/git/components/CtxAwareGitQuickActions/index.tsx +++ b/app/client/src/git/components/CtxAwareGitQuickActions/index.tsx @@ -1 +1,54 @@ -export default {}; +import React from "react"; +import GitQuickActions from "../GitQuickActions"; +import { useGitContext } from "../GitContextProvider"; +import useStatusChangeCount from "./hooks/useStatusChangeCount"; + +function CtxAwareGitQuickActions() { + const { + discard, + discardLoading, + fetchStatusLoading, + pull, + pullError, + pullLoading, + status, + toggleGitConnectModal, + toggleGitOpsModal, + toggleGitSettingsModal, + } = useGitContext(); + + const isGitConnected = false; + const isAutocommitEnabled = true; + const isAutocommitPolling = false; + const isConnectPermitted = true; + const isProtectedMode = false; + + const isPullFailing = !!pullError; + const isStatusClean = status?.isClean ?? false; + const statusBehindCount = status?.behindCount ?? 0; + const statusChangeCount = useStatusChangeCount(status); + + return ( + + ); +} + +export default CtxAwareGitQuickActions; diff --git a/app/client/src/git/components/GitContextProvider/hooks/useGitBranches.ts b/app/client/src/git/components/GitContextProvider/hooks/useGitBranches.ts index 2eb9f40a6d38..da20d0e19ca3 100644 --- a/app/client/src/git/components/GitContextProvider/hooks/useGitBranches.ts +++ b/app/client/src/git/components/GitContextProvider/hooks/useGitBranches.ts @@ -8,7 +8,7 @@ import { selectDeleteBranch, } from "git/store/selectors/gitSingleArtifactSelectors"; import type { GitRootState } from "git/store/types"; -import { useCallback } from "react"; +import { useCallback, useMemo } from "react"; import { useDispatch, useSelector } from "react-redux"; interface UseGitBranchesParams { @@ -16,7 +16,7 @@ interface UseGitBranchesParams { baseArtifactId: string; } -export interface UseGitBranchesReturns { +export interface UseGitBranchesReturnValue { branches: FetchBranchesResponseData | null; fetchBranchesLoading: boolean; fetchBranchesError: string | null; @@ -30,14 +30,19 @@ export interface UseGitBranchesReturns { checkoutBranchLoading: boolean; checkoutBranchError: string | null; checkoutBranch: (branchName: string) => void; + toggleGitBranchListPopup: (open: boolean) => void; } export default function useGitBranches({ artifactType, baseArtifactId, -}: UseGitBranchesParams): UseGitBranchesReturns { - const basePayload = { artifactType, baseArtifactId }; +}: UseGitBranchesParams): UseGitBranchesReturnValue { + const basePayload = useMemo( + () => ({ artifactType, baseArtifactId }), + [artifactType, baseArtifactId], + ); const dispatch = useDispatch(); + // fetch branches const branchesState = useSelector((state: GitRootState) => selectBranches(state, basePayload), @@ -45,12 +50,12 @@ export default function useGitBranches({ const fetchBranches = useCallback(() => { dispatch( gitArtifactActions.fetchBranchesInit({ - artifactType, - baseArtifactId, + ...basePayload, pruneBranches: true, }), ); - }, [artifactType, baseArtifactId, dispatch]); + }, [basePayload, dispatch]); + // create branch const createBranchState = useSelector((state: GitRootState) => selectCreateBranch(state, basePayload), @@ -59,13 +64,12 @@ export default function useGitBranches({ (branchName: string) => { dispatch( gitArtifactActions.createBranchInit({ - artifactType, - baseArtifactId, + ...basePayload, branchName, }), ); }, - [artifactType, baseArtifactId, dispatch], + [basePayload, dispatch], ); // delete branch const deleteBranchState = useSelector((state: GitRootState) => @@ -75,13 +79,12 @@ export default function useGitBranches({ (branchName: string) => { dispatch( gitArtifactActions.deleteBranchInit({ - artifactType, - baseArtifactId, + ...basePayload, branchName, }), ); }, - [artifactType, baseArtifactId, dispatch], + [basePayload, dispatch], ); // checkout branch const checkoutBranchState = useSelector((state: GitRootState) => @@ -91,15 +94,24 @@ export default function useGitBranches({ (branchName: string) => { dispatch( gitArtifactActions.checkoutBranchInit({ - artifactType, - baseArtifactId, + ...basePayload, branchName, }), ); }, - [artifactType, baseArtifactId, dispatch], + [basePayload, dispatch], ); + // git branch list popup + const toggleGitBranchListPopup = (open: boolean) => { + dispatch( + gitArtifactActions.toggleGitBranchListPopup({ + ...basePayload, + open, + }), + ); + }; + return { branches: branchesState?.value ?? null, fetchBranchesLoading: branchesState?.loading ?? false, @@ -114,5 +126,6 @@ export default function useGitBranches({ checkoutBranchLoading: checkoutBranchState?.loading ?? false, checkoutBranchError: checkoutBranchState?.error ?? null, checkoutBranch, + toggleGitBranchListPopup, }; } diff --git a/app/client/src/git/components/GitContextProvider/hooks/useGitConnect.ts b/app/client/src/git/components/GitContextProvider/hooks/useGitConnect.ts new file mode 100644 index 000000000000..900f1716c8c5 --- /dev/null +++ b/app/client/src/git/components/GitContextProvider/hooks/useGitConnect.ts @@ -0,0 +1,37 @@ +import type { GitArtifactType } from "git/constants/enums"; +import { gitArtifactActions } from "git/store/gitArtifactSlice"; +import { useMemo } from "react"; +import { useDispatch } from "react-redux"; + +interface UseGitConnectParams { + artifactType: keyof typeof GitArtifactType; + baseArtifactId: string; +} + +export interface UseGitConnectReturnValue { + toggleGitConnectModal: (open: boolean) => void; +} + +export default function useGitConnect({ + artifactType, + baseArtifactId, +}: UseGitConnectParams): UseGitConnectReturnValue { + const dispatch = useDispatch(); + const basePayload = useMemo( + () => ({ artifactType, baseArtifactId }), + [artifactType, baseArtifactId], + ); + + const toggleGitConnectModal = (open: boolean) => { + dispatch( + gitArtifactActions.toggleGitConnectModal({ + ...basePayload, + open, + }), + ); + }; + + return { + toggleGitConnectModal, + }; +} diff --git a/app/client/src/git/components/GitContextProvider/hooks/useGitOps.ts b/app/client/src/git/components/GitContextProvider/hooks/useGitOps.ts new file mode 100644 index 000000000000..3c8cbe6cb71c --- /dev/null +++ b/app/client/src/git/components/GitContextProvider/hooks/useGitOps.ts @@ -0,0 +1,157 @@ +import { GitOpsTab, type GitArtifactType } from "git/constants/enums"; +import type { FetchMergeStatusResponseData } from "git/requests/fetchMergeStatusRequest.types"; +import type { FetchStatusResponseData } from "git/requests/fetchStatusRequest.types"; +import { gitArtifactActions } from "git/store/gitArtifactSlice"; +import { + selectCommit, + selectDiscard, + selectMerge, + selectMergeStatus, + selectPull, + selectStatus, +} from "git/store/selectors/gitSingleArtifactSelectors"; +import type { GitRootState } from "git/store/types"; +import { useCallback, useMemo } from "react"; +import { useDispatch, useSelector } from "react-redux"; + +interface UseGitOpsParams { + artifactType: keyof typeof GitArtifactType; + baseArtifactId: string; +} + +export interface UseGitOpsReturnValue { + commitLoading: boolean; + commitError: string | null; + commit: (commitMessage: string) => void; + discardLoading: boolean; + discardError: string | null; + discard: () => void; + status: FetchStatusResponseData | null; + fetchStatusLoading: boolean; + fetchStatusError: string | null; + fetchStatus: () => void; + mergeLoading: boolean; + mergeError: string | null; + merge: () => void; + mergeStatus: FetchMergeStatusResponseData | null; + fetchMergeStatusLoading: boolean; + fetchMergeStatusError: string | null; + fetchMergeStatus: () => void; + pullLoading: boolean; + pullError: string | null; + pull: () => void; + toggleGitOpsModal: (open: boolean, tab: keyof typeof GitOpsTab) => void; +} + +export default function useGitOps({ + artifactType, + baseArtifactId, +}: UseGitOpsParams): UseGitOpsReturnValue { + const dispatch = useDispatch(); + const basePayload = useMemo( + () => ({ artifactType, baseArtifactId }), + [artifactType, baseArtifactId], + ); + + // commit + const commitState = useSelector((state: GitRootState) => + selectCommit(state, basePayload), + ); + + const commit = useCallback( + (commitMessage: string) => { + dispatch( + gitArtifactActions.commitInit({ + ...basePayload, + commitMessage, + doPush: true, + }), + ); + }, + [basePayload, dispatch], + ); + + // discard + const discardState = useSelector((state: GitRootState) => + selectDiscard(state, basePayload), + ); + + const discard = useCallback(() => { + dispatch(gitArtifactActions.discardInit(basePayload)); + }, [basePayload, dispatch]); + + // status + const statusState = useSelector((state: GitRootState) => + selectStatus(state, basePayload), + ); + + const fetchStatus = useCallback(() => { + dispatch( + gitArtifactActions.fetchStatusInit({ + ...basePayload, + compareRemote: true, + }), + ); + }, [basePayload, dispatch]); + + // merge + const mergeState = useSelector((state: GitRootState) => + selectMerge(state, basePayload), + ); + + const merge = useCallback(() => { + dispatch(gitArtifactActions.mergeInit(basePayload)); + }, [basePayload, dispatch]); + + // merge status + const mergeStatusState = useSelector((state: GitRootState) => + selectMergeStatus(state, basePayload), + ); + + const fetchMergeStatus = useCallback(() => { + dispatch(gitArtifactActions.fetchMergeStatusInit(basePayload)); + }, [basePayload, dispatch]); + + // pull + const pullState = useSelector((state: GitRootState) => + selectPull(state, basePayload), + ); + + const pull = useCallback(() => { + dispatch(gitArtifactActions.pullInit(basePayload)); + }, [basePayload, dispatch]); + + // git ops modal + const toggleGitOpsModal = useCallback( + (open: boolean, tab: keyof typeof GitOpsTab = GitOpsTab.Deploy) => { + dispatch( + gitArtifactActions.toggleGitOpsModal({ ...basePayload, open, tab }), + ); + }, + [basePayload, dispatch], + ); + + return { + commitLoading: commitState?.loading ?? false, + commitError: commitState?.error ?? null, + commit, + discardLoading: discardState?.loading ?? false, + discardError: discardState?.error ?? null, + discard, + status: statusState?.value ?? null, + fetchStatusLoading: statusState?.loading ?? false, + fetchStatusError: statusState?.error ?? null, + fetchStatus, + mergeLoading: mergeState?.loading ?? false, + mergeError: mergeState?.error ?? null, + merge, + mergeStatus: mergeStatusState?.value ?? null, + fetchMergeStatusLoading: mergeStatusState?.loading ?? false, + fetchMergeStatusError: mergeStatusState?.error ?? null, + fetchMergeStatus, + pullLoading: pullState?.loading ?? false, + pullError: pullState?.error ?? null, + pull, + toggleGitOpsModal, + }; +} diff --git a/app/client/src/git/components/GitContextProvider/hooks/useGitSettings.ts b/app/client/src/git/components/GitContextProvider/hooks/useGitSettings.ts new file mode 100644 index 000000000000..096e934d7d5e --- /dev/null +++ b/app/client/src/git/components/GitContextProvider/hooks/useGitSettings.ts @@ -0,0 +1,44 @@ +import type { GitArtifactType, GitSettingsTab } from "git/constants/enums"; +import { gitArtifactActions } from "git/store/gitArtifactSlice"; +import { useMemo } from "react"; +import { useDispatch } from "react-redux"; + +interface UseGitSettingsParams { + artifactType: keyof typeof GitArtifactType; + baseArtifactId: string; +} + +export interface UseGitSettingsReturnValue { + toggleGitSettingsModal: ( + open: boolean, + tab: keyof typeof GitSettingsTab, + ) => void; +} + +export default function useGitSettings({ + artifactType, + baseArtifactId, +}: UseGitSettingsParams): UseGitSettingsReturnValue { + const dispatch = useDispatch(); + const basePayload = useMemo( + () => ({ artifactType, baseArtifactId }), + [artifactType, baseArtifactId], + ); + + const toggleGitSettingsModal = ( + open: boolean, + tab: keyof typeof GitSettingsTab, + ) => { + dispatch( + gitArtifactActions.toggleGitSettingsModal({ + ...basePayload, + open, + tab, + }), + ); + }; + + return { + toggleGitSettingsModal, + }; +} diff --git a/app/client/src/git/components/GitContextProvider/index.tsx b/app/client/src/git/components/GitContextProvider/index.tsx index 6deab437d947..d093e0f5e709 100644 --- a/app/client/src/git/components/GitContextProvider/index.tsx +++ b/app/client/src/git/components/GitContextProvider/index.tsx @@ -1,14 +1,28 @@ -import React, { createContext, useEffect } from "react"; -import useGitBranches from "./hooks/useGitBranches"; -import type { UseGitBranchesReturns } from "./hooks/useGitBranches"; +import React, { createContext, useContext, useEffect, useMemo } from "react"; import type { GitArtifactType } from "git/constants/enums"; +import type { UseGitOpsReturnValue } from "./hooks/useGitOps"; +import type { UseGitSettingsReturnValue } from "./hooks/useGitSettings"; +import type { UseGitBranchesReturnValue } from "./hooks/useGitBranches"; +import type { UseGitConnectReturnValue } from "./hooks/useGitConnect"; +import useGitOps from "./hooks/useGitOps"; +import useGitConnect from "./hooks/useGitConnect"; +import useGitSettings from "./hooks/useGitSettings"; +import useGitBranches from "./hooks/useGitBranches"; -interface GitContextValue extends UseGitBranchesReturns {} +interface GitContextValue + extends UseGitConnectReturnValue, + UseGitOpsReturnValue, + UseGitSettingsReturnValue, + UseGitBranchesReturnValue {} const gitContextInitialValue = {} as GitContextValue; export const GitContext = createContext(gitContextInitialValue); +export const useGitContext = () => { + return useContext(GitContext); +}; + interface GitContextProviderProps { artifactType: keyof typeof GitArtifactType; baseArtifactId: string; @@ -20,18 +34,30 @@ export default function GitContextProvider({ baseArtifactId, children, }: GitContextProviderProps) { - const useGitBranchesReturns = useGitBranches({ - artifactType, - baseArtifactId, - }); + const basePayload = useMemo( + () => ({ artifactType, baseArtifactId }), + [artifactType, baseArtifactId], + ); + const useGitConnectReturnValue = useGitConnect(basePayload); + const useGitOpsReturnValue = useGitOps(basePayload); + const useGitBranchesReturnValue = useGitBranches(basePayload); + const useGitSettingsReturnValue = useGitSettings(basePayload); + + const { fetchBranches } = useGitBranchesReturnValue; - useEffect(function gitInitEffect() { - useGitBranchesReturns.fetchBranches(); - }, []); + useEffect( + function gitInitEffect() { + fetchBranches(); + }, + [fetchBranches], + ); // eslint-disable-next-line react-perf/jsx-no-new-object-as-prop const contextValue = { - ...useGitBranchesReturns, + ...useGitOpsReturnValue, + ...useGitBranchesReturnValue, + ...useGitConnectReturnValue, + ...useGitSettingsReturnValue, } as GitContextValue; return ( diff --git a/app/client/src/git/components/GitQuickActions/index.test.tsx b/app/client/src/git/components/GitQuickActions/index.test.tsx index 498f9887a994..a7c41bb2cd08 100644 --- a/app/client/src/git/components/GitQuickActions/index.test.tsx +++ b/app/client/src/git/components/GitQuickActions/index.test.tsx @@ -35,7 +35,7 @@ describe("QuickActions Component", () => { isStatusClean: true, pull: jest.fn(), statusBehindCount: 0, - statusChangesCount: 0, + statusChangeCount: 0, toggleGitConnectModal: jest.fn(), toggleGitOpsModal: jest.fn(), toggleGitSettingsModal: jest.fn(), diff --git a/app/client/src/git/components/GitQuickActions/index.tsx b/app/client/src/git/components/GitQuickActions/index.tsx index 64de7e619600..e43bf2f0d3d1 100644 --- a/app/client/src/git/components/GitQuickActions/index.tsx +++ b/app/client/src/git/components/GitQuickActions/index.tsx @@ -16,11 +16,6 @@ import QuickActionButton from "./QuickActionButton"; import AutocommitStatusbar from "./AutocommitStatusbar"; import getPullBtnStatus from "./helpers/getPullButtonStatus"; import noop from "lodash/noop"; -import type { - ToggleGitConnectModalPayload, - ToggleGitOpsModalPayload, - ToggleGitSettingsModalPayload, -} from "git/store/actions/uiActions"; const Container = styled.div` height: 100%; @@ -42,10 +37,13 @@ interface GitQuickActionsProps { isStatusClean: boolean; pull: () => void; statusBehindCount: number; - statusChangesCount: number; - toggleGitConnectModal: (params: ToggleGitConnectModalPayload) => void; - toggleGitOpsModal: (params: ToggleGitOpsModalPayload) => void; - toggleGitSettingsModal: (params: ToggleGitSettingsModalPayload) => void; + statusChangeCount: number; + toggleGitConnectModal: (open: boolean) => void; + toggleGitOpsModal: (open: boolean, tab: keyof typeof GitOpsTab) => void; + toggleGitSettingsModal: ( + open: boolean, + tab: keyof typeof GitSettingsTab, + ) => void; } function GitQuickActions({ @@ -62,7 +60,7 @@ function GitQuickActions({ isStatusClean = false, pull = noop, statusBehindCount = 0, - statusChangesCount = 0, + statusChangeCount = 0, toggleGitConnectModal = noop, toggleGitOpsModal = noop, toggleGitSettingsModal = noop, @@ -80,10 +78,7 @@ function GitQuickActions({ const onCommitBtnClick = useCallback(() => { if (!isFetchStatusLoading && !isProtectedMode) { - toggleGitOpsModal({ - open: true, - tab: GitOpsTab.Deploy, - }); + toggleGitOpsModal(true, GitOpsTab.Deploy); AnalyticsUtil.logEvent("GS_DEPLOY_GIT_MODAL_TRIGGERED", { source: "BOTTOM_BAR_GIT_COMMIT_BUTTON", @@ -110,17 +105,11 @@ function GitQuickActions({ AnalyticsUtil.logEvent("GS_MERGE_GIT_MODAL_TRIGGERED", { source: "BOTTOM_BAR_GIT_MERGE_BUTTON", }); - toggleGitOpsModal({ - open: true, - tab: GitOpsTab.Merge, - }); + toggleGitOpsModal(true, GitOpsTab.Merge); }, [toggleGitOpsModal]); const onSettingsClick = useCallback(() => { - toggleGitSettingsModal({ - open: true, - tab: GitSettingsTab.General, - }); + toggleGitSettingsModal(true, GitSettingsTab.General); AnalyticsUtil.logEvent("GS_SETTING_CLICK", { source: "BOTTOM_BAR_GIT_SETTING_BUTTON", }); @@ -131,9 +120,7 @@ function GitQuickActions({ source: "BOTTOM_BAR_GIT_CONNECT_BUTTON", }); - toggleGitConnectModal({ - open: true, - }); + toggleGitConnectModal(true); }, [toggleGitConnectModal]); return isGitConnected ? ( @@ -145,7 +132,7 @@ function GitQuickActions({ <> ; diff --git a/app/client/src/git/sagas/checkoutBranchSaga.ts b/app/client/src/git/sagas/checkoutBranchSaga.ts index bacb2a283c38..506ecae653d3 100644 --- a/app/client/src/git/sagas/checkoutBranchSaga.ts +++ b/app/client/src/git/sagas/checkoutBranchSaga.ts @@ -46,7 +46,7 @@ export default function* checkoutBranchSaga( ); yield put( - gitArtifactActions.toggleBranchListPopup({ + gitArtifactActions.toggleGitBranchListPopup({ ...basePayload, open: false, }), diff --git a/app/client/src/git/sagas/index.ts b/app/client/src/git/sagas/index.ts index ed4f54f25a67..076853a8612a 100644 --- a/app/client/src/git/sagas/index.ts +++ b/app/client/src/git/sagas/index.ts @@ -15,7 +15,6 @@ export function* gitSagas() { // branches takeLatest(gitArtifactActions.fetchBranchesInit.type, fetchBranchesSaga), - takeLatest(gitArtifactActions.fetchBranchesInit.type, fetchBranchesSaga), takeLatest(gitArtifactActions.commitInit.type, commitSaga), takeLatest( diff --git a/app/client/src/git/store/actions/fetchMergeStatusActions.ts b/app/client/src/git/store/actions/fetchMergeStatusActions.ts index e911daaa224d..71ae8fccf107 100644 --- a/app/client/src/git/store/actions/fetchMergeStatusActions.ts +++ b/app/client/src/git/store/actions/fetchMergeStatusActions.ts @@ -1,9 +1,6 @@ -import type { - GitArtifactPayloadAction, - GitArtifactErrorPayloadAction, - GitMergeStatus, -} from "../types"; +import type { GitAsyncSuccessPayload, GitAsyncErrorPayload } from "../types"; import { createSingleArtifactAction } from "../helpers/createSingleArtifactAction"; +import type { FetchMergeStatusResponseData } from "git/requests/fetchMergeStatusRequest.types"; export const fetchMergeStatusInitAction = createSingleArtifactAction( (state) => { @@ -14,25 +11,21 @@ export const fetchMergeStatusInitAction = createSingleArtifactAction( }, ); -export const fetchMergeStatusSuccessAction = createSingleArtifactAction( - ( - state, - action: GitArtifactPayloadAction<{ mergeStatus: GitMergeStatus }>, - ) => { - state.apiResponses.mergeStatus.loading = false; - state.apiResponses.mergeStatus.value = action.payload.mergeStatus; +export const fetchMergeStatusSuccessAction = createSingleArtifactAction< + GitAsyncSuccessPayload +>((state, action) => { + state.apiResponses.mergeStatus.loading = false; + state.apiResponses.mergeStatus.value = action.payload.responseData; - return state; - }, -); + return state; +}); -export const fetchMergeStatusErrorAction = createSingleArtifactAction( - (state, action: GitArtifactErrorPayloadAction) => { +export const fetchMergeStatusErrorAction = + createSingleArtifactAction((state, action) => { const { error } = action.payload; state.apiResponses.mergeStatus.loading = false; state.apiResponses.mergeStatus.error = error; return state; - }, -); + }); diff --git a/app/client/src/git/store/actions/fetchStatusActions.ts b/app/client/src/git/store/actions/fetchStatusActions.ts index 734c26a52abb..1121e368d012 100644 --- a/app/client/src/git/store/actions/fetchStatusActions.ts +++ b/app/client/src/git/store/actions/fetchStatusActions.ts @@ -1,9 +1,8 @@ -import type { FetchStatusRequestParams } from "git/requests/fetchStatusRequest.types"; import type { - GitArtifactPayloadAction, - GitArtifactErrorPayloadAction, - GitStatus, -} from "../types"; + FetchStatusRequestParams, + FetchStatusResponseData, +} from "git/requests/fetchStatusRequest.types"; +import type { GitAsyncErrorPayload, GitAsyncSuccessPayload } from "../types"; import { createSingleArtifactAction } from "../helpers/createSingleArtifactAction"; export interface FetchStatusInitPayload extends FetchStatusRequestParams {} @@ -16,22 +15,21 @@ export const fetchStatusInitAction = return state; }); -export const fetchStatusSuccessAction = createSingleArtifactAction( - (state, action: GitArtifactPayloadAction<{ status: GitStatus }>) => { - state.apiResponses.status.loading = false; - state.apiResponses.status.value = action.payload.status; +export const fetchStatusSuccessAction = createSingleArtifactAction< + GitAsyncSuccessPayload +>((state, action) => { + state.apiResponses.status.loading = false; + state.apiResponses.status.value = action.payload.responseData; - return state; - }, -); + return state; +}); -export const fetchStatusErrorAction = createSingleArtifactAction( - (state, action: GitArtifactErrorPayloadAction) => { +export const fetchStatusErrorAction = + createSingleArtifactAction((state, action) => { const { error } = action.payload; state.apiResponses.status.loading = false; state.apiResponses.status.error = error; return state; - }, -); + }); diff --git a/app/client/src/git/store/actions/uiActions.ts b/app/client/src/git/store/actions/uiActions.ts index fcb69ae73653..fe77a5684e51 100644 --- a/app/client/src/git/store/actions/uiActions.ts +++ b/app/client/src/git/store/actions/uiActions.ts @@ -18,7 +18,7 @@ interface BranchListPopupPayload { open: boolean; } -export const toggleBranchListPopupAction = +export const toggleGitBranchListPopupAction = createSingleArtifactAction((state, action) => { const { open } = action.payload; diff --git a/app/client/src/git/store/gitArtifactSlice.ts b/app/client/src/git/store/gitArtifactSlice.ts index ab2e2dfd780a..da29a9f54b4a 100644 --- a/app/client/src/git/store/gitArtifactSlice.ts +++ b/app/client/src/git/store/gitArtifactSlice.ts @@ -53,7 +53,10 @@ import { deleteBranchSuccessAction, } from "./actions/deleteBranchActions"; import { - toggleBranchListPopupAction, + toggleGitBranchListPopupAction, + toggleGitConnectModalAction, + toggleGitOpsModalAction, + toggleGitSettingsModalAction, toggleRepoLimitErrorModalAction, } from "./actions/uiActions"; import { @@ -61,6 +64,21 @@ import { checkoutBranchInitAction, checkoutBranchSuccessAction, } from "./actions/checkoutBranchActions"; +import { + discardErrorAction, + discardInitAction, + discardSuccessAction, +} from "./actions/discardActions"; +import { + fetchMergeStatusErrorAction, + fetchMergeStatusInitAction, + fetchMergeStatusSuccessAction, +} from "./actions/fetchMergeStatusActions"; +import { + mergeErrorAction, + mergeInitAction, + mergeSuccessAction, +} from "./actions/mergeActions"; const initialState: GitArtifactReduxState = {}; @@ -71,9 +89,34 @@ export const gitArtifactSlice = createSlice({ reducers: { mount: mountAction, unmount: unmountAction, + + // connect connectInit: connectInitAction, connectSuccess: connectSuccessAction, connectError: connectErrorAction, + toggleGitConnectModal: toggleGitConnectModalAction, + toggleRepoLimitErrorModal: toggleRepoLimitErrorModalAction, + + // git ops + commitInit: commitInitAction, + commitSuccess: commitSuccessAction, + commitError: commitErrorAction, + discardInit: discardInitAction, + discardSuccess: discardSuccessAction, + discardError: discardErrorAction, + fetchStatusInit: fetchStatusInitAction, + fetchStatusSuccess: fetchStatusSuccessAction, + fetchStatusError: fetchStatusErrorAction, + fetchMergeStatusInit: fetchMergeStatusInitAction, + fetchMergeStatusSuccess: fetchMergeStatusSuccessAction, + fetchMergeStatusError: fetchMergeStatusErrorAction, + mergeInit: mergeInitAction, + mergeSuccess: mergeSuccessAction, + mergeError: mergeErrorAction, + pullInit: pullInitAction, + pullSuccess: pullSuccessAction, + pullError: pullErrorAction, + toggleGitOpsModal: toggleGitOpsModalAction, // branches fetchBranchesInit: fetchBranchesInitAction, @@ -88,30 +131,21 @@ export const gitArtifactSlice = createSlice({ checkoutBranchInit: checkoutBranchInitAction, checkoutBranchSuccess: checkoutBranchSuccessAction, checkoutBranchError: checkoutBranchErrorAction, + toggleGitBranchListPopup: toggleGitBranchListPopupAction, + + // settings + toggleGitSettingsModal: toggleGitSettingsModalAction, // metadata fetchMetadataInit: fetchMetadataInitAction, fetchMetadataSuccess: fetchMetadataSuccessAction, fetchMetadataError: fetchMetadataErrorAction, - fetchStatusInit: fetchStatusInitAction, - fetchStatusSuccess: fetchStatusSuccessAction, - fetchStatusError: fetchStatusErrorAction, - commitInit: commitInitAction, - commitSuccess: commitSuccessAction, - commitError: commitErrorAction, - pullInit: pullInitAction, - pullSuccess: pullSuccessAction, - pullError: pullErrorAction, fetchLocalProfileInit: fetchLocalProfileInitAction, fetchLocalProfileSuccess: fetchLocalProfileSuccessAction, fetchLocalProfileError: fetchLocalProfileErrorAction, updateLocalProfileInit: updateLocalProfileInitAction, updateLocalProfileSuccess: updateLocalProfileSuccessAction, updateLocalProfileError: updateLocalProfileErrorAction, - - // ui actions - toggleBranchListPopup: toggleBranchListPopupAction, - toggleRepoLimitErrorModal: toggleRepoLimitErrorModalAction, }, }); diff --git a/app/client/src/git/store/selectors/gitSingleArtifactSelectors.ts b/app/client/src/git/store/selectors/gitSingleArtifactSelectors.ts index bff95a870171..e67bcdc99b4a 100644 --- a/app/client/src/git/store/selectors/gitSingleArtifactSelectors.ts +++ b/app/client/src/git/store/selectors/gitSingleArtifactSelectors.ts @@ -15,6 +15,34 @@ export const selectSingleArtifact = ( ]; }; +// git ops +export const selectCommit = ( + state: GitRootState, + artifactDef: GitArtifactDef, +) => selectSingleArtifact(state, artifactDef)?.apiResponses?.commit; + +export const selectDiscard = ( + state: GitRootState, + artifactDef: GitArtifactDef, +) => selectSingleArtifact(state, artifactDef)?.apiResponses?.discard; + +export const selectStatus = ( + state: GitRootState, + artifactDef: GitArtifactDef, +) => selectSingleArtifact(state, artifactDef)?.apiResponses?.status; + +export const selectMerge = (state: GitRootState, artifactDef: GitArtifactDef) => + selectSingleArtifact(state, artifactDef)?.apiResponses?.merge; + +export const selectMergeStatus = ( + state: GitRootState, + artifactDef: GitArtifactDef, +) => selectSingleArtifact(state, artifactDef)?.apiResponses?.mergeStatus; + +export const selectPull = (state: GitRootState, artifactDef: GitArtifactDef) => + selectSingleArtifact(state, artifactDef)?.apiResponses?.pull; + +// git branches export const selectBranches = ( state: GitRootState, artifactDef: GitArtifactDef, diff --git a/app/client/src/git/store/types.ts b/app/client/src/git/store/types.ts index 9e6b8833b7b7..695572840d93 100644 --- a/app/client/src/git/store/types.ts +++ b/app/client/src/git/store/types.ts @@ -9,16 +9,12 @@ import type { import type { FetchGlobalProfileResponseData } from "../requests/fetchGlobalProfileRequest.types"; import type { FetchBranchesResponseData } from "../requests/fetchBranchesRequest.types"; import type { FetchLocalProfileResponseData } from "../requests/fetchLocalProfileRequest.types"; +import type { FetchStatusResponseData } from "git/requests/fetchStatusRequest.types"; +import type { FetchMergeStatusResponseData } from "git/requests/fetchMergeStatusRequest.types"; // These will be updated when contracts are finalized export type GitMetadata = Record; -export type GitStatus = Record; - -export type GitMergeStatus = Record; - -export type GitLocalProfile = Record; - export type GitProtectedBranches = Record; export type GitAutocommitProgress = Record; @@ -38,11 +34,11 @@ interface AsyncStateWithoutValue { export interface GitSingleArtifactAPIResponsesReduxState { metadata: AsyncState; connect: AsyncStateWithoutValue; - status: AsyncState; + status: AsyncState; commit: AsyncStateWithoutValue; pull: AsyncStateWithoutValue; discard: AsyncStateWithoutValue; - mergeStatus: AsyncState; + mergeStatus: AsyncState; merge: AsyncStateWithoutValue; branches: AsyncState; checkoutBranch: AsyncStateWithoutValue; From c3d9a31753c32195438434088788aa2cec139278 Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Tue, 10 Dec 2024 00:14:36 +0800 Subject: [PATCH 016/143] fix: remove gittest --- app/client/src/components/BottomBar/index.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/client/src/components/BottomBar/index.tsx b/app/client/src/components/BottomBar/index.tsx index da11a533102d..c40dbca3fc34 100644 --- a/app/client/src/components/BottomBar/index.tsx +++ b/app/client/src/components/BottomBar/index.tsx @@ -15,7 +15,6 @@ import { useDispatch } from "react-redux"; import { softRefreshActions } from "actions/pluginActionActions"; import { START_SWITCH_ENVIRONMENT } from "ee/constants/messages"; import { getIsAnvilEnabledInCurrentApplication } from "layoutSystems/anvil/integrations/selectors"; -import GitTest from "git/components/connect/GitTest"; export default function BottomBar() { const appId = useSelector(getCurrentApplicationId) || ""; @@ -42,7 +41,6 @@ export default function BottomBar() { /> )} {!isPreviewMode && !isAnvilEnabled && } -
{!isPreviewMode && ( From fa8c461f11b6f59e5a944a5d9f47dc38e829bced Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Tue, 10 Dec 2024 17:22:08 +0800 Subject: [PATCH 017/143] chore: adding init sagas --- .../components/GitContextProvider/index.tsx | 11 +--- .../src/git/requests/fetchBranchesRequest.ts | 2 +- .../requests/fetchBranchesRequest.types.ts | 2 +- .../requests/fetchGitMetadataRequest.types.ts | 7 ++- .../src/git/requests/fetchStatusRequest.ts | 2 +- .../git/requests/fetchStatusRequest.types.ts | 2 +- app/client/src/git/sagas/index.ts | 2 + app/client/src/git/sagas/initGitSaga.ts | 25 +++++++++ .../store/actions/fetchGitMetadataActions.ts | 31 +++++++++++ .../git/store/actions/fetchMetadataActions.ts | 33 ------------ .../src/git/store/actions/initGitActions.ts | 15 ++++++ .../store/actions/triggerAutocommitActions.ts | 9 ++-- app/client/src/git/store/gitArtifactSlice.ts | 51 +++++++++++++++---- app/client/src/git/store/types.ts | 6 +-- 14 files changed, 132 insertions(+), 66 deletions(-) create mode 100644 app/client/src/git/sagas/initGitSaga.ts create mode 100644 app/client/src/git/store/actions/fetchGitMetadataActions.ts delete mode 100644 app/client/src/git/store/actions/fetchMetadataActions.ts create mode 100644 app/client/src/git/store/actions/initGitActions.ts diff --git a/app/client/src/git/components/GitContextProvider/index.tsx b/app/client/src/git/components/GitContextProvider/index.tsx index d093e0f5e709..28e02104ba33 100644 --- a/app/client/src/git/components/GitContextProvider/index.tsx +++ b/app/client/src/git/components/GitContextProvider/index.tsx @@ -1,4 +1,4 @@ -import React, { createContext, useContext, useEffect, useMemo } from "react"; +import React, { createContext, useContext, useMemo } from "react"; import type { GitArtifactType } from "git/constants/enums"; import type { UseGitOpsReturnValue } from "./hooks/useGitOps"; import type { UseGitSettingsReturnValue } from "./hooks/useGitSettings"; @@ -43,15 +43,6 @@ export default function GitContextProvider({ const useGitBranchesReturnValue = useGitBranches(basePayload); const useGitSettingsReturnValue = useGitSettings(basePayload); - const { fetchBranches } = useGitBranchesReturnValue; - - useEffect( - function gitInitEffect() { - fetchBranches(); - }, - [fetchBranches], - ); - // eslint-disable-next-line react-perf/jsx-no-new-object-as-prop const contextValue = { ...useGitOpsReturnValue, diff --git a/app/client/src/git/requests/fetchBranchesRequest.ts b/app/client/src/git/requests/fetchBranchesRequest.ts index 6dd616e9b0fc..c6f267179096 100644 --- a/app/client/src/git/requests/fetchBranchesRequest.ts +++ b/app/client/src/git/requests/fetchBranchesRequest.ts @@ -8,7 +8,7 @@ import type { AxiosPromise } from "axios"; export default async function fetchBranchesRequest( branchedApplicationId: string, - params: FetchBranchesRequestParams, + params: FetchBranchesRequestParams = { pruneBranches: true }, ): AxiosPromise { const queryParams = {} as FetchBranchesRequestParams; diff --git a/app/client/src/git/requests/fetchBranchesRequest.types.ts b/app/client/src/git/requests/fetchBranchesRequest.types.ts index dadab374a03b..0ea1aeed64cf 100644 --- a/app/client/src/git/requests/fetchBranchesRequest.types.ts +++ b/app/client/src/git/requests/fetchBranchesRequest.types.ts @@ -1,7 +1,7 @@ import type { ApiResponse } from "api/ApiResponses"; export interface FetchBranchesRequestParams { - pruneBranches: boolean; + pruneBranches?: boolean; } interface SingleBranch { diff --git a/app/client/src/git/requests/fetchGitMetadataRequest.types.ts b/app/client/src/git/requests/fetchGitMetadataRequest.types.ts index 95ef9f6ec3ab..c532052e9793 100644 --- a/app/client/src/git/requests/fetchGitMetadataRequest.types.ts +++ b/app/client/src/git/requests/fetchGitMetadataRequest.types.ts @@ -1,4 +1,6 @@ -export interface FetchGitMetadataResponse { +import type { ApiResponse } from "api/types"; + +export interface FetchGitMetadataResponseData { branchName: string; defaultBranchName: string; remoteUrl: string; @@ -13,3 +15,6 @@ export interface FetchGitMetadataResponse { }; isAutoDeploymentEnabled?: boolean; } + +export type FetchGitMetadataResponse = + ApiResponse; diff --git a/app/client/src/git/requests/fetchStatusRequest.ts b/app/client/src/git/requests/fetchStatusRequest.ts index 587b4f66ea0b..4f4b1467e66d 100644 --- a/app/client/src/git/requests/fetchStatusRequest.ts +++ b/app/client/src/git/requests/fetchStatusRequest.ts @@ -8,7 +8,7 @@ import type { AxiosResponse } from "axios"; export default async function fetchStatusRequest( branchedApplicationId: string, - params: FetchStatusRequestParams, + params: FetchStatusRequestParams = { compareRemote: true }, ): Promise> { return Api.get(`${GIT_BASE_URL}/status/app/${branchedApplicationId}`, params); } diff --git a/app/client/src/git/requests/fetchStatusRequest.types.ts b/app/client/src/git/requests/fetchStatusRequest.types.ts index 975f94b2b483..c4400688b794 100644 --- a/app/client/src/git/requests/fetchStatusRequest.types.ts +++ b/app/client/src/git/requests/fetchStatusRequest.types.ts @@ -1,7 +1,7 @@ import type { ApiResponse } from "api/types"; export interface FetchStatusRequestParams { - compareRemote: boolean; + compareRemote?: boolean; } export interface FetchStatusResponseData { added: string[]; diff --git a/app/client/src/git/sagas/index.ts b/app/client/src/git/sagas/index.ts index 076853a8612a..6eae3108e484 100644 --- a/app/client/src/git/sagas/index.ts +++ b/app/client/src/git/sagas/index.ts @@ -8,9 +8,11 @@ import fetchBranchesSaga from "./fetchBranchesSaga"; import fetchLocalProfileSaga from "./fetchLocalProfileSaga"; import updateLocalProfileSaga from "./updateLocalProfileSaga"; import updateGlobalProfileSaga from "./updateGlobalProfileSaga"; +import initGitForEditorSaga from "./initGitSaga"; export function* gitSagas() { yield all([ + takeLatest(gitArtifactActions.initGitForEditor.type, initGitForEditorSaga), takeLatest(gitArtifactActions.connectInit.type, connectSaga), // branches diff --git a/app/client/src/git/sagas/initGitSaga.ts b/app/client/src/git/sagas/initGitSaga.ts new file mode 100644 index 000000000000..d2d85f82d7be --- /dev/null +++ b/app/client/src/git/sagas/initGitSaga.ts @@ -0,0 +1,25 @@ +import { GitArtifactType } from "git/constants/enums"; +import type { InitGitForEditorPayload } from "git/store/actions/initGitActions"; +import { gitArtifactActions } from "git/store/gitArtifactSlice"; +import type { GitArtifactPayloadAction } from "git/store/types"; +import { put } from "redux-saga/effects"; + +export default function* initGitForEditorSaga( + action: GitArtifactPayloadAction, +) { + const { artifact, artifactType, baseArtifactId } = action.payload; + const basePayload = { artifactType, baseArtifactId }; + + yield put(gitArtifactActions.mount(basePayload)); + + if (artifactType === GitArtifactType.Application) { + if (!!artifact.gitApplicationMetadata) { + yield put(gitArtifactActions.fetchGitMetadataInit(basePayload)); + // yield take(gitArtifactActions.fetchGitMetadataSuccess.type); + yield put(gitArtifactActions.triggerAutocommitInit(basePayload)); + yield put(gitArtifactActions.fetchBranchesInit(basePayload)); + yield put(gitArtifactActions.fetchProtectedBranchesInit(basePayload)); + yield put(gitArtifactActions.fetchStatusInit(basePayload)); + } + } +} diff --git a/app/client/src/git/store/actions/fetchGitMetadataActions.ts b/app/client/src/git/store/actions/fetchGitMetadataActions.ts new file mode 100644 index 000000000000..6bbb8d41d380 --- /dev/null +++ b/app/client/src/git/store/actions/fetchGitMetadataActions.ts @@ -0,0 +1,31 @@ +import type { GitAsyncErrorPayload, GitAsyncSuccessPayload } from "../types"; +import { createSingleArtifactAction } from "../helpers/createSingleArtifactAction"; +import type { FetchGitMetadataResponseData } from "git/requests/fetchGitMetadataRequest.types"; + +export const fetchGitMetadataInitAction = createSingleArtifactAction( + (state) => { + state.apiResponses.metadata.loading = true; + state.apiResponses.metadata.error = null; + + return state; + }, +); + +export const fetchGitMetadataSuccessAction = createSingleArtifactAction< + GitAsyncSuccessPayload +>((state, action) => { + state.apiResponses.metadata.loading = false; + state.apiResponses.metadata.value = action.payload.responseData; + + return state; +}); + +export const fetchGitMetadataErrorAction = + createSingleArtifactAction((state, action) => { + const { error } = action.payload; + + state.apiResponses.metadata.loading = false; + state.apiResponses.metadata.error = error; + + return state; + }); diff --git a/app/client/src/git/store/actions/fetchMetadataActions.ts b/app/client/src/git/store/actions/fetchMetadataActions.ts deleted file mode 100644 index f4d1fd9da2cb..000000000000 --- a/app/client/src/git/store/actions/fetchMetadataActions.ts +++ /dev/null @@ -1,33 +0,0 @@ -import type { - GitArtifactPayloadAction, - GitArtifactErrorPayloadAction, - GitMetadata, -} from "../types"; -import { createSingleArtifactAction } from "../helpers/createSingleArtifactAction"; - -export const fetchMetadataInitAction = createSingleArtifactAction((state) => { - state.apiResponses.metadata.loading = true; - state.apiResponses.metadata.error = null; - - return state; -}); - -export const fetchMetadataSuccessAction = createSingleArtifactAction( - (state, action: GitArtifactPayloadAction<{ metadata: GitMetadata }>) => { - state.apiResponses.metadata.loading = false; - state.apiResponses.metadata.value = action.payload.metadata; - - return state; - }, -); - -export const fetchMetadataErrorAction = createSingleArtifactAction( - (state, action: GitArtifactErrorPayloadAction) => { - const { error } = action.payload; - - state.apiResponses.metadata.loading = false; - state.apiResponses.metadata.error = error; - - return state; - }, -); diff --git a/app/client/src/git/store/actions/initGitActions.ts b/app/client/src/git/store/actions/initGitActions.ts new file mode 100644 index 000000000000..5ba453b0edaf --- /dev/null +++ b/app/client/src/git/store/actions/initGitActions.ts @@ -0,0 +1,15 @@ +import type { FetchGitMetadataResponseData } from "git/requests/fetchGitMetadataRequest.types"; +import { createSingleArtifactAction } from "../helpers/createSingleArtifactAction"; + +export interface InitGitForEditorPayload { + artifact: { + id: string; + baseId: string; + gitApplicationMetadata?: Partial; + }; +} + +export const initGitForEditorAction = + createSingleArtifactAction((state) => { + return state; + }); diff --git a/app/client/src/git/store/actions/triggerAutocommitActions.ts b/app/client/src/git/store/actions/triggerAutocommitActions.ts index 414de9ed68c8..29ec4667cbe1 100644 --- a/app/client/src/git/store/actions/triggerAutocommitActions.ts +++ b/app/client/src/git/store/actions/triggerAutocommitActions.ts @@ -1,5 +1,5 @@ import { createSingleArtifactAction } from "../helpers/createSingleArtifactAction"; -import type { GitArtifactErrorPayloadAction } from "../types"; +import type { GitAsyncErrorPayload } from "../types"; export const triggerAutocommitInitAction = createSingleArtifactAction( (state) => { @@ -18,13 +18,12 @@ export const triggerAutocommitSuccessAction = createSingleArtifactAction( }, ); -export const triggerAutocommitErrorAction = createSingleArtifactAction( - (state, action: GitArtifactErrorPayloadAction) => { +export const triggerAutocommitErrorAction = + createSingleArtifactAction((state, action) => { const { error } = action.payload; state.apiResponses.triggerAutocommit.loading = false; state.apiResponses.triggerAutocommit.error = error; return state; - }, -); + }); diff --git a/app/client/src/git/store/gitArtifactSlice.ts b/app/client/src/git/store/gitArtifactSlice.ts index da29a9f54b4a..4bbd810a64ab 100644 --- a/app/client/src/git/store/gitArtifactSlice.ts +++ b/app/client/src/git/store/gitArtifactSlice.ts @@ -8,10 +8,10 @@ import { connectSuccessAction, } from "./actions/connectActions"; import { - fetchMetadataErrorAction, - fetchMetadataInitAction, - fetchMetadataSuccessAction, -} from "./actions/fetchMetadataActions"; + fetchGitMetadataErrorAction, + fetchGitMetadataInitAction, + fetchGitMetadataSuccessAction, +} from "./actions/fetchGitMetadataActions"; import { fetchBranchesErrorAction, fetchBranchesInitAction, @@ -79,6 +79,26 @@ import { mergeInitAction, mergeSuccessAction, } from "./actions/mergeActions"; +import { + triggerAutocommitErrorAction, + triggerAutocommitInitAction, + triggerAutocommitSuccessAction, +} from "./actions/triggerAutocommitActions"; +import { + toggleAutocommitErrorAction, + toggleAutocommitInitAction, + toggleAutocommitSuccessAction, +} from "./actions/toggleAutocommitActions"; +import { + fetchProtectedBranchesErrorAction, + fetchProtectedBranchesInitAction, + fetchProtectedBranchesSuccessAction, +} from "./actions/fetchProtectedBranchesActions"; +import { + updateProtectedBranchesErrorAction, + updateProtectedBranchesInitAction, +} from "./actions/updateProtectedBranchesActions"; +import { initGitForEditorAction } from "./actions/initGitActions"; const initialState: GitArtifactReduxState = {}; @@ -87,8 +107,13 @@ export const gitArtifactSlice = createSlice({ reducerPath: "git.artifact", initialState, reducers: { + // init + initGitForEditor: initGitForEditorAction, mount: mountAction, unmount: unmountAction, + fetchGitMetadataInit: fetchGitMetadataInitAction, + fetchGitMetadataSuccess: fetchGitMetadataSuccessAction, + fetchGitMetadataError: fetchGitMetadataErrorAction, // connect connectInit: connectInitAction, @@ -135,17 +160,25 @@ export const gitArtifactSlice = createSlice({ // settings toggleGitSettingsModal: toggleGitSettingsModalAction, - - // metadata - fetchMetadataInit: fetchMetadataInitAction, - fetchMetadataSuccess: fetchMetadataSuccessAction, - fetchMetadataError: fetchMetadataErrorAction, fetchLocalProfileInit: fetchLocalProfileInitAction, fetchLocalProfileSuccess: fetchLocalProfileSuccessAction, fetchLocalProfileError: fetchLocalProfileErrorAction, updateLocalProfileInit: updateLocalProfileInitAction, updateLocalProfileSuccess: updateLocalProfileSuccessAction, updateLocalProfileError: updateLocalProfileErrorAction, + fetchProtectedBranchesInit: fetchProtectedBranchesInitAction, + fetchProtectedBranchesSuccess: fetchProtectedBranchesSuccessAction, + fetchProtectedBranchesError: fetchProtectedBranchesErrorAction, + updateProtectedBranchesInit: updateProtectedBranchesInitAction, + updateProtectedBranchesError: updateProtectedBranchesErrorAction, + + // autocommit + toggleAutocommitInit: toggleAutocommitInitAction, + toggleAutocommitSuccess: toggleAutocommitSuccessAction, + toggleAutocommitError: toggleAutocommitErrorAction, + triggerAutocommitInit: triggerAutocommitInitAction, + triggerAutocommitSuccess: triggerAutocommitSuccessAction, + triggerAutocommitError: triggerAutocommitErrorAction, }, }); diff --git a/app/client/src/git/store/types.ts b/app/client/src/git/store/types.ts index 695572840d93..c941b13e96eb 100644 --- a/app/client/src/git/store/types.ts +++ b/app/client/src/git/store/types.ts @@ -11,9 +11,7 @@ import type { FetchBranchesResponseData } from "../requests/fetchBranchesRequest import type { FetchLocalProfileResponseData } from "../requests/fetchLocalProfileRequest.types"; import type { FetchStatusResponseData } from "git/requests/fetchStatusRequest.types"; import type { FetchMergeStatusResponseData } from "git/requests/fetchMergeStatusRequest.types"; - -// These will be updated when contracts are finalized -export type GitMetadata = Record; +import type { FetchGitMetadataResponseData } from "git/requests/fetchGitMetadataRequest.types"; export type GitProtectedBranches = Record; @@ -32,7 +30,7 @@ interface AsyncStateWithoutValue { error: string | null; } export interface GitSingleArtifactAPIResponsesReduxState { - metadata: AsyncState; + metadata: AsyncState; connect: AsyncStateWithoutValue; status: AsyncState; commit: AsyncStateWithoutValue; From 9b1414e01144c9d665a283825bb3de20b303ea63 Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Tue, 10 Dec 2024 18:11:56 +0800 Subject: [PATCH 018/143] fix: test fixes --- .../GitQuickActions/ConnectButton.test.tsx | 42 ++++++------ .../helpers/getPullButtonStatus.test.ts | 2 +- .../components/GitQuickActions/index.test.tsx | 64 ++++++++----------- 3 files changed, 47 insertions(+), 61 deletions(-) diff --git a/app/client/src/git/components/GitQuickActions/ConnectButton.test.tsx b/app/client/src/git/components/GitQuickActions/ConnectButton.test.tsx index 71406cd399c4..ee01a5af95da 100644 --- a/app/client/src/git/components/GitQuickActions/ConnectButton.test.tsx +++ b/app/client/src/git/components/GitQuickActions/ConnectButton.test.tsx @@ -2,7 +2,6 @@ import React from "react"; import { render, screen, fireEvent } from "@testing-library/react"; import ConnectButton from "./ConnectButton"; import AnalyticsUtil from "ee/utils/AnalyticsUtil"; -import { GitSyncModalTab } from "entities/GitSync"; import "@testing-library/jest-dom"; import { theme } from "constants/DefaultTheme"; import { ThemeProvider } from "styled-components"; @@ -27,7 +26,7 @@ jest.mock("@appsmith/ads", () => ({ })); describe("ConnectButton Component", () => { - const openGitSyncModalMock = jest.fn(); + const onClickMock = jest.fn(); afterEach(() => { jest.clearAllMocks(); @@ -36,7 +35,7 @@ describe("ConnectButton Component", () => { it("should render correctly when isConnectPermitted is true", () => { render( - + , ); @@ -61,7 +60,7 @@ describe("ConnectButton Component", () => { it("should handle click when isConnectPermitted is true", () => { render( - + , ); @@ -69,25 +68,25 @@ describe("ConnectButton Component", () => { fireEvent.click(button); - expect(AnalyticsUtil.logEvent).toHaveBeenCalledWith( - "GS_CONNECT_GIT_CLICK", - { - source: "BOTTOM_BAR_GIT_CONNECT_BUTTON", - }, - ); + expect(onClickMock).toHaveBeenCalled(); + + // ! might have to move this to Quick Actions instead + // expect(AnalyticsUtil.logEvent).toHaveBeenCalledWith( + // "GS_CONNECT_GIT_CLICK", + // { + // source: "BOTTOM_BAR_GIT_CONNECT_BUTTON", + // }, + // ); - expect(openGitSyncModalMock).toHaveBeenCalledWith({ - tab: GitSyncModalTab.GIT_CONNECTION, - }); + // expect(onClickMock).toHaveBeenCalledWith({ + // tab: GitSyncModalTab.GIT_CONNECTION, + // }); }); it("should render correctly when isConnectPermitted is false", () => { render( - + , ); @@ -115,10 +114,7 @@ describe("ConnectButton Component", () => { it("should not handle click when isConnectPermitted is false", () => { render( - + , ); @@ -127,13 +123,13 @@ describe("ConnectButton Component", () => { fireEvent.click(button); expect(AnalyticsUtil.logEvent).not.toHaveBeenCalled(); - expect(openGitSyncModalMock).not.toHaveBeenCalled(); + expect(onClickMock).not.toHaveBeenCalled(); }); it("should display correct tooltip content when isConnectPermitted is true", () => { render( - + , ); diff --git a/app/client/src/git/components/GitQuickActions/helpers/getPullButtonStatus.test.ts b/app/client/src/git/components/GitQuickActions/helpers/getPullButtonStatus.test.ts index 6a221fe2ea9b..8f8d27562143 100644 --- a/app/client/src/git/components/GitQuickActions/helpers/getPullButtonStatus.test.ts +++ b/app/client/src/git/components/GitQuickActions/helpers/getPullButtonStatus.test.ts @@ -99,7 +99,7 @@ describe("getPullBtnStatus", () => { const result = getPullBtnStatus(params); expect(result).toEqual({ - disabled: true, + isDisabled: true, message: "No commits to pull. This branch is in sync with the remote repository", }); diff --git a/app/client/src/git/components/GitQuickActions/index.test.tsx b/app/client/src/git/components/GitQuickActions/index.test.tsx index a7c41bb2cd08..72138f9b9b38 100644 --- a/app/client/src/git/components/GitQuickActions/index.test.tsx +++ b/app/client/src/git/components/GitQuickActions/index.test.tsx @@ -2,11 +2,10 @@ import React from "react"; import { render, screen, fireEvent } from "@testing-library/react"; import AnalyticsUtil from "ee/utils/AnalyticsUtil"; import QuickActions from "."; -import { GitSettingsTab } from "../../constants/enums"; -import { GitSyncModalTab } from "entities/GitSync"; import { theme } from "constants/DefaultTheme"; import { ThemeProvider } from "styled-components"; import "@testing-library/jest-dom/extend-expect"; +import { GitOpsTab, GitSettingsTab } from "git/constants/enums"; jest.mock("ee/utils/AnalyticsUtil", () => ({ logEvent: jest.fn(), @@ -84,12 +83,8 @@ describe("QuickActions Component", () => { const props = { ...defaultProps, isGitConnected: true, - gitMetadata: { - autoCommitConfig: { - enabled: true, - }, - }, - isPollingAutocommit: true, + isAutocommitEnabled: true, + isAutocommitPolling: true, }; const { container } = render( @@ -120,10 +115,10 @@ describe("QuickActions Component", () => { )[0]; fireEvent.click(commitButton); - expect(props.toggleGitOpsModal).toHaveBeenCalledWith({ - open: true, - tab: GitSyncModalTab.DEPLOY, - }); + expect(props.toggleGitOpsModal).toHaveBeenCalledWith( + true, + GitOpsTab.Deploy, + ); expect(AnalyticsUtil.logEvent).toHaveBeenCalledWith( "GS_DEPLOY_GIT_MODAL_TRIGGERED", { @@ -136,14 +131,12 @@ describe("QuickActions Component", () => { const props = { ...defaultProps, isGitConnected: true, - isDiscardInProgress: false, - isPullInProgress: false, - isFetchingGitStatus: false, - pullDisabled: false, - gitStatus: { - behindCount: 1, - isClean: false, - }, + isDiscardLoading: false, + isPullLoading: false, + isFetchStatusLoading: false, + isPullDisabled: false, + statusBehindCount: 1, + statusIsClean: false, isProtectedMode: true, }; @@ -183,10 +176,7 @@ describe("QuickActions Component", () => { source: "BOTTOM_BAR_GIT_MERGE_BUTTON", }, ); - expect(props.toggleGitOpsModal).toHaveBeenCalledWith({ - open: true, - tab: GitSyncModalTab.MERGE, - }); + expect(props.toggleGitOpsModal).toHaveBeenCalledWith(true, GitOpsTab.Merge); }); it("should call onSettingsClick when settings button is clicked", () => { @@ -208,10 +198,10 @@ describe("QuickActions Component", () => { expect(AnalyticsUtil.logEvent).toHaveBeenCalledWith("GS_SETTING_CLICK", { source: "BOTTOM_BAR_GIT_SETTING_BUTTON", }); - expect(props.toggleGitSettingsModal).toHaveBeenCalledWith({ - open: true, - tab: GitSettingsTab.General, - }); + expect(props.toggleGitSettingsModal).toHaveBeenCalledWith( + true, + GitSettingsTab.General, + ); }); it("should disable commit button when isProtectedMode is true", () => { @@ -237,7 +227,7 @@ describe("QuickActions Component", () => { const props = { ...defaultProps, isGitConnected: true, - isPullInProgress: true, + isPullLoading: true, }; const { container } = render( @@ -259,7 +249,7 @@ describe("QuickActions Component", () => { const props = { ...defaultProps, isGitConnected: true, - changesToCommit: 5, + statusChangeCount: 5, }; render( @@ -277,7 +267,7 @@ describe("QuickActions Component", () => { ...defaultProps, isGitConnected: true, isProtectedMode: true, - changesToCommit: 5, + statusChangeCount: 5, }; render( @@ -289,10 +279,12 @@ describe("QuickActions Component", () => { }); it("should disable pull button when pullDisabled is true", () => { - const mockGetPullBtnStatus = jest.requireMock("./helpers").getPullBtnStatus; + const mockGetPullBtnStatus = jest.requireMock( + "./helpers/getPullButtonStatus", + ).default; mockGetPullBtnStatus.mockReturnValue({ - disabled: true, + isDisabled: true, message: "Pull Disabled", }); @@ -316,10 +308,8 @@ describe("QuickActions Component", () => { const props = { ...defaultProps, isGitConnected: true, - gitStatus: { - behindCount: 3, - isClean: true, - }, + statusBehindCount: 3, + statusIsClean: true, }; render( From 2de337e206c895ac7248541b1a6a7e55559bb5d0 Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Tue, 10 Dec 2024 18:24:22 +0800 Subject: [PATCH 019/143] fix: review changes --- .../git/components/GitContextProvider/hooks/useGitOps.ts | 2 +- .../components/GitQuickActions/BranchButton/index.tsx | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/app/client/src/git/components/GitContextProvider/hooks/useGitOps.ts b/app/client/src/git/components/GitContextProvider/hooks/useGitOps.ts index 3c8cbe6cb71c..3c9f3990d6e9 100644 --- a/app/client/src/git/components/GitContextProvider/hooks/useGitOps.ts +++ b/app/client/src/git/components/GitContextProvider/hooks/useGitOps.ts @@ -40,7 +40,7 @@ export interface UseGitOpsReturnValue { pullLoading: boolean; pullError: string | null; pull: () => void; - toggleGitOpsModal: (open: boolean, tab: keyof typeof GitOpsTab) => void; + toggleGitOpsModal: (open: boolean, tab?: keyof typeof GitOpsTab) => void; } export default function useGitOps({ diff --git a/app/client/src/git/components/GitQuickActions/BranchButton/index.tsx b/app/client/src/git/components/GitQuickActions/BranchButton/index.tsx index 466b8f961e5d..88a694402db6 100644 --- a/app/client/src/git/components/GitQuickActions/BranchButton/index.tsx +++ b/app/client/src/git/components/GitQuickActions/BranchButton/index.tsx @@ -14,7 +14,7 @@ interface BranchButtonProps { isOpen?: boolean; setIsOpen?: (isOpen: boolean) => void; isDisabled?: boolean; - isProtectedMode?: false; + isProtectedMode?: boolean; isStatusClean?: boolean; } @@ -41,6 +41,10 @@ const BranchButtonLabel = styled.span` text-overflow: ellipsis; `; +const popoverModifiers: { offset: Record } = { + offset: { enabled: true, options: { offset: [7, 10] } }, +}; + export default function BranchButton({ currentBranch = "", isDisabled = false, @@ -76,8 +80,7 @@ export default function BranchButton({ hasBackdrop isOpen={isOpen} minimal - // eslint-disable-next-line react-perf/jsx-no-new-object-as-prop - modifiers={{ offset: { enabled: true, options: { offset: [7, 10] } } }} + modifiers={popoverModifiers} onInteraction={onPopoverInteraction} placement="top-start" > From 3a470551bb3a8fe7084f05467eca477839d882b4 Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Wed, 11 Dec 2024 01:34:49 +0800 Subject: [PATCH 020/143] chore: adding autocommit to saga --- .../fetchAutocommitProgressRequest.ts | 4 +- .../fetchAutocommitProgressRequest.types.ts | 8 +- .../git/requests/fetchGitMetadataRequest.ts | 4 +- .../git/requests/triggerAutocommitRequest.ts | 4 +- .../triggerAutocommitRequest.types.ts | 8 +- .../src/git/sagas/fetchGitMetadataSaga.ts | 35 +++++ app/client/src/git/sagas/index.ts | 147 ++++++++++++++---- app/client/src/git/sagas/initGitSaga.ts | 11 +- .../src/git/sagas/triggerAutcommitSaga.ts | 126 +++++++++++++++ .../actions/fetchAutocommitProgressActions.ts | 22 +-- .../store/actions/triggerAutocommitActions.ts | 27 +++- app/client/src/git/store/gitArtifactSlice.ts | 12 ++ .../helpers/gitSingleArtifactInitialState.ts | 3 +- .../selectors/gitSingleArtifactSelectors.ts | 14 ++ app/client/src/git/store/types.ts | 4 +- 15 files changed, 366 insertions(+), 63 deletions(-) create mode 100644 app/client/src/git/sagas/fetchGitMetadataSaga.ts create mode 100644 app/client/src/git/sagas/triggerAutcommitSaga.ts diff --git a/app/client/src/git/requests/fetchAutocommitProgressRequest.ts b/app/client/src/git/requests/fetchAutocommitProgressRequest.ts index 8ad1c71d22c8..1f68624b780c 100644 --- a/app/client/src/git/requests/fetchAutocommitProgressRequest.ts +++ b/app/client/src/git/requests/fetchAutocommitProgressRequest.ts @@ -1,11 +1,11 @@ import Api from "api/Api"; import { GIT_BASE_URL } from "./constants"; -import type { AxiosResponse } from "axios"; +import type { AxiosPromise } from "axios"; import type { FetchAutocommitProgressResponse } from "./fetchAutocommitProgressRequest.types"; export default async function fetchAutocommitProgressRequest( baseApplicationId: string, -): Promise> { +): AxiosPromise { return Api.get( `${GIT_BASE_URL}/auto-commit/progress/app/${baseApplicationId}`, ); diff --git a/app/client/src/git/requests/fetchAutocommitProgressRequest.types.ts b/app/client/src/git/requests/fetchAutocommitProgressRequest.types.ts index 60f10b5fc6b3..3745c107dd22 100644 --- a/app/client/src/git/requests/fetchAutocommitProgressRequest.types.ts +++ b/app/client/src/git/requests/fetchAutocommitProgressRequest.types.ts @@ -1,7 +1,11 @@ +import type { ApiResponse } from "api/types"; import type { AutocommitStatus } from "../constants/enums"; -export interface FetchAutocommitProgressResponse { - autoCommitResponse: AutocommitStatus; +export interface FetchAutocommitProgressResponseData { + autoCommitResponse: keyof typeof AutocommitStatus; progress: number; branchName: string; } + +export type FetchAutocommitProgressResponse = + ApiResponse; diff --git a/app/client/src/git/requests/fetchGitMetadataRequest.ts b/app/client/src/git/requests/fetchGitMetadataRequest.ts index 136f5776f557..7b3376b8ef0e 100644 --- a/app/client/src/git/requests/fetchGitMetadataRequest.ts +++ b/app/client/src/git/requests/fetchGitMetadataRequest.ts @@ -1,10 +1,10 @@ import Api from "api/Api"; import { GIT_BASE_URL } from "./constants"; -import type { AxiosResponse } from "axios"; +import type { AxiosPromise } from "axios"; import type { FetchGitMetadataResponse } from "./fetchGitMetadataRequest.types"; export default async function fetchGitMetadataRequest( baseApplicationId: string, -): Promise> { +): AxiosPromise { return Api.get(`${GIT_BASE_URL}/metadata/app/${baseApplicationId}`); } diff --git a/app/client/src/git/requests/triggerAutocommitRequest.ts b/app/client/src/git/requests/triggerAutocommitRequest.ts index 01c603cb4ce5..7a2085df2d31 100644 --- a/app/client/src/git/requests/triggerAutocommitRequest.ts +++ b/app/client/src/git/requests/triggerAutocommitRequest.ts @@ -1,10 +1,10 @@ import Api from "api/Api"; import { GIT_BASE_URL } from "./constants"; -import type { AxiosResponse } from "axios"; +import type { AxiosPromise } from "axios"; import type { TriggerAutocommitResponse } from "./triggerAutocommitRequest.types"; export default async function triggerAutocommitRequest( branchedApplicationId: string, -): Promise> { +): AxiosPromise { return Api.post(`${GIT_BASE_URL}/auto-commit/app/${branchedApplicationId}`); } diff --git a/app/client/src/git/requests/triggerAutocommitRequest.types.ts b/app/client/src/git/requests/triggerAutocommitRequest.types.ts index 6abf80ecf226..cbb28d3610f8 100644 --- a/app/client/src/git/requests/triggerAutocommitRequest.types.ts +++ b/app/client/src/git/requests/triggerAutocommitRequest.types.ts @@ -1,7 +1,11 @@ +import type { ApiResponse } from "api/types"; import type { AutocommitStatus } from "../constants/enums"; -export interface TriggerAutocommitResponse { - autoCommitResponse: AutocommitStatus; +export interface TriggerAutocommitResponseData { + autoCommitResponse: keyof typeof AutocommitStatus; progress: number; branchName: string; } + +export type TriggerAutocommitResponse = + ApiResponse; diff --git a/app/client/src/git/sagas/fetchGitMetadataSaga.ts b/app/client/src/git/sagas/fetchGitMetadataSaga.ts new file mode 100644 index 000000000000..9f694ff10f36 --- /dev/null +++ b/app/client/src/git/sagas/fetchGitMetadataSaga.ts @@ -0,0 +1,35 @@ +import fetchGitMetadataRequest from "git/requests/fetchGitMetadataRequest"; +import type { FetchGitMetadataResponse } from "git/requests/fetchGitMetadataRequest.types"; +import { gitArtifactActions } from "git/store/gitArtifactSlice"; +import type { GitArtifactPayloadAction } from "git/store/types"; +import { call, put } from "redux-saga/effects"; +import { validateResponse } from "sagas/ErrorSagas"; + +export default function* fetchGitMetadataSaga( + action: GitArtifactPayloadAction, +) { + const { artifactType, baseArtifactId } = action.payload; + const basePayload = { artifactType, baseArtifactId }; + let response: FetchGitMetadataResponse | undefined; + + try { + response = yield call(fetchGitMetadataRequest, baseArtifactId); + const isValidResponse: boolean = yield validateResponse(response, false); + + if (response && isValidResponse) { + yield put( + gitArtifactActions.fetchGitMetadataSuccess({ + ...basePayload, + responseData: response.data, + }), + ); + } + } catch (error) { + yield put( + gitArtifactActions.fetchGitMetadataError({ + ...basePayload, + error: error as string, + }), + ); + } +} diff --git a/app/client/src/git/sagas/index.ts b/app/client/src/git/sagas/index.ts index 6eae3108e484..79cd08debbfd 100644 --- a/app/client/src/git/sagas/index.ts +++ b/app/client/src/git/sagas/index.ts @@ -1,5 +1,11 @@ import { gitArtifactActions } from "git/store/gitArtifactSlice"; -import { all, takeLatest } from "redux-saga/effects"; +import { + actionChannel, + call, + fork, + take, + takeLatest, +} from "redux-saga/effects"; import connectSaga from "./connectSaga"; import commitSaga from "./commitSaga"; import { gitConfigActions } from "git/store/gitConfigSlice"; @@ -9,31 +15,118 @@ import fetchLocalProfileSaga from "./fetchLocalProfileSaga"; import updateLocalProfileSaga from "./updateLocalProfileSaga"; import updateGlobalProfileSaga from "./updateGlobalProfileSaga"; import initGitForEditorSaga from "./initGitSaga"; +import fetchGitMetadataSaga from "./fetchGitMetadataSaga"; +import triggerAutocommitSaga from "./triggerAutcommitSaga"; +import type { TakeableChannel } from "redux-saga"; +import { objectKeys } from "@appsmith/utils"; +import type { PayloadAction } from "@reduxjs/toolkit"; -export function* gitSagas() { - yield all([ - takeLatest(gitArtifactActions.initGitForEditor.type, initGitForEditorSaga), - takeLatest(gitArtifactActions.connectInit.type, connectSaga), - - // branches - takeLatest(gitArtifactActions.fetchBranchesInit.type, fetchBranchesSaga), - - takeLatest(gitArtifactActions.commitInit.type, commitSaga), - takeLatest( - gitArtifactActions.fetchLocalProfileInit.type, - fetchLocalProfileSaga, - ), - takeLatest( - gitArtifactActions.updateLocalProfileInit.type, - updateLocalProfileSaga, - ), - takeLatest( - gitConfigActions.fetchGlobalProfileInit.type, - fetchGlobalProfileSaga, - ), - takeLatest( - gitConfigActions.updateGlobalProfileInit.type, - updateGlobalProfileSaga, - ), - ]); +const gitRequestBlockingActions: Record< + string, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (action: PayloadAction) => Generator +> = { + // init + [gitArtifactActions.fetchGitMetadataInit.type]: fetchGitMetadataSaga, + + // connect + [gitArtifactActions.connectInit.type]: connectSaga, + + // ops + [gitArtifactActions.commitInit.type]: commitSaga, + + // branches + [gitArtifactActions.fetchBranchesInit.type]: fetchBranchesSaga, + + // settings + [gitArtifactActions.fetchLocalProfileInit.type]: fetchLocalProfileSaga, + [gitArtifactActions.updateLocalProfileInit.type]: updateLocalProfileSaga, + [gitConfigActions.fetchGlobalProfileInit.type]: fetchGlobalProfileSaga, + [gitConfigActions.updateGlobalProfileInit.type]: updateGlobalProfileSaga, + + // autocommit + [gitArtifactActions.triggerAutocommitInit.type]: triggerAutocommitSaga, +}; + +const gitRequestNonBlockingActions: Record< + string, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (action: PayloadAction) => Generator +> = { + // init + [gitArtifactActions.initGitForEditor.type]: initGitForEditorSaga, +}; + +/** + * All git actions on the server are behind a lock, + * that means that only one action can be performed at once. + * + * To follow the same principle, we will queue all actions from the client + * as well and only perform one action at a time. + * + * This will ensure that client is not running parallel requests to the server for git + * */ +function* watchGitBlockingRequests() { + const gitActionChannel: TakeableChannel = yield actionChannel( + objectKeys(gitRequestBlockingActions), + ); + + while (true) { + const action: PayloadAction = yield take(gitActionChannel); + + yield call(gitRequestBlockingActions[action.type], action); + } } + +function* watchGitNonBlockingRequests() { + const keys = objectKeys(gitRequestNonBlockingActions); + + for (const actionType of keys) { + yield takeLatest(actionType, gitRequestNonBlockingActions[actionType]); + } +} + +export default function* gitSagas() { + yield fork(watchGitNonBlockingRequests); + yield fork(watchGitBlockingRequests); +} + +// export function* gitSagas() { +// yield all([ +// // init +// takeLatest(gitArtifactActions.initGitForEditor.type, initGitForEditorSaga), +// takeLatest( +// gitArtifactActions.fetchGitMetadataInit.type, +// fetchGitMetadataSaga, +// ), + +// takeLatest(gitArtifactActions.connectInit.type, connectSaga), + +// // branches +// takeLatest(gitArtifactActions.fetchBranchesInit.type, fetchBranchesSaga), + +// takeLatest(gitArtifactActions.commitInit.type, commitSaga), +// takeLatest( +// gitArtifactActions.fetchLocalProfileInit.type, +// fetchLocalProfileSaga, +// ), +// takeLatest( +// gitArtifactActions.updateLocalProfileInit.type, +// updateLocalProfileSaga, +// ), +// takeLatest( +// gitConfigActions.fetchGlobalProfileInit.type, +// fetchGlobalProfileSaga, +// ), +// takeLatest( +// gitConfigActions.updateGlobalProfileInit.type, +// updateGlobalProfileSaga, +// ), + +// // autocommit +// takeLatest( +// gitArtifactActions.triggerAutocommitInit.type, +// triggerAutocommitSaga, +// ), +// ]); +// } diff --git a/app/client/src/git/sagas/initGitSaga.ts b/app/client/src/git/sagas/initGitSaga.ts index d2d85f82d7be..c0177f32f5bd 100644 --- a/app/client/src/git/sagas/initGitSaga.ts +++ b/app/client/src/git/sagas/initGitSaga.ts @@ -2,7 +2,7 @@ import { GitArtifactType } from "git/constants/enums"; import type { InitGitForEditorPayload } from "git/store/actions/initGitActions"; import { gitArtifactActions } from "git/store/gitArtifactSlice"; import type { GitArtifactPayloadAction } from "git/store/types"; -import { put } from "redux-saga/effects"; +import { put, take } from "redux-saga/effects"; export default function* initGitForEditorSaga( action: GitArtifactPayloadAction, @@ -15,8 +15,13 @@ export default function* initGitForEditorSaga( if (artifactType === GitArtifactType.Application) { if (!!artifact.gitApplicationMetadata) { yield put(gitArtifactActions.fetchGitMetadataInit(basePayload)); - // yield take(gitArtifactActions.fetchGitMetadataSuccess.type); - yield put(gitArtifactActions.triggerAutocommitInit(basePayload)); + yield take(gitArtifactActions.fetchGitMetadataSuccess.type); + yield put( + gitArtifactActions.triggerAutocommitInit({ + ...basePayload, + artifactId: artifact.id, + }), + ); yield put(gitArtifactActions.fetchBranchesInit(basePayload)); yield put(gitArtifactActions.fetchProtectedBranchesInit(basePayload)); yield put(gitArtifactActions.fetchStatusInit(basePayload)); diff --git a/app/client/src/git/sagas/triggerAutcommitSaga.ts b/app/client/src/git/sagas/triggerAutcommitSaga.ts new file mode 100644 index 000000000000..a9b2a76334a8 --- /dev/null +++ b/app/client/src/git/sagas/triggerAutcommitSaga.ts @@ -0,0 +1,126 @@ +import { triggerAutocommitSuccessAction } from "actions/gitSyncActions"; +import { AutocommitStatus, type GitArtifactType } from "git/constants/enums"; +import fetchAutocommitProgressRequest from "git/requests/fetchAutocommitProgressRequest"; +import type { + FetchAutocommitProgressResponse, + FetchAutocommitProgressResponseData, +} from "git/requests/fetchAutocommitProgressRequest.types"; +import triggerAutocommitRequest from "git/requests/triggerAutocommitRequest"; +import type { + TriggerAutocommitResponse, + TriggerAutocommitResponseData, +} from "git/requests/triggerAutocommitRequest.types"; +import type { TriggerAutocommitInitPayload } from "git/store/actions/triggerAutocommitActions"; +import { gitArtifactActions } from "git/store/gitArtifactSlice"; +import { selectAutocommitEnabled } from "git/store/selectors/gitSingleArtifactSelectors"; +import type { GitArtifactPayloadAction } from "git/store/types"; +import { + call, + cancel, + delay, + fork, + put, + select, + take, +} from "redux-saga/effects"; +import { validateResponse } from "sagas/ErrorSagas"; + +interface PollAutcommitProgressParams { + artifactType: keyof typeof GitArtifactType; + baseArtifactId: string; + artifactId: string; +} + +function isAutocommitHappening( + responseData: + | TriggerAutocommitResponseData + | FetchAutocommitProgressResponseData + | undefined, +): boolean { + return ( + !!responseData && + (responseData.autoCommitResponse === AutocommitStatus.PUBLISHED || + responseData.autoCommitResponse === AutocommitStatus.IN_PROGRESS || + responseData.autoCommitResponse === AutocommitStatus.LOCKED) + ); +} + +function* pollAutocommitProgressSaga(params: PollAutcommitProgressParams) { + const { artifactId, artifactType, baseArtifactId } = params; + const basePayload = { artifactType, baseArtifactId }; + let triggerResponse: TriggerAutocommitResponse | undefined; + + try { + triggerResponse = yield call(triggerAutocommitRequest, artifactId); + const isValidResponse: boolean = yield validateResponse(triggerResponse); + + if (triggerResponse && isValidResponse) { + yield put(gitArtifactActions.triggerAutocommitSuccess(basePayload)); + } + } catch (error) { + yield put( + gitArtifactActions.triggerAutocommitError({ + ...basePayload, + error: error as string, + }), + ); + } + + try { + if (isAutocommitHappening(triggerResponse?.data)) { + yield put(gitArtifactActions.pollAutocommitProgressStart(basePayload)); + + while (true) { + yield put(gitArtifactActions.fetchAutocommitProgressInit(basePayload)); + const progressResponse: FetchAutocommitProgressResponse = yield call( + fetchAutocommitProgressRequest, + baseArtifactId, + ); + const isValidResponse: boolean = + yield validateResponse(progressResponse); + + if (isValidResponse && !isAutocommitHappening(progressResponse?.data)) { + yield put(gitArtifactActions.pollAutcommitProgressStop(basePayload)); + } + + if (!isValidResponse) { + yield put(gitArtifactActions.pollAutcommitProgressStop(basePayload)); + } + + yield delay(1000); + } + } else { + yield put(gitArtifactActions.pollAutcommitProgressStop(basePayload)); + } + } catch (error) { + yield put(gitArtifactActions.pollAutcommitProgressStop(basePayload)); + yield put( + gitArtifactActions.fetchAutocommitProgressError({ + ...basePayload, + error: error as string, + }), + ); + } +} + +export default function* triggerAutocommitSaga( + action: GitArtifactPayloadAction, +) { + const { artifactId, artifactType, baseArtifactId } = action.payload; + const basePayload = { artifactType, baseArtifactId }; + const isAutocommitEnabled: boolean = yield select( + selectAutocommitEnabled, + basePayload, + ); + + if (isAutocommitEnabled) { + const params = { artifactType, baseArtifactId, artifactId }; + /* @ts-expect-error: not sure how to do typings of this */ + const pollTask = yield fork(pollAutocommitProgressSaga, params); + + yield take(gitArtifactActions.pollAutcommitProgressStop.type); + yield cancel(pollTask); + } else { + yield put(triggerAutocommitSuccessAction()); + } +} diff --git a/app/client/src/git/store/actions/fetchAutocommitProgressActions.ts b/app/client/src/git/store/actions/fetchAutocommitProgressActions.ts index 2736b0c72cc4..a7d92793e4aa 100644 --- a/app/client/src/git/store/actions/fetchAutocommitProgressActions.ts +++ b/app/client/src/git/store/actions/fetchAutocommitProgressActions.ts @@ -1,8 +1,4 @@ -import type { - GitArtifactPayloadAction, - GitArtifactErrorPayloadAction, - GitAutocommitProgress, -} from "../types"; +import type { GitAsyncErrorPayload } from "../types"; import { createSingleArtifactAction } from "../helpers/createSingleArtifactAction"; export const fetchAutocommitProgressInitAction = createSingleArtifactAction( @@ -15,27 +11,19 @@ export const fetchAutocommitProgressInitAction = createSingleArtifactAction( ); export const fetchAutocommitProgressSuccessAction = createSingleArtifactAction( - ( - state, - action: GitArtifactPayloadAction<{ - autocommitProgress: GitAutocommitProgress; - }>, - ) => { + (state) => { state.apiResponses.autocommitProgress.loading = false; - state.apiResponses.autocommitProgress.value = - action.payload.autocommitProgress; return state; }, ); -export const fetchAutocommitProgressErrorAction = createSingleArtifactAction( - (state, action: GitArtifactErrorPayloadAction) => { +export const fetchAutocommitProgressErrorAction = + createSingleArtifactAction((state, action) => { const { error } = action.payload; state.apiResponses.autocommitProgress.loading = false; state.apiResponses.autocommitProgress.error = error; return state; - }, -); + }); diff --git a/app/client/src/git/store/actions/triggerAutocommitActions.ts b/app/client/src/git/store/actions/triggerAutocommitActions.ts index 29ec4667cbe1..32424ac6e9ff 100644 --- a/app/client/src/git/store/actions/triggerAutocommitActions.ts +++ b/app/client/src/git/store/actions/triggerAutocommitActions.ts @@ -1,14 +1,17 @@ import { createSingleArtifactAction } from "../helpers/createSingleArtifactAction"; import type { GitAsyncErrorPayload } from "../types"; -export const triggerAutocommitInitAction = createSingleArtifactAction( - (state) => { +export interface TriggerAutocommitInitPayload { + artifactId: string; +} + +export const triggerAutocommitInitAction = + createSingleArtifactAction((state) => { state.apiResponses.triggerAutocommit.loading = true; state.apiResponses.triggerAutocommit.error = null; return state; - }, -); + }); export const triggerAutocommitSuccessAction = createSingleArtifactAction( (state) => { @@ -27,3 +30,19 @@ export const triggerAutocommitErrorAction = return state; }); + +export const pollAutocommitProgressStartAction = createSingleArtifactAction( + (state) => { + state.ui.autocommitPolling = true; + + return state; + }, +); + +export const pollAutcommitProgressStopAction = createSingleArtifactAction( + (state) => { + state.ui.autocommitPolling = false; + + return state; + }, +); diff --git a/app/client/src/git/store/gitArtifactSlice.ts b/app/client/src/git/store/gitArtifactSlice.ts index 4bbd810a64ab..6abd9700bffd 100644 --- a/app/client/src/git/store/gitArtifactSlice.ts +++ b/app/client/src/git/store/gitArtifactSlice.ts @@ -80,6 +80,8 @@ import { mergeSuccessAction, } from "./actions/mergeActions"; import { + pollAutcommitProgressStopAction, + pollAutocommitProgressStartAction, triggerAutocommitErrorAction, triggerAutocommitInitAction, triggerAutocommitSuccessAction, @@ -99,6 +101,11 @@ import { updateProtectedBranchesInitAction, } from "./actions/updateProtectedBranchesActions"; import { initGitForEditorAction } from "./actions/initGitActions"; +import { + fetchAutocommitProgressErrorAction, + fetchAutocommitProgressInitAction, + fetchAutocommitProgressSuccessAction, +} from "./actions/fetchAutocommitProgressActions"; const initialState: GitArtifactReduxState = {}; @@ -179,6 +186,11 @@ export const gitArtifactSlice = createSlice({ triggerAutocommitInit: triggerAutocommitInitAction, triggerAutocommitSuccess: triggerAutocommitSuccessAction, triggerAutocommitError: triggerAutocommitErrorAction, + fetchAutocommitProgressInit: fetchAutocommitProgressInitAction, + fetchAutocommitProgressSuccess: fetchAutocommitProgressSuccessAction, + fetchAutocommitProgressError: fetchAutocommitProgressErrorAction, + pollAutocommitProgressStart: pollAutocommitProgressStartAction, + pollAutcommitProgressStop: pollAutcommitProgressStopAction, }, }); diff --git a/app/client/src/git/store/helpers/gitSingleArtifactInitialState.ts b/app/client/src/git/store/helpers/gitSingleArtifactInitialState.ts index a194106914a3..589eb44be8de 100644 --- a/app/client/src/git/store/helpers/gitSingleArtifactInitialState.ts +++ b/app/client/src/git/store/helpers/gitSingleArtifactInitialState.ts @@ -33,6 +33,8 @@ const gitSingleArtifactInitialUIState: GitSingleArtifactUIReduxState = { repoLimitErrorModal: { open: false, }, + autocommitModalOpen: false, + autocommitPolling: false, }; const gitSingleArtifactInitialAPIResponses: GitSingleArtifactAPIResponsesReduxState = @@ -112,7 +114,6 @@ const gitSingleArtifactInitialAPIResponses: GitSingleArtifactAPIResponsesReduxSt error: null, }, autocommitProgress: { - value: null, loading: false, error: null, }, diff --git a/app/client/src/git/store/selectors/gitSingleArtifactSelectors.ts b/app/client/src/git/store/selectors/gitSingleArtifactSelectors.ts index e67bcdc99b4a..e2def116db81 100644 --- a/app/client/src/git/store/selectors/gitSingleArtifactSelectors.ts +++ b/app/client/src/git/store/selectors/gitSingleArtifactSelectors.ts @@ -15,6 +15,12 @@ export const selectSingleArtifact = ( ]; }; +// init +export const selectGitMetadata = ( + state: GitRootState, + artifactDef: GitArtifactDef, +) => selectSingleArtifact(state, artifactDef)?.apiResponses.metadata; + // git ops export const selectCommit = ( state: GitRootState, @@ -62,3 +68,11 @@ export const selectCheckoutBranch = ( state: GitRootState, artifactDef: GitArtifactDef, ) => selectSingleArtifact(state, artifactDef)?.apiResponses.checkoutBranch; + +// autocommit +export const selectAutocommitEnabled = ( + state: GitRootState, + artifactDef: GitArtifactDef, +) => + selectSingleArtifact(state, artifactDef)?.apiResponses?.metadata?.value + ?.autoCommitConfig?.enabled; diff --git a/app/client/src/git/store/types.ts b/app/client/src/git/store/types.ts index c941b13e96eb..b464277531e3 100644 --- a/app/client/src/git/store/types.ts +++ b/app/client/src/git/store/types.ts @@ -47,7 +47,7 @@ export interface GitSingleArtifactAPIResponsesReduxState { disconnect: AsyncStateWithoutValue; protectedBranches: AsyncState; updateProtectedBranches: AsyncStateWithoutValue; - autocommitProgress: AsyncState; + autocommitProgress: AsyncStateWithoutValue; toggleAutocommit: AsyncStateWithoutValue; triggerAutocommit: AsyncStateWithoutValue; sshKey: AsyncState; @@ -77,6 +77,8 @@ export interface GitSingleArtifactUIReduxState { repoLimitErrorModal: { open: boolean; }; + autocommitPolling: boolean; + autocommitModalOpen: boolean; } export interface GitSingleArtifactReduxState { ui: GitSingleArtifactUIReduxState; From ca19474c34050d1dfeecdb7e86f10bc87e0ad734 Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Wed, 11 Dec 2024 02:45:12 +0800 Subject: [PATCH 021/143] fix: adding relevant selectors for quick git actions --- .../CtxAwareGitQuickActions/index.tsx | 21 ++++--- .../hooks/useGitBranches.ts | 10 ++-- .../hooks/useGitMetadata.ts | 45 +++++++++++++++ .../GitContextProvider/hooks/useGitOps.ts | 16 +++--- .../hooks/useGitSettings.ts | 51 ++++++++++++++++- .../components/GitContextProvider/index.tsx | 13 ++++- .../GitQuickActions/QuickActionButton.tsx | 10 +--- .../git/components/GitQuickActions/index.tsx | 1 + .../requests/fetchProtectedBranchesRequest.ts | 6 +- .../fetchProtectedBranchesRequest.types.ts | 7 ++- .../src/git/requests/fetchStatusRequest.ts | 4 +- .../git/sagas/fetchProtectedBranchesSaga.ts | 36 ++++++++++++ app/client/src/git/sagas/fetchStatusSaga.ts | 43 ++++++++++++++ app/client/src/git/sagas/index.ts | 57 ++++--------------- .../actions/fetchProtectedBranchesActions.ts | 34 ++++------- app/client/src/git/store/gitArtifactSlice.ts | 2 + .../selectors/gitSingleArtifactSelectors.ts | 46 +++++++++++++-- app/client/src/git/store/types.ts | 7 +-- 18 files changed, 294 insertions(+), 115 deletions(-) create mode 100644 app/client/src/git/components/GitContextProvider/hooks/useGitMetadata.ts create mode 100644 app/client/src/git/sagas/fetchProtectedBranchesSaga.ts create mode 100644 app/client/src/git/sagas/fetchStatusSaga.ts diff --git a/app/client/src/git/components/CtxAwareGitQuickActions/index.tsx b/app/client/src/git/components/CtxAwareGitQuickActions/index.tsx index 9deb2f2d7a55..3830747d85cc 100644 --- a/app/client/src/git/components/CtxAwareGitQuickActions/index.tsx +++ b/app/client/src/git/components/CtxAwareGitQuickActions/index.tsx @@ -5,9 +5,14 @@ import useStatusChangeCount from "./hooks/useStatusChangeCount"; function CtxAwareGitQuickActions() { const { + autocommitEnabled, + autocommitPolling, + connectPermitted, discard, discardLoading, fetchStatusLoading, + gitConnected, + protectedMode, pull, pullError, pullLoading, @@ -17,12 +22,6 @@ function CtxAwareGitQuickActions() { toggleGitSettingsModal, } = useGitContext(); - const isGitConnected = false; - const isAutocommitEnabled = true; - const isAutocommitPolling = false; - const isConnectPermitted = true; - const isProtectedMode = false; - const isPullFailing = !!pullError; const isStatusClean = status?.isClean ?? false; const statusBehindCount = status?.behindCount ?? 0; @@ -31,13 +30,13 @@ function CtxAwareGitQuickActions() { return ( ({ artifactType, baseArtifactId }), + [artifactType, baseArtifactId], + ); + + const gitMetadataState = useSelector((state: GitRootState) => + selectGitMetadata(state, basePayload), + ); + const gitConnected = useSelector((state: GitRootState) => + selectGitConnected(state, basePayload), + ); + + return { + gitMetadata: gitMetadataState.value, + fetchGitMetadataLoading: gitMetadataState.loading ?? false, + fetchGitMetadataError: gitMetadataState.error, + gitConnected: gitConnected ?? false, + }; +} diff --git a/app/client/src/git/components/GitContextProvider/hooks/useGitOps.ts b/app/client/src/git/components/GitContextProvider/hooks/useGitOps.ts index 3c9f3990d6e9..1d0b59f71cd0 100644 --- a/app/client/src/git/components/GitContextProvider/hooks/useGitOps.ts +++ b/app/client/src/git/components/GitContextProvider/hooks/useGitOps.ts @@ -133,24 +133,24 @@ export default function useGitOps({ return { commitLoading: commitState?.loading ?? false, - commitError: commitState?.error ?? null, + commitError: commitState?.error, commit, discardLoading: discardState?.loading ?? false, - discardError: discardState?.error ?? null, + discardError: discardState?.error, discard, - status: statusState?.value ?? null, + status: statusState?.value, fetchStatusLoading: statusState?.loading ?? false, - fetchStatusError: statusState?.error ?? null, + fetchStatusError: statusState?.error, fetchStatus, mergeLoading: mergeState?.loading ?? false, - mergeError: mergeState?.error ?? null, + mergeError: mergeState?.error, merge, - mergeStatus: mergeStatusState?.value ?? null, + mergeStatus: mergeStatusState?.value, fetchMergeStatusLoading: mergeStatusState?.loading ?? false, - fetchMergeStatusError: mergeStatusState?.error ?? null, + fetchMergeStatusError: mergeStatusState?.error, fetchMergeStatus, pullLoading: pullState?.loading ?? false, - pullError: pullState?.error ?? null, + pullError: pullState?.error, pull, toggleGitOpsModal, }; diff --git a/app/client/src/git/components/GitContextProvider/hooks/useGitSettings.ts b/app/client/src/git/components/GitContextProvider/hooks/useGitSettings.ts index 096e934d7d5e..2e63f8e60325 100644 --- a/app/client/src/git/components/GitContextProvider/hooks/useGitSettings.ts +++ b/app/client/src/git/components/GitContextProvider/hooks/useGitSettings.ts @@ -1,7 +1,15 @@ import type { GitArtifactType, GitSettingsTab } from "git/constants/enums"; +import type { FetchProtectedBranchesResponseData } from "git/requests/fetchProtectedBranchesRequest.types"; import { gitArtifactActions } from "git/store/gitArtifactSlice"; +import { + selectAutocommitEnabled, + selectAutocommitPolling, + selectProtectedBranches, + selectProtectedMode, +} from "git/store/selectors/gitSingleArtifactSelectors"; +import type { GitRootState } from "git/store/types"; import { useMemo } from "react"; -import { useDispatch } from "react-redux"; +import { useDispatch, useSelector } from "react-redux"; interface UseGitSettingsParams { artifactType: keyof typeof GitArtifactType; @@ -9,6 +17,13 @@ interface UseGitSettingsParams { } export interface UseGitSettingsReturnValue { + autocommitEnabled: boolean; + autocommitPolling: boolean; + protectedBranches: FetchProtectedBranchesResponseData | null; + fetchProtectedBranchesLoading: boolean; + fetchProtectedBranchesError: string | null; + fetchProtectedBranches: () => void; + protectedMode: boolean; toggleGitSettingsModal: ( open: boolean, tab: keyof typeof GitSettingsTab, @@ -25,6 +40,33 @@ export default function useGitSettings({ [artifactType, baseArtifactId], ); + // autocommit + const autocommitEnabled = useSelector((state: GitRootState) => + selectAutocommitEnabled(state, basePayload), + ); + + const autocommitPolling = useSelector((state: GitRootState) => + selectAutocommitPolling(state, basePayload), + ); + + // branch protection + const protectedBranchesState = useSelector((state: GitRootState) => + selectProtectedBranches(state, basePayload), + ); + + const fetchProtectedBranches = () => { + dispatch( + gitArtifactActions.fetchProtectedBranchesInit({ + ...basePayload, + }), + ); + }; + + const protectedMode = useSelector((state: GitRootState) => + selectProtectedMode(state, basePayload), + ); + + // ui const toggleGitSettingsModal = ( open: boolean, tab: keyof typeof GitSettingsTab, @@ -39,6 +81,13 @@ export default function useGitSettings({ }; return { + autocommitEnabled: autocommitEnabled ?? false, + autocommitPolling: autocommitPolling ?? false, + protectedBranches: protectedBranchesState.value, + fetchProtectedBranchesLoading: protectedBranchesState.loading ?? false, + fetchProtectedBranchesError: protectedBranchesState.error, + fetchProtectedBranches, + protectedMode: protectedMode ?? false, toggleGitSettingsModal, }; } diff --git a/app/client/src/git/components/GitContextProvider/index.tsx b/app/client/src/git/components/GitContextProvider/index.tsx index 28e02104ba33..a5e62626f710 100644 --- a/app/client/src/git/components/GitContextProvider/index.tsx +++ b/app/client/src/git/components/GitContextProvider/index.tsx @@ -8,12 +8,17 @@ import useGitOps from "./hooks/useGitOps"; import useGitConnect from "./hooks/useGitConnect"; import useGitSettings from "./hooks/useGitSettings"; import useGitBranches from "./hooks/useGitBranches"; +import type { UseGitMetadataReturnValue } from "./hooks/useGitMetadata"; +import useGitMetadata from "./hooks/useGitMetadata"; interface GitContextValue extends UseGitConnectReturnValue, + UseGitMetadataReturnValue, UseGitOpsReturnValue, UseGitSettingsReturnValue, - UseGitBranchesReturnValue {} + UseGitBranchesReturnValue { + connectPermitted: boolean; +} const gitContextInitialValue = {} as GitContextValue; @@ -27,17 +32,21 @@ interface GitContextProviderProps { artifactType: keyof typeof GitArtifactType; baseArtifactId: string; children: React.ReactNode; + // extra + connectPermitted?: boolean; } export default function GitContextProvider({ artifactType, baseArtifactId, children, + connectPermitted = true, }: GitContextProviderProps) { const basePayload = useMemo( () => ({ artifactType, baseArtifactId }), [artifactType, baseArtifactId], ); + const useGitMetadataReturnValue = useGitMetadata(basePayload); const useGitConnectReturnValue = useGitConnect(basePayload); const useGitOpsReturnValue = useGitOps(basePayload); const useGitBranchesReturnValue = useGitBranches(basePayload); @@ -45,10 +54,12 @@ export default function GitContextProvider({ // eslint-disable-next-line react-perf/jsx-no-new-object-as-prop const contextValue = { + ...useGitMetadataReturnValue, ...useGitOpsReturnValue, ...useGitBranchesReturnValue, ...useGitConnectReturnValue, ...useGitSettingsReturnValue, + connectPermitted, } as GitContextValue; return ( diff --git a/app/client/src/git/components/GitQuickActions/QuickActionButton.tsx b/app/client/src/git/components/GitQuickActions/QuickActionButton.tsx index c22306b748fa..71c11dbe65ad 100644 --- a/app/client/src/git/components/GitQuickActions/QuickActionButton.tsx +++ b/app/client/src/git/components/GitQuickActions/QuickActionButton.tsx @@ -19,12 +19,11 @@ const SpinnerContainer = styled.div` padding: 0 10px; `; -const QuickActionButtonContainer = styled.button<{ disabled?: boolean }>` +const QuickActionButtonContainer = styled.div<{ disabled?: boolean }>` margin: 0 ${(props) => props.theme.spaces[1]}px; display: block; position: relative; overflow: visible; - cursor: ${({ disabled = false }) => (disabled ? "not-allowed" : "pointer")}; opacity: ${({ disabled = false }) => (disabled ? 0.6 : 1)}; `; @@ -57,11 +56,7 @@ function QuickActionButton({ const content = capitalizeFirstLetter(tooltipText); return ( - + {loading ? ( @@ -73,6 +68,7 @@ function QuickActionButton({ isDisabled={disabled} isIconButton kind="tertiary" + onClick={onClick} size="md" startIcon={icon} /> diff --git a/app/client/src/git/components/GitQuickActions/index.tsx b/app/client/src/git/components/GitQuickActions/index.tsx index e43bf2f0d3d1..f874f781fa64 100644 --- a/app/client/src/git/components/GitQuickActions/index.tsx +++ b/app/client/src/git/components/GitQuickActions/index.tsx @@ -95,6 +95,7 @@ function GitQuickActions({ if (isProtectedMode) { discard(); } else { + // ! case: why is triggeredFromBottomBar this needed? // pull({ triggeredFromBottomBar: true }); pull(); } diff --git a/app/client/src/git/requests/fetchProtectedBranchesRequest.ts b/app/client/src/git/requests/fetchProtectedBranchesRequest.ts index 492a23c5eeca..78f54d9d7140 100644 --- a/app/client/src/git/requests/fetchProtectedBranchesRequest.ts +++ b/app/client/src/git/requests/fetchProtectedBranchesRequest.ts @@ -1,10 +1,10 @@ import Api from "api/Api"; import { GIT_BASE_URL } from "./constants"; -import type { AxiosResponse } from "axios"; -import type { FetchProtectedBranches } from "./fetchProtectedBranchesRequest.types"; +import type { AxiosPromise } from "axios"; +import type { FetchProtectedBranchesResponse } from "./fetchProtectedBranchesRequest.types"; export default async function fetchProtectedBranchesRequest( baseApplicationId: string, -): Promise> { +): AxiosPromise { return Api.get(`${GIT_BASE_URL}/branch/app/${baseApplicationId}/protected`); } diff --git a/app/client/src/git/requests/fetchProtectedBranchesRequest.types.ts b/app/client/src/git/requests/fetchProtectedBranchesRequest.types.ts index 166cc05322ed..eb298bd43407 100644 --- a/app/client/src/git/requests/fetchProtectedBranchesRequest.types.ts +++ b/app/client/src/git/requests/fetchProtectedBranchesRequest.types.ts @@ -1 +1,6 @@ -export type FetchProtectedBranches = string[]; +import type { ApiResponse } from "api/types"; + +export type FetchProtectedBranchesResponseData = string[]; + +export type FetchProtectedBranchesResponse = + ApiResponse; diff --git a/app/client/src/git/requests/fetchStatusRequest.ts b/app/client/src/git/requests/fetchStatusRequest.ts index 4f4b1467e66d..a0a68703f09c 100644 --- a/app/client/src/git/requests/fetchStatusRequest.ts +++ b/app/client/src/git/requests/fetchStatusRequest.ts @@ -4,11 +4,11 @@ import type { FetchStatusResponse, } from "./fetchStatusRequest.types"; import { GIT_BASE_URL } from "./constants"; -import type { AxiosResponse } from "axios"; +import type { AxiosPromise } from "axios"; export default async function fetchStatusRequest( branchedApplicationId: string, params: FetchStatusRequestParams = { compareRemote: true }, -): Promise> { +): AxiosPromise { return Api.get(`${GIT_BASE_URL}/status/app/${branchedApplicationId}`, params); } diff --git a/app/client/src/git/sagas/fetchProtectedBranchesSaga.ts b/app/client/src/git/sagas/fetchProtectedBranchesSaga.ts new file mode 100644 index 000000000000..c0c5d70e7314 --- /dev/null +++ b/app/client/src/git/sagas/fetchProtectedBranchesSaga.ts @@ -0,0 +1,36 @@ +import fetchProtectedBranchesRequest from "git/requests/fetchProtectedBranchesRequest"; +import type { FetchProtectedBranchesResponse } from "git/requests/fetchProtectedBranchesRequest.types"; +import { gitArtifactActions } from "git/store/gitArtifactSlice"; +import type { GitArtifactPayloadAction } from "git/store/types"; +import { call, put } from "redux-saga/effects"; +import { validateResponse } from "sagas/ErrorSagas"; + +export default function* fetchProtectedBranchesSaga( + action: GitArtifactPayloadAction, +) { + const { artifactType, baseArtifactId } = action.payload; + const basePayload = { artifactType, baseArtifactId }; + let response: FetchProtectedBranchesResponse | undefined; + + try { + response = yield call(fetchProtectedBranchesRequest, baseArtifactId); + + const isValidResponse: boolean = yield validateResponse(response); + + if (response && isValidResponse) { + yield put( + gitArtifactActions.fetchProtectedBranchesSuccess({ + ...basePayload, + responseData: response.data, + }), + ); + } + } catch (error) { + yield put( + gitArtifactActions.fetchProtectedBranchesError({ + ...basePayload, + error: error as string, + }), + ); + } +} diff --git a/app/client/src/git/sagas/fetchStatusSaga.ts b/app/client/src/git/sagas/fetchStatusSaga.ts new file mode 100644 index 000000000000..b0bf5d97e4da --- /dev/null +++ b/app/client/src/git/sagas/fetchStatusSaga.ts @@ -0,0 +1,43 @@ +import fetchStatusRequest from "git/requests/fetchStatusRequest"; +import type { FetchStatusResponse } from "git/requests/fetchStatusRequest.types"; +import type { FetchStatusInitPayload } from "git/store/actions/fetchStatusActions"; +import { gitArtifactActions } from "git/store/gitArtifactSlice"; +import type { GitArtifactPayloadAction } from "git/store/types"; +import { call, put } from "redux-saga/effects"; +import { validateResponse } from "sagas/ErrorSagas"; + +export default function* fetchStatusSaga( + action: GitArtifactPayloadAction, +) { + const { artifactType, baseArtifactId } = action.payload; + const basePayload = { artifactType, baseArtifactId }; + let response: FetchStatusResponse | undefined; + + try { + response = yield call(fetchStatusRequest, baseArtifactId); + const isValidResponse: boolean = yield validateResponse(response); + + if (response && isValidResponse) { + yield put( + gitArtifactActions.fetchStatusSuccess({ + ...basePayload, + responseData: response.data, + }), + ); + } + } catch (error) { + yield put( + gitArtifactActions.fetchStatusError({ + ...basePayload, + error: error as string, + }), + ); + + // ! case: BETTER ERROR HANDLING + // if ((error as Error)?.message?.includes("Auth fail")) { + // payload.error = new Error(createMessage(ERROR_GIT_AUTH_FAIL)); + // } else if ((error as Error)?.message?.includes("Invalid remote: origin")) { + // payload.error = new Error(createMessage(ERROR_GIT_INVALID_REMOTE)); + // } + } +} diff --git a/app/client/src/git/sagas/index.ts b/app/client/src/git/sagas/index.ts index 79cd08debbfd..97c05c542a84 100644 --- a/app/client/src/git/sagas/index.ts +++ b/app/client/src/git/sagas/index.ts @@ -1,4 +1,3 @@ -import { gitArtifactActions } from "git/store/gitArtifactSlice"; import { actionChannel, call, @@ -6,9 +5,13 @@ import { take, takeLatest, } from "redux-saga/effects"; +import type { TakeableChannel } from "redux-saga"; +import type { PayloadAction } from "@reduxjs/toolkit"; +import { objectKeys } from "@appsmith/utils"; +import { gitConfigActions } from "../store/gitConfigSlice"; +import { gitArtifactActions } from "../store/gitArtifactSlice"; import connectSaga from "./connectSaga"; import commitSaga from "./commitSaga"; -import { gitConfigActions } from "git/store/gitConfigSlice"; import fetchGlobalProfileSaga from "./fetchGlobalProfileSaga"; import fetchBranchesSaga from "./fetchBranchesSaga"; import fetchLocalProfileSaga from "./fetchLocalProfileSaga"; @@ -17,9 +20,8 @@ import updateGlobalProfileSaga from "./updateGlobalProfileSaga"; import initGitForEditorSaga from "./initGitSaga"; import fetchGitMetadataSaga from "./fetchGitMetadataSaga"; import triggerAutocommitSaga from "./triggerAutcommitSaga"; -import type { TakeableChannel } from "redux-saga"; -import { objectKeys } from "@appsmith/utils"; -import type { PayloadAction } from "@reduxjs/toolkit"; +import fetchStatusSaga from "./fetchStatusSaga"; +import fetchProtectedBranchesSaga from "./fetchProtectedBranchesSaga"; const gitRequestBlockingActions: Record< string, @@ -34,6 +36,7 @@ const gitRequestBlockingActions: Record< // ops [gitArtifactActions.commitInit.type]: commitSaga, + [gitArtifactActions.fetchStatusInit.type]: fetchStatusSaga, // branches [gitArtifactActions.fetchBranchesInit.type]: fetchBranchesSaga, @@ -55,6 +58,10 @@ const gitRequestNonBlockingActions: Record< > = { // init [gitArtifactActions.initGitForEditor.type]: initGitForEditorSaga, + + // settings + [gitArtifactActions.fetchProtectedBranchesInit.type]: + fetchProtectedBranchesSaga, }; /** @@ -90,43 +97,3 @@ export default function* gitSagas() { yield fork(watchGitNonBlockingRequests); yield fork(watchGitBlockingRequests); } - -// export function* gitSagas() { -// yield all([ -// // init -// takeLatest(gitArtifactActions.initGitForEditor.type, initGitForEditorSaga), -// takeLatest( -// gitArtifactActions.fetchGitMetadataInit.type, -// fetchGitMetadataSaga, -// ), - -// takeLatest(gitArtifactActions.connectInit.type, connectSaga), - -// // branches -// takeLatest(gitArtifactActions.fetchBranchesInit.type, fetchBranchesSaga), - -// takeLatest(gitArtifactActions.commitInit.type, commitSaga), -// takeLatest( -// gitArtifactActions.fetchLocalProfileInit.type, -// fetchLocalProfileSaga, -// ), -// takeLatest( -// gitArtifactActions.updateLocalProfileInit.type, -// updateLocalProfileSaga, -// ), -// takeLatest( -// gitConfigActions.fetchGlobalProfileInit.type, -// fetchGlobalProfileSaga, -// ), -// takeLatest( -// gitConfigActions.updateGlobalProfileInit.type, -// updateGlobalProfileSaga, -// ), - -// // autocommit -// takeLatest( -// gitArtifactActions.triggerAutocommitInit.type, -// triggerAutocommitSaga, -// ), -// ]); -// } diff --git a/app/client/src/git/store/actions/fetchProtectedBranchesActions.ts b/app/client/src/git/store/actions/fetchProtectedBranchesActions.ts index 223952a3962b..dc66ff2290c0 100644 --- a/app/client/src/git/store/actions/fetchProtectedBranchesActions.ts +++ b/app/client/src/git/store/actions/fetchProtectedBranchesActions.ts @@ -1,9 +1,6 @@ -import type { - GitArtifactPayloadAction, - GitArtifactErrorPayloadAction, - GitProtectedBranches, -} from "../types"; +import type { GitAsyncSuccessPayload, GitAsyncErrorPayload } from "../types"; import { createSingleArtifactAction } from "../helpers/createSingleArtifactAction"; +import type { FetchProtectedBranchesResponseData } from "git/requests/fetchProtectedBranchesRequest.types"; export const fetchProtectedBranchesInitAction = createSingleArtifactAction( (state) => { @@ -14,28 +11,21 @@ export const fetchProtectedBranchesInitAction = createSingleArtifactAction( }, ); -export const fetchProtectedBranchesSuccessAction = createSingleArtifactAction( - ( - state, - action: GitArtifactPayloadAction<{ - protectedBranches: GitProtectedBranches; - }>, - ) => { - state.apiResponses.protectedBranches.loading = false; - state.apiResponses.protectedBranches.value = - action.payload.protectedBranches; +export const fetchProtectedBranchesSuccessAction = createSingleArtifactAction< + GitAsyncSuccessPayload +>((state, action) => { + state.apiResponses.protectedBranches.loading = false; + state.apiResponses.protectedBranches.value = action.payload.responseData; - return state; - }, -); + return state; +}); -export const fetchProtectedBranchesErrorAction = createSingleArtifactAction( - (state, action: GitArtifactErrorPayloadAction) => { +export const fetchProtectedBranchesErrorAction = + createSingleArtifactAction((state, action) => { const { error } = action.payload; state.apiResponses.protectedBranches.loading = false; state.apiResponses.protectedBranches.error = error; return state; - }, -); + }); diff --git a/app/client/src/git/store/gitArtifactSlice.ts b/app/client/src/git/store/gitArtifactSlice.ts index 6abd9700bffd..df032255e05b 100644 --- a/app/client/src/git/store/gitArtifactSlice.ts +++ b/app/client/src/git/store/gitArtifactSlice.ts @@ -99,6 +99,7 @@ import { import { updateProtectedBranchesErrorAction, updateProtectedBranchesInitAction, + updateProtectedBranchesSuccessAction, } from "./actions/updateProtectedBranchesActions"; import { initGitForEditorAction } from "./actions/initGitActions"; import { @@ -177,6 +178,7 @@ export const gitArtifactSlice = createSlice({ fetchProtectedBranchesSuccess: fetchProtectedBranchesSuccessAction, fetchProtectedBranchesError: fetchProtectedBranchesErrorAction, updateProtectedBranchesInit: updateProtectedBranchesInitAction, + updateProtectedBranchesSuccess: updateProtectedBranchesSuccessAction, updateProtectedBranchesError: updateProtectedBranchesErrorAction, // autocommit diff --git a/app/client/src/git/store/selectors/gitSingleArtifactSelectors.ts b/app/client/src/git/store/selectors/gitSingleArtifactSelectors.ts index e2def116db81..6e36c250d148 100644 --- a/app/client/src/git/store/selectors/gitSingleArtifactSelectors.ts +++ b/app/client/src/git/store/selectors/gitSingleArtifactSelectors.ts @@ -15,12 +15,17 @@ export const selectSingleArtifact = ( ]; }; -// init +// metadata export const selectGitMetadata = ( state: GitRootState, artifactDef: GitArtifactDef, ) => selectSingleArtifact(state, artifactDef)?.apiResponses.metadata; +export const selectGitConnected = ( + state: GitRootState, + artifactDef: GitArtifactDef, +) => !!selectGitMetadata(state, artifactDef).value; + // git ops export const selectCommit = ( state: GitRootState, @@ -49,6 +54,16 @@ export const selectPull = (state: GitRootState, artifactDef: GitArtifactDef) => selectSingleArtifact(state, artifactDef)?.apiResponses?.pull; // git branches + +export const selectCurrentBranch = ( + state: GitRootState, + artifactDef: GitArtifactDef, +) => { + const gitMetadataState = selectGitMetadata(state, artifactDef).value; + + return gitMetadataState?.branchName; +}; + export const selectBranches = ( state: GitRootState, artifactDef: GitArtifactDef, @@ -73,6 +88,29 @@ export const selectCheckoutBranch = ( export const selectAutocommitEnabled = ( state: GitRootState, artifactDef: GitArtifactDef, -) => - selectSingleArtifact(state, artifactDef)?.apiResponses?.metadata?.value - ?.autoCommitConfig?.enabled; +) => { + const gitMetadata = selectGitMetadata(state, artifactDef).value; + + return gitMetadata?.autoCommitConfig?.enabled; +}; + +export const selectAutocommitPolling = ( + state: GitRootState, + artifactDef: GitArtifactDef, +) => selectSingleArtifact(state, artifactDef)?.ui.autocommitPolling; + +// protected branches +export const selectProtectedBranches = ( + state: GitRootState, + artifactDef: GitArtifactDef, +) => selectSingleArtifact(state, artifactDef)?.apiResponses.protectedBranches; + +export const selectProtectedMode = ( + state: GitRootState, + artifactDef: GitArtifactDef, +) => { + const currentBranch = selectCurrentBranch(state, artifactDef); + const protectedBranches = selectProtectedBranches(state, artifactDef).value; + + return protectedBranches?.includes(currentBranch ?? ""); +}; diff --git a/app/client/src/git/store/types.ts b/app/client/src/git/store/types.ts index b464277531e3..b3a8c18fc02a 100644 --- a/app/client/src/git/store/types.ts +++ b/app/client/src/git/store/types.ts @@ -12,10 +12,7 @@ import type { FetchLocalProfileResponseData } from "../requests/fetchLocalProfil import type { FetchStatusResponseData } from "git/requests/fetchStatusRequest.types"; import type { FetchMergeStatusResponseData } from "git/requests/fetchMergeStatusRequest.types"; import type { FetchGitMetadataResponseData } from "git/requests/fetchGitMetadataRequest.types"; - -export type GitProtectedBranches = Record; - -export type GitAutocommitProgress = Record; +import type { FetchProtectedBranchesResponseData } from "git/requests/fetchProtectedBranchesRequest.types"; export type GitSSHKey = Record; @@ -45,7 +42,7 @@ export interface GitSingleArtifactAPIResponsesReduxState { localProfile: AsyncState; updateLocalProfile: AsyncStateWithoutValue; disconnect: AsyncStateWithoutValue; - protectedBranches: AsyncState; + protectedBranches: AsyncState; updateProtectedBranches: AsyncStateWithoutValue; autocommitProgress: AsyncStateWithoutValue; toggleAutocommit: AsyncStateWithoutValue; From 59f91f428e1c9acce33a9acb32bc987a33f68baf Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Wed, 11 Dec 2024 14:41:53 +0800 Subject: [PATCH 022/143] fix: resolving conflict errors --- app/client/src/git/store/actions/repoLimitErrorModalActions.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/client/src/git/store/actions/repoLimitErrorModalActions.ts b/app/client/src/git/store/actions/repoLimitErrorModalActions.ts index 96061395e854..d79b29d61d15 100644 --- a/app/client/src/git/store/actions/repoLimitErrorModalActions.ts +++ b/app/client/src/git/store/actions/repoLimitErrorModalActions.ts @@ -1,4 +1,4 @@ -import { createSingleArtifactAction } from "./helpers/createSingleArtifactAction"; +import { createSingleArtifactAction } from "../helpers/createSingleArtifactAction"; interface ToggleRepoLimitModalActionPayload { open: boolean; From e1eb35a6c4efab61735ccc55837bdbf5bb26ccfa Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Wed, 11 Dec 2024 15:16:22 +0800 Subject: [PATCH 023/143] fix: review changes --- .../hooks/useGitContextValue.ts | 42 +++++++++++++++++++ .../components/GitContextProvider/index.tsx | 37 +++------------- .../GitQuickActions/BranchButton/index.tsx | 10 +++-- 3 files changed, 54 insertions(+), 35 deletions(-) create mode 100644 app/client/src/git/components/GitContextProvider/hooks/useGitContextValue.ts diff --git a/app/client/src/git/components/GitContextProvider/hooks/useGitContextValue.ts b/app/client/src/git/components/GitContextProvider/hooks/useGitContextValue.ts new file mode 100644 index 000000000000..36f1b2a988f2 --- /dev/null +++ b/app/client/src/git/components/GitContextProvider/hooks/useGitContextValue.ts @@ -0,0 +1,42 @@ +import type { GitArtifactType } from "git/constants/enums"; +import type { UseGitConnectReturnValue } from "./useGitConnect"; +import type { UseGitOpsReturnValue } from "./useGitOps"; +import type { UseGitSettingsReturnValue } from "./useGitSettings"; +import type { UseGitBranchesReturnValue } from "./useGitBranches"; +import useGitConnect from "./useGitConnect"; +import useGitOps from "./useGitOps"; +import useGitBranches from "./useGitBranches"; +import useGitSettings from "./useGitSettings"; +import { useMemo } from "react"; + +interface UseGitContextValueParams { + artifactType: keyof typeof GitArtifactType; + baseArtifactId: string; +} + +export interface GitContextValue + extends UseGitConnectReturnValue, + UseGitOpsReturnValue, + UseGitSettingsReturnValue, + UseGitBranchesReturnValue {} + +export default function useGitContextValue({ + artifactType, + baseArtifactId, +}: UseGitContextValueParams): GitContextValue { + const basePayload = useMemo( + () => ({ artifactType, baseArtifactId }), + [artifactType, baseArtifactId], + ); + const useGitConnectReturnValue = useGitConnect(basePayload); + const useGitOpsReturnValue = useGitOps(basePayload); + const useGitBranchesReturnValue = useGitBranches(basePayload); + const useGitSettingsReturnValue = useGitSettings(basePayload); + + return { + ...useGitOpsReturnValue, + ...useGitBranchesReturnValue, + ...useGitConnectReturnValue, + ...useGitSettingsReturnValue, + }; +} diff --git a/app/client/src/git/components/GitContextProvider/index.tsx b/app/client/src/git/components/GitContextProvider/index.tsx index d093e0f5e709..2d057c30670b 100644 --- a/app/client/src/git/components/GitContextProvider/index.tsx +++ b/app/client/src/git/components/GitContextProvider/index.tsx @@ -1,19 +1,7 @@ -import React, { createContext, useContext, useEffect, useMemo } from "react"; +import React, { createContext, useContext, useEffect } from "react"; import type { GitArtifactType } from "git/constants/enums"; -import type { UseGitOpsReturnValue } from "./hooks/useGitOps"; -import type { UseGitSettingsReturnValue } from "./hooks/useGitSettings"; -import type { UseGitBranchesReturnValue } from "./hooks/useGitBranches"; -import type { UseGitConnectReturnValue } from "./hooks/useGitConnect"; -import useGitOps from "./hooks/useGitOps"; -import useGitConnect from "./hooks/useGitConnect"; -import useGitSettings from "./hooks/useGitSettings"; -import useGitBranches from "./hooks/useGitBranches"; - -interface GitContextValue - extends UseGitConnectReturnValue, - UseGitOpsReturnValue, - UseGitSettingsReturnValue, - UseGitBranchesReturnValue {} +import type { GitContextValue } from "./hooks/useGitContextValue"; +import useGitContextValue from "./hooks/useGitContextValue"; const gitContextInitialValue = {} as GitContextValue; @@ -34,16 +22,9 @@ export default function GitContextProvider({ baseArtifactId, children, }: GitContextProviderProps) { - const basePayload = useMemo( - () => ({ artifactType, baseArtifactId }), - [artifactType, baseArtifactId], - ); - const useGitConnectReturnValue = useGitConnect(basePayload); - const useGitOpsReturnValue = useGitOps(basePayload); - const useGitBranchesReturnValue = useGitBranches(basePayload); - const useGitSettingsReturnValue = useGitSettings(basePayload); + const contextValue = useGitContextValue({ artifactType, baseArtifactId }); - const { fetchBranches } = useGitBranchesReturnValue; + const { fetchBranches } = contextValue; useEffect( function gitInitEffect() { @@ -52,14 +33,6 @@ export default function GitContextProvider({ [fetchBranches], ); - // eslint-disable-next-line react-perf/jsx-no-new-object-as-prop - const contextValue = { - ...useGitOpsReturnValue, - ...useGitBranchesReturnValue, - ...useGitConnectReturnValue, - ...useGitSettingsReturnValue, - } as GitContextValue; - return ( {children} ); diff --git a/app/client/src/git/components/GitQuickActions/BranchButton/index.tsx b/app/client/src/git/components/GitQuickActions/BranchButton/index.tsx index 88a694402db6..d73cba35e40e 100644 --- a/app/client/src/git/components/GitQuickActions/BranchButton/index.tsx +++ b/app/client/src/git/components/GitQuickActions/BranchButton/index.tsx @@ -1,5 +1,5 @@ import { Button, Icon, Tooltip } from "@appsmith/ads"; -import React, { useCallback } from "react"; +import React, { useCallback, useEffect, useState } from "react"; import styled from "styled-components"; import noop from "lodash/noop"; import BranchList from "./BranchList"; @@ -53,6 +53,7 @@ export default function BranchButton({ isStatusClean = false, setIsOpen = noop, }: BranchButtonProps) { + const [isEllipsis, setIsEllipsis] = useState(false); const labelTarget = React.useRef(null); const onPopoverInteraction = useCallback( @@ -68,6 +69,10 @@ export default function BranchButton({ [setIsOpen], ); + useEffect(function ellipsisCheck() { + setIsEllipsis(isEllipsisActive(labelTarget.current) ?? false); + }, []); + const renderContent = useCallback(() => { return ; }, []); @@ -86,8 +91,7 @@ export default function BranchButton({ > Date: Wed, 11 Dec 2024 16:13:14 +0800 Subject: [PATCH 024/143] fix: fixing test cases --- .../components/GitQuickActions/index.test.tsx | 26 ++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/app/client/src/git/components/GitQuickActions/index.test.tsx b/app/client/src/git/components/GitQuickActions/index.test.tsx index 72138f9b9b38..4e04554ec92c 100644 --- a/app/client/src/git/components/GitQuickActions/index.test.tsx +++ b/app/client/src/git/components/GitQuickActions/index.test.tsx @@ -110,8 +110,8 @@ describe("QuickActions Component", () => { , ); - const commitButton = container.getElementsByClassName( - "t--bottom-bar-commit", + const commitButton = container.querySelectorAll( + ".t--bottom-bar-commit button", )[0]; fireEvent.click(commitButton); @@ -145,8 +145,9 @@ describe("QuickActions Component", () => { , ); - const pullButton = - container.getElementsByClassName("t--bottom-bar-pull")[0]; + const pullButton = container.querySelectorAll( + ".t--bottom-bar-pull button", + )[0]; fireEvent.click(pullButton); expect(AnalyticsUtil.logEvent).toHaveBeenCalledWith("GS_PULL_GIT_CLICK", { @@ -165,8 +166,8 @@ describe("QuickActions Component", () => { , ); - const mergeButton = container.getElementsByClassName( - "t--bottom-bar-merge", + const mergeButton = container.querySelectorAll( + ".t--bottom-bar-merge button", )[0]; fireEvent.click(mergeButton); @@ -190,8 +191,8 @@ describe("QuickActions Component", () => { , ); - const settingsButton = container.getElementsByClassName( - "t--bottom-git-settings", + const settingsButton = container.querySelectorAll( + ".t--bottom-git-settings button", )[0]; fireEvent.click(settingsButton); @@ -216,8 +217,8 @@ describe("QuickActions Component", () => { , ); - const commitButton = container.getElementsByClassName( - "t--bottom-bar-commit", + const commitButton = container.querySelectorAll( + ".t--bottom-bar-commit button", )[0]; expect(commitButton).toBeDisabled(); @@ -298,8 +299,9 @@ describe("QuickActions Component", () => { , ); - const pullButton = - container.getElementsByClassName("t--bottom-bar-pull")[0]; + const pullButton = container.querySelectorAll( + ".t--bottom-bar-pull button", + )[0]; expect(pullButton).toBeDisabled(); }); From 56cbaef07c05665735bcb0fafb85975e24cc42eb Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Wed, 11 Dec 2024 16:15:01 +0800 Subject: [PATCH 025/143] fix: fixing more test cases --- .../git/components/GitQuickActions/QuickActionButton.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/client/src/git/components/GitQuickActions/QuickActionButton.test.tsx b/app/client/src/git/components/GitQuickActions/QuickActionButton.test.tsx index 6bd94a586f56..037db38a04d2 100644 --- a/app/client/src/git/components/GitQuickActions/QuickActionButton.test.tsx +++ b/app/client/src/git/components/GitQuickActions/QuickActionButton.test.tsx @@ -50,7 +50,7 @@ describe("QuickActionButton", () => { , ); - const btn = container.getElementsByClassName("t--test-btn")[0]; + const btn = container.querySelectorAll(".t--test-btn button")[0]; fireEvent.click(btn); expect(defaultProps.onClick).toHaveBeenCalledTimes(1); From f8545b45736941a4671fed8491ea36a96c830e47 Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Wed, 11 Dec 2024 16:22:15 +0800 Subject: [PATCH 026/143] fix: changing AxiosResponse to AxiosPromise --- app/client/src/git/requests/checkoutBranchRequest.ts | 4 ++-- app/client/src/git/requests/commitRequest.ts | 4 ++-- app/client/src/git/requests/createBranchRequest.ts | 4 ++-- app/client/src/git/requests/deleteBranchRequest.ts | 4 ++-- app/client/src/git/requests/discardRequest.ts | 4 ++-- app/client/src/git/requests/disconnectRequest.ts | 4 ++-- app/client/src/git/requests/fetchMergeStatusRequest.ts | 4 ++-- app/client/src/git/requests/fetchSSHKeyRequest.ts | 4 ++-- app/client/src/git/requests/generateSSHKeyRequest.ts | 4 ++-- app/client/src/git/requests/importGitRequest.ts | 4 ++-- app/client/src/git/requests/mergeRequest.ts | 4 ++-- app/client/src/git/requests/pullRequest.ts | 4 ++-- app/client/src/git/requests/toggleAutocommitRequest.ts | 4 ++-- app/client/src/git/requests/updateGlobalProfileRequest.ts | 4 ++-- app/client/src/git/requests/updateProtectedBranchesRequest.ts | 4 ++-- 15 files changed, 30 insertions(+), 30 deletions(-) diff --git a/app/client/src/git/requests/checkoutBranchRequest.ts b/app/client/src/git/requests/checkoutBranchRequest.ts index 4df5da6112d3..e0c2f7e990ac 100644 --- a/app/client/src/git/requests/checkoutBranchRequest.ts +++ b/app/client/src/git/requests/checkoutBranchRequest.ts @@ -1,4 +1,4 @@ -import type { AxiosResponse } from "axios"; +import type { AxiosPromise } from "axios"; import type { CheckoutBranchRequestParams, CheckoutBranchResponse, @@ -9,7 +9,7 @@ import Api from "api/Api"; export default async function checkoutBranchRequest( branchedApplicationId: string, params: CheckoutBranchRequestParams, -): Promise> { +): AxiosPromise { return Api.get( `${GIT_BASE_URL}/checkout-branch/app/${branchedApplicationId}`, params, diff --git a/app/client/src/git/requests/commitRequest.ts b/app/client/src/git/requests/commitRequest.ts index 69541d030368..2cbd8aff65a6 100644 --- a/app/client/src/git/requests/commitRequest.ts +++ b/app/client/src/git/requests/commitRequest.ts @@ -4,12 +4,12 @@ import type { CommitResponse, } from "./commitRequest.types"; import { GIT_BASE_URL } from "./constants"; -import type { AxiosResponse } from "axios"; +import type { AxiosPromise } from "axios"; export default async function commitRequest( branchedApplicationId: string, params: CommitRequestParams, -): Promise> { +): AxiosPromise { return Api.post( `${GIT_BASE_URL}/commit/app/${branchedApplicationId}`, params, diff --git a/app/client/src/git/requests/createBranchRequest.ts b/app/client/src/git/requests/createBranchRequest.ts index a67b5ee04099..9445ad2c3a55 100644 --- a/app/client/src/git/requests/createBranchRequest.ts +++ b/app/client/src/git/requests/createBranchRequest.ts @@ -1,4 +1,4 @@ -import type { AxiosResponse } from "axios"; +import type { AxiosPromise } from "axios"; import type { CreateBranchRequestParams, CreateBranchResponse, @@ -9,7 +9,7 @@ import Api from "api/Api"; export default async function createBranchRequest( branchedApplicationId: string, params: CreateBranchRequestParams, -): Promise> { +): AxiosPromise { return Api.post( `${GIT_BASE_URL}/create-branch/app/${branchedApplicationId}`, params, diff --git a/app/client/src/git/requests/deleteBranchRequest.ts b/app/client/src/git/requests/deleteBranchRequest.ts index 63f718506d48..cba2463d2019 100644 --- a/app/client/src/git/requests/deleteBranchRequest.ts +++ b/app/client/src/git/requests/deleteBranchRequest.ts @@ -1,4 +1,4 @@ -import type { AxiosResponse } from "axios"; +import type { AxiosPromise } from "axios"; import type { DeleteBranchRequestParams, DeleteBranchResponse, @@ -9,6 +9,6 @@ import Api from "api/Api"; export default async function deleteBranchRequest( baseApplicationId: string, params: DeleteBranchRequestParams, -): Promise> { +): AxiosPromise { return Api.delete(`${GIT_BASE_URL}/branch/app/${baseApplicationId}`, params); } diff --git a/app/client/src/git/requests/discardRequest.ts b/app/client/src/git/requests/discardRequest.ts index fda452fc206c..6dffe7513caf 100644 --- a/app/client/src/git/requests/discardRequest.ts +++ b/app/client/src/git/requests/discardRequest.ts @@ -1,9 +1,9 @@ import Api from "api/Api"; import { GIT_BASE_URL } from "./constants"; -import type { AxiosResponse } from "axios"; +import type { AxiosPromise } from "axios"; export default async function discardRequest( branchedApplicationId: string, -): Promise> { +): AxiosPromise { return Api.put(`${GIT_BASE_URL}/discard/app/${branchedApplicationId}`); } diff --git a/app/client/src/git/requests/disconnectRequest.ts b/app/client/src/git/requests/disconnectRequest.ts index 9ec9b3a4e2b9..93c16be07baa 100644 --- a/app/client/src/git/requests/disconnectRequest.ts +++ b/app/client/src/git/requests/disconnectRequest.ts @@ -1,10 +1,10 @@ -import type { AxiosResponse } from "axios"; +import type { AxiosPromise } from "axios"; import { GIT_BASE_URL } from "./constants"; import type { DisconnectResponse } from "./disconnectRequest.types"; import Api from "api/Api"; export default async function disconnectRequest( baseApplicationId: string, -): Promise> { +): AxiosPromise { return Api.post(`${GIT_BASE_URL}/disconnect/app/${baseApplicationId}`); } diff --git a/app/client/src/git/requests/fetchMergeStatusRequest.ts b/app/client/src/git/requests/fetchMergeStatusRequest.ts index 95701d5cadc8..402ac66de587 100644 --- a/app/client/src/git/requests/fetchMergeStatusRequest.ts +++ b/app/client/src/git/requests/fetchMergeStatusRequest.ts @@ -1,4 +1,4 @@ -import type { AxiosResponse } from "axios"; +import type { AxiosPromise } from "axios"; import type { FetchMergeStatusRequestParams, FetchMergeStatusResponse, @@ -9,7 +9,7 @@ import { GIT_BASE_URL } from "./constants"; export default async function fetchMergeStatusRequest( branchedApplicationId: string, params: FetchMergeStatusRequestParams, -): Promise> { +): AxiosPromise { return Api.post( `${GIT_BASE_URL}/merge/status/app/${branchedApplicationId}`, params, diff --git a/app/client/src/git/requests/fetchSSHKeyRequest.ts b/app/client/src/git/requests/fetchSSHKeyRequest.ts index e61884e28a3b..29c295dc6d02 100644 --- a/app/client/src/git/requests/fetchSSHKeyRequest.ts +++ b/app/client/src/git/requests/fetchSSHKeyRequest.ts @@ -1,10 +1,10 @@ -import type { AxiosResponse } from "axios"; +import type { AxiosPromise } from "axios"; import type { FetchSSHKeyResponse } from "./fetchSSHKeyRequest.types"; import Api from "api/Api"; import { APPLICATION_BASE_URL } from "./constants"; export default async function fetchSSHKeyRequest( baseApplicationId: string, -): Promise> { +): AxiosPromise { return Api.get(`${APPLICATION_BASE_URL}/ssh-keypair/${baseApplicationId}`); } diff --git a/app/client/src/git/requests/generateSSHKeyRequest.ts b/app/client/src/git/requests/generateSSHKeyRequest.ts index 525c0423a16f..7c747f94371e 100644 --- a/app/client/src/git/requests/generateSSHKeyRequest.ts +++ b/app/client/src/git/requests/generateSSHKeyRequest.ts @@ -1,4 +1,4 @@ -import type { AxiosResponse } from "axios"; +import type { AxiosPromise } from "axios"; import type { GenerateSSHKeyRequestParams, GenerateSSHKeyResponse, @@ -9,7 +9,7 @@ import Api from "api/Api"; export default async function generateSSHKeyRequest( baseApplicationId: string, params: GenerateSSHKeyRequestParams, -): Promise> { +): AxiosPromise { const url = params.isImporting ? `${GIT_BASE_URL}/import/keys?keyType=${params.keyType}` : `${APPLICATION_BASE_URL}/ssh-keypair/${baseApplicationId}?keyType=${params.keyType}`; diff --git a/app/client/src/git/requests/importGitRequest.ts b/app/client/src/git/requests/importGitRequest.ts index e9378361da88..522cd187ebe3 100644 --- a/app/client/src/git/requests/importGitRequest.ts +++ b/app/client/src/git/requests/importGitRequest.ts @@ -4,11 +4,11 @@ import type { ImportGitRequestParams, ImportGitResponse, } from "./importGitRequest.types"; -import type { AxiosResponse } from "axios"; +import type { AxiosPromise } from "axios"; export default async function importGitRequest( workspaceId: string, params: ImportGitRequestParams, -): Promise> { +): AxiosPromise { return Api.post(`${GIT_BASE_URL}/import/${workspaceId}`, params); } diff --git a/app/client/src/git/requests/mergeRequest.ts b/app/client/src/git/requests/mergeRequest.ts index ee30566c4936..daee44fad21d 100644 --- a/app/client/src/git/requests/mergeRequest.ts +++ b/app/client/src/git/requests/mergeRequest.ts @@ -1,11 +1,11 @@ import Api from "api/Api"; import type { MergeRequestParams, MergeResponse } from "./mergeRequest.types"; import { GIT_BASE_URL } from "./constants"; -import type { AxiosResponse } from "axios"; +import type { AxiosPromise } from "axios"; export default async function mergeRequest( branchedApplicationId: string, params: MergeRequestParams, -): Promise> { +): AxiosPromise { return Api.post(`${GIT_BASE_URL}/merge/app/${branchedApplicationId}`, params); } diff --git a/app/client/src/git/requests/pullRequest.ts b/app/client/src/git/requests/pullRequest.ts index 21bd6f4f2a3c..18870918c0cd 100644 --- a/app/client/src/git/requests/pullRequest.ts +++ b/app/client/src/git/requests/pullRequest.ts @@ -1,10 +1,10 @@ import Api from "api/Api"; import { GIT_BASE_URL } from "./constants"; -import type { AxiosResponse } from "axios"; +import type { AxiosPromise } from "axios"; import type { PullRequestResponse } from "./pullRequest.types"; export default async function pullRequest( branchedApplicationId: string, -): Promise> { +): AxiosPromise { return Api.get(`${GIT_BASE_URL}/pull/app/${branchedApplicationId}`); } diff --git a/app/client/src/git/requests/toggleAutocommitRequest.ts b/app/client/src/git/requests/toggleAutocommitRequest.ts index deba662ded3f..85131550f108 100644 --- a/app/client/src/git/requests/toggleAutocommitRequest.ts +++ b/app/client/src/git/requests/toggleAutocommitRequest.ts @@ -1,11 +1,11 @@ import Api from "api/Api"; import { GIT_BASE_URL } from "./constants"; -import type { AxiosResponse } from "axios"; +import type { AxiosPromise } from "axios"; import type { ToggleAutocommitResponse } from "./toggleAutocommitRequest.types"; export default async function toggleAutocommitRequest( baseApplicationId: string, -): Promise> { +): AxiosPromise { return Api.patch( `${GIT_BASE_URL}/auto-commit/toggle/app/${baseApplicationId}`, ); diff --git a/app/client/src/git/requests/updateGlobalProfileRequest.ts b/app/client/src/git/requests/updateGlobalProfileRequest.ts index 647ff15426f7..62d11a931a70 100644 --- a/app/client/src/git/requests/updateGlobalProfileRequest.ts +++ b/app/client/src/git/requests/updateGlobalProfileRequest.ts @@ -1,4 +1,4 @@ -import type { AxiosResponse } from "axios"; +import type { AxiosPromise } from "axios"; import type { UpdateGlobalProfileRequestParams, UpdateGlobalProfileResponse, @@ -8,6 +8,6 @@ import { GIT_BASE_URL } from "./constants"; export default async function updateGlobalProfileRequest( params: UpdateGlobalProfileRequestParams, -): Promise> { +): AxiosPromise { return Api.post(`${GIT_BASE_URL}/profile/default`, params); } diff --git a/app/client/src/git/requests/updateProtectedBranchesRequest.ts b/app/client/src/git/requests/updateProtectedBranchesRequest.ts index 5af603ecaa7d..aa3822c1b5e2 100644 --- a/app/client/src/git/requests/updateProtectedBranchesRequest.ts +++ b/app/client/src/git/requests/updateProtectedBranchesRequest.ts @@ -4,12 +4,12 @@ import type { UpdateProtectedBranchesRequestParams, UpdateProtectedBranchesResponse, } from "./updateProtectedBranchesRequest.types"; -import type { AxiosResponse } from "axios"; +import type { AxiosPromise } from "axios"; export default async function updateProtectedBranchesRequest( baseApplicationId: string, params: UpdateProtectedBranchesRequestParams, -): Promise> { +): AxiosPromise { return Api.post( `${GIT_BASE_URL}/branch/app/${baseApplicationId}/protected`, params, From 65e9ea6610c68546d3c6cac6d2e987703792bd00 Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Wed, 11 Dec 2024 16:34:56 +0800 Subject: [PATCH 027/143] fix: fixing build and naming issues --- .../components/CtxAwareGitQuickActions/index.tsx | 2 +- .../GitContextProvider/hooks/useGitContextValue.ts | 7 ++++++- app/client/src/git/sagas/index.ts | 2 +- ...erAutcommitSaga.ts => triggerAutocommitSaga.ts} | 14 +++++++------- .../git/store/actions/triggerAutocommitActions.ts | 2 +- app/client/src/git/store/gitArtifactSlice.ts | 4 ++-- 6 files changed, 18 insertions(+), 13 deletions(-) rename app/client/src/git/sagas/{triggerAutcommitSaga.ts => triggerAutocommitSaga.ts} (88%) diff --git a/app/client/src/git/components/CtxAwareGitQuickActions/index.tsx b/app/client/src/git/components/CtxAwareGitQuickActions/index.tsx index 3830747d85cc..824350f3b195 100644 --- a/app/client/src/git/components/CtxAwareGitQuickActions/index.tsx +++ b/app/client/src/git/components/CtxAwareGitQuickActions/index.tsx @@ -7,7 +7,6 @@ function CtxAwareGitQuickActions() { const { autocommitEnabled, autocommitPolling, - connectPermitted, discard, discardLoading, fetchStatusLoading, @@ -22,6 +21,7 @@ function CtxAwareGitQuickActions() { toggleGitSettingsModal, } = useGitContext(); + const connectPermitted = true; const isPullFailing = !!pullError; const isStatusClean = status?.isClean ?? false; const statusBehindCount = status?.behindCount ?? 0; diff --git a/app/client/src/git/components/GitContextProvider/hooks/useGitContextValue.ts b/app/client/src/git/components/GitContextProvider/hooks/useGitContextValue.ts index 36f1b2a988f2..0945eea223f0 100644 --- a/app/client/src/git/components/GitContextProvider/hooks/useGitContextValue.ts +++ b/app/client/src/git/components/GitContextProvider/hooks/useGitContextValue.ts @@ -8,6 +8,8 @@ import useGitOps from "./useGitOps"; import useGitBranches from "./useGitBranches"; import useGitSettings from "./useGitSettings"; import { useMemo } from "react"; +import type { UseGitMetadataReturnValue } from "./useGitMetadata"; +import useGitMetadata from "./useGitMetadata"; interface UseGitContextValueParams { artifactType: keyof typeof GitArtifactType; @@ -15,7 +17,8 @@ interface UseGitContextValueParams { } export interface GitContextValue - extends UseGitConnectReturnValue, + extends UseGitMetadataReturnValue, + UseGitConnectReturnValue, UseGitOpsReturnValue, UseGitSettingsReturnValue, UseGitBranchesReturnValue {} @@ -28,12 +31,14 @@ export default function useGitContextValue({ () => ({ artifactType, baseArtifactId }), [artifactType, baseArtifactId], ); + const useGitMetadataReturnValue = useGitMetadata(basePayload); const useGitConnectReturnValue = useGitConnect(basePayload); const useGitOpsReturnValue = useGitOps(basePayload); const useGitBranchesReturnValue = useGitBranches(basePayload); const useGitSettingsReturnValue = useGitSettings(basePayload); return { + ...useGitMetadataReturnValue, ...useGitOpsReturnValue, ...useGitBranchesReturnValue, ...useGitConnectReturnValue, diff --git a/app/client/src/git/sagas/index.ts b/app/client/src/git/sagas/index.ts index 97c05c542a84..60108c4d068b 100644 --- a/app/client/src/git/sagas/index.ts +++ b/app/client/src/git/sagas/index.ts @@ -19,7 +19,7 @@ import updateLocalProfileSaga from "./updateLocalProfileSaga"; import updateGlobalProfileSaga from "./updateGlobalProfileSaga"; import initGitForEditorSaga from "./initGitSaga"; import fetchGitMetadataSaga from "./fetchGitMetadataSaga"; -import triggerAutocommitSaga from "./triggerAutcommitSaga"; +import triggerAutocommitSaga from "./triggerAutocommitSaga"; import fetchStatusSaga from "./fetchStatusSaga"; import fetchProtectedBranchesSaga from "./fetchProtectedBranchesSaga"; diff --git a/app/client/src/git/sagas/triggerAutcommitSaga.ts b/app/client/src/git/sagas/triggerAutocommitSaga.ts similarity index 88% rename from app/client/src/git/sagas/triggerAutcommitSaga.ts rename to app/client/src/git/sagas/triggerAutocommitSaga.ts index a9b2a76334a8..80eab189beba 100644 --- a/app/client/src/git/sagas/triggerAutcommitSaga.ts +++ b/app/client/src/git/sagas/triggerAutocommitSaga.ts @@ -25,7 +25,7 @@ import { } from "redux-saga/effects"; import { validateResponse } from "sagas/ErrorSagas"; -interface PollAutcommitProgressParams { +interface PollAutocommitProgressParams { artifactType: keyof typeof GitArtifactType; baseArtifactId: string; artifactId: string; @@ -45,7 +45,7 @@ function isAutocommitHappening( ); } -function* pollAutocommitProgressSaga(params: PollAutcommitProgressParams) { +function* pollAutocommitProgressSaga(params: PollAutocommitProgressParams) { const { artifactId, artifactType, baseArtifactId } = params; const basePayload = { artifactType, baseArtifactId }; let triggerResponse: TriggerAutocommitResponse | undefined; @@ -80,20 +80,20 @@ function* pollAutocommitProgressSaga(params: PollAutcommitProgressParams) { yield validateResponse(progressResponse); if (isValidResponse && !isAutocommitHappening(progressResponse?.data)) { - yield put(gitArtifactActions.pollAutcommitProgressStop(basePayload)); + yield put(gitArtifactActions.pollAutocommitProgressStop(basePayload)); } if (!isValidResponse) { - yield put(gitArtifactActions.pollAutcommitProgressStop(basePayload)); + yield put(gitArtifactActions.pollAutocommitProgressStop(basePayload)); } yield delay(1000); } } else { - yield put(gitArtifactActions.pollAutcommitProgressStop(basePayload)); + yield put(gitArtifactActions.pollAutocommitProgressStop(basePayload)); } } catch (error) { - yield put(gitArtifactActions.pollAutcommitProgressStop(basePayload)); + yield put(gitArtifactActions.pollAutocommitProgressStop(basePayload)); yield put( gitArtifactActions.fetchAutocommitProgressError({ ...basePayload, @@ -118,7 +118,7 @@ export default function* triggerAutocommitSaga( /* @ts-expect-error: not sure how to do typings of this */ const pollTask = yield fork(pollAutocommitProgressSaga, params); - yield take(gitArtifactActions.pollAutcommitProgressStop.type); + yield take(gitArtifactActions.pollAutocommitProgressStop.type); yield cancel(pollTask); } else { yield put(triggerAutocommitSuccessAction()); diff --git a/app/client/src/git/store/actions/triggerAutocommitActions.ts b/app/client/src/git/store/actions/triggerAutocommitActions.ts index 32424ac6e9ff..28e88ecd2f16 100644 --- a/app/client/src/git/store/actions/triggerAutocommitActions.ts +++ b/app/client/src/git/store/actions/triggerAutocommitActions.ts @@ -39,7 +39,7 @@ export const pollAutocommitProgressStartAction = createSingleArtifactAction( }, ); -export const pollAutcommitProgressStopAction = createSingleArtifactAction( +export const pollAutocommitProgressStopAction = createSingleArtifactAction( (state) => { state.ui.autocommitPolling = false; diff --git a/app/client/src/git/store/gitArtifactSlice.ts b/app/client/src/git/store/gitArtifactSlice.ts index df032255e05b..425b6421d403 100644 --- a/app/client/src/git/store/gitArtifactSlice.ts +++ b/app/client/src/git/store/gitArtifactSlice.ts @@ -80,7 +80,7 @@ import { mergeSuccessAction, } from "./actions/mergeActions"; import { - pollAutcommitProgressStopAction, + pollAutocommitProgressStopAction, pollAutocommitProgressStartAction, triggerAutocommitErrorAction, triggerAutocommitInitAction, @@ -192,7 +192,7 @@ export const gitArtifactSlice = createSlice({ fetchAutocommitProgressSuccess: fetchAutocommitProgressSuccessAction, fetchAutocommitProgressError: fetchAutocommitProgressErrorAction, pollAutocommitProgressStart: pollAutocommitProgressStartAction, - pollAutcommitProgressStop: pollAutcommitProgressStopAction, + pollAutocommitProgressStop: pollAutocommitProgressStopAction, }, }); From f613ae1265ee49b3a1ff62cd3a541db1c7446faa Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Wed, 11 Dec 2024 16:59:28 +0800 Subject: [PATCH 028/143] fix: remove expect error --- app/client/src/git/sagas/triggerAutocommitSaga.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/client/src/git/sagas/triggerAutocommitSaga.ts b/app/client/src/git/sagas/triggerAutocommitSaga.ts index 80eab189beba..fb4c6185406b 100644 --- a/app/client/src/git/sagas/triggerAutocommitSaga.ts +++ b/app/client/src/git/sagas/triggerAutocommitSaga.ts @@ -23,6 +23,7 @@ import { select, take, } from "redux-saga/effects"; +import type { Task } from "redux-saga"; import { validateResponse } from "sagas/ErrorSagas"; interface PollAutocommitProgressParams { @@ -115,8 +116,7 @@ export default function* triggerAutocommitSaga( if (isAutocommitEnabled) { const params = { artifactType, baseArtifactId, artifactId }; - /* @ts-expect-error: not sure how to do typings of this */ - const pollTask = yield fork(pollAutocommitProgressSaga, params); + const pollTask: Task = yield fork(pollAutocommitProgressSaga, params); yield take(gitArtifactActions.pollAutocommitProgressStop.type); yield cancel(pollTask); From adddd089b9729ad740f63021c95db643497ff8b1 Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Wed, 11 Dec 2024 18:37:09 +0800 Subject: [PATCH 029/143] chore: adding git ops modal --- .../components/CtxAwareGitOpsModal/index.tsx | 25 +++++ .../CtxAwareGitQuickActions/index.tsx | 12 +-- .../hooks/useGitBranches.ts | 8 +- .../GitContextProvider/hooks/useGitConnect.ts | 8 +- .../GitContextProvider/hooks/useGitOps.ts | 24 ++++- .../hooks/useGitSettings.ts | 8 +- app/client/src/git/components/GitModals.tsx | 6 ++ .../GitOpsModal/TabDeploy/index.tsx | 5 + .../components/GitOpsModal/TabMerge/index.tsx | 5 + .../src/git/components/GitOpsModal/index.tsx | 97 +++++++++++++++++++ .../components/GitQuickActions/index.test.tsx | 15 ++- .../git/components/GitQuickActions/index.tsx | 28 +++--- .../src/git/sagas/checkoutBranchSaga.ts | 2 +- app/client/src/git/store/actions/uiActions.ts | 24 ++--- app/client/src/git/store/gitArtifactSlice.ts | 16 +-- .../helpers/gitSingleArtifactInitialState.ts | 6 +- .../selectors/gitSingleArtifactSelectors.ts | 10 ++ app/client/src/git/store/types.ts | 6 +- 18 files changed, 230 insertions(+), 75 deletions(-) create mode 100644 app/client/src/git/components/CtxAwareGitOpsModal/index.tsx create mode 100644 app/client/src/git/components/GitModals.tsx create mode 100644 app/client/src/git/components/GitOpsModal/TabDeploy/index.tsx create mode 100644 app/client/src/git/components/GitOpsModal/TabMerge/index.tsx create mode 100644 app/client/src/git/components/GitOpsModal/index.tsx diff --git a/app/client/src/git/components/CtxAwareGitOpsModal/index.tsx b/app/client/src/git/components/CtxAwareGitOpsModal/index.tsx new file mode 100644 index 000000000000..b45cb1553646 --- /dev/null +++ b/app/client/src/git/components/CtxAwareGitOpsModal/index.tsx @@ -0,0 +1,25 @@ +import React from "react"; +import GitOpsModal from "../GitOpsModal"; +import { useGitContext } from "../GitContextProvider"; + +export default function CtxAwareGitOpsModal() { + const { + gitMetadata, + opsModalOpen, + opsModalTab, + protectedMode, + toggleOpsModal, + } = useGitContext(); + + const repoName = gitMetadata?.repoName ?? null; + + return ( + + ); +} diff --git a/app/client/src/git/components/CtxAwareGitQuickActions/index.tsx b/app/client/src/git/components/CtxAwareGitQuickActions/index.tsx index 824350f3b195..0a58fce1fed6 100644 --- a/app/client/src/git/components/CtxAwareGitQuickActions/index.tsx +++ b/app/client/src/git/components/CtxAwareGitQuickActions/index.tsx @@ -16,9 +16,9 @@ function CtxAwareGitQuickActions() { pullError, pullLoading, status, - toggleGitConnectModal, - toggleGitOpsModal, - toggleGitSettingsModal, + toggleConnectModal, + toggleOpsModal, + toggleSettingsModal, } = useGitContext(); const connectPermitted = true; @@ -43,9 +43,9 @@ function CtxAwareGitQuickActions() { pull={pull} statusBehindCount={statusBehindCount} statusChangeCount={statusChangeCount} - toggleGitConnectModal={toggleGitConnectModal} - toggleGitOpsModal={toggleGitOpsModal} - toggleGitSettingsModal={toggleGitSettingsModal} + toggleConnectModal={toggleConnectModal} + toggleOpsModal={toggleOpsModal} + toggleSettingsModal={toggleSettingsModal} /> ); } diff --git a/app/client/src/git/components/GitContextProvider/hooks/useGitBranches.ts b/app/client/src/git/components/GitContextProvider/hooks/useGitBranches.ts index 4d23f042f795..bc670004b7c3 100644 --- a/app/client/src/git/components/GitContextProvider/hooks/useGitBranches.ts +++ b/app/client/src/git/components/GitContextProvider/hooks/useGitBranches.ts @@ -30,7 +30,7 @@ export interface UseGitBranchesReturnValue { checkoutBranchLoading: boolean; checkoutBranchError: string | null; checkoutBranch: (branchName: string) => void; - toggleGitBranchListPopup: (open: boolean) => void; + toggleBranchListPopup: (open: boolean) => void; } export default function useGitBranches({ @@ -103,9 +103,9 @@ export default function useGitBranches({ ); // git branch list popup - const toggleGitBranchListPopup = (open: boolean) => { + const toggleBranchListPopup = (open: boolean) => { dispatch( - gitArtifactActions.toggleGitBranchListPopup({ + gitArtifactActions.toggleBranchListPopup({ ...basePayload, open, }), @@ -126,6 +126,6 @@ export default function useGitBranches({ checkoutBranchLoading: checkoutBranchState?.loading ?? false, checkoutBranchError: checkoutBranchState?.error, checkoutBranch, - toggleGitBranchListPopup, + toggleBranchListPopup, }; } diff --git a/app/client/src/git/components/GitContextProvider/hooks/useGitConnect.ts b/app/client/src/git/components/GitContextProvider/hooks/useGitConnect.ts index 900f1716c8c5..9741a857e7a3 100644 --- a/app/client/src/git/components/GitContextProvider/hooks/useGitConnect.ts +++ b/app/client/src/git/components/GitContextProvider/hooks/useGitConnect.ts @@ -9,7 +9,7 @@ interface UseGitConnectParams { } export interface UseGitConnectReturnValue { - toggleGitConnectModal: (open: boolean) => void; + toggleConnectModal: (open: boolean) => void; } export default function useGitConnect({ @@ -22,9 +22,9 @@ export default function useGitConnect({ [artifactType, baseArtifactId], ); - const toggleGitConnectModal = (open: boolean) => { + const toggleConnectModal = (open: boolean) => { dispatch( - gitArtifactActions.toggleGitConnectModal({ + gitArtifactActions.toggleConnectModal({ ...basePayload, open, }), @@ -32,6 +32,6 @@ export default function useGitConnect({ }; return { - toggleGitConnectModal, + toggleConnectModal, }; } diff --git a/app/client/src/git/components/GitContextProvider/hooks/useGitOps.ts b/app/client/src/git/components/GitContextProvider/hooks/useGitOps.ts index 1d0b59f71cd0..503c45072f70 100644 --- a/app/client/src/git/components/GitContextProvider/hooks/useGitOps.ts +++ b/app/client/src/git/components/GitContextProvider/hooks/useGitOps.ts @@ -7,6 +7,8 @@ import { selectDiscard, selectMerge, selectMergeStatus, + selectOpsModalOpen, + selectOpsModalTab, selectPull, selectStatus, } from "git/store/selectors/gitSingleArtifactSelectors"; @@ -40,7 +42,9 @@ export interface UseGitOpsReturnValue { pullLoading: boolean; pullError: string | null; pull: () => void; - toggleGitOpsModal: (open: boolean, tab?: keyof typeof GitOpsTab) => void; + opsModalTab: keyof typeof GitOpsTab; + opsModalOpen: boolean; + toggleOpsModal: (open: boolean, tab?: keyof typeof GitOpsTab) => void; } export default function useGitOps({ @@ -121,11 +125,19 @@ export default function useGitOps({ dispatch(gitArtifactActions.pullInit(basePayload)); }, [basePayload, dispatch]); - // git ops modal - const toggleGitOpsModal = useCallback( + // ops modal + const opsModalOpen = useSelector((state: GitRootState) => + selectOpsModalOpen(state, basePayload), + ); + + const opsModalTab = useSelector((state: GitRootState) => + selectOpsModalTab(state, basePayload), + ); + + const toggleOpsModal = useCallback( (open: boolean, tab: keyof typeof GitOpsTab = GitOpsTab.Deploy) => { dispatch( - gitArtifactActions.toggleGitOpsModal({ ...basePayload, open, tab }), + gitArtifactActions.toggleOpsModal({ ...basePayload, open, tab }), ); }, [basePayload, dispatch], @@ -152,6 +164,8 @@ export default function useGitOps({ pullLoading: pullState?.loading ?? false, pullError: pullState?.error, pull, - toggleGitOpsModal, + opsModalTab, + opsModalOpen, + toggleOpsModal, }; } diff --git a/app/client/src/git/components/GitContextProvider/hooks/useGitSettings.ts b/app/client/src/git/components/GitContextProvider/hooks/useGitSettings.ts index 2e63f8e60325..54f1699f253c 100644 --- a/app/client/src/git/components/GitContextProvider/hooks/useGitSettings.ts +++ b/app/client/src/git/components/GitContextProvider/hooks/useGitSettings.ts @@ -24,7 +24,7 @@ export interface UseGitSettingsReturnValue { fetchProtectedBranchesError: string | null; fetchProtectedBranches: () => void; protectedMode: boolean; - toggleGitSettingsModal: ( + toggleSettingsModal: ( open: boolean, tab: keyof typeof GitSettingsTab, ) => void; @@ -67,12 +67,12 @@ export default function useGitSettings({ ); // ui - const toggleGitSettingsModal = ( + const toggleSettingsModal = ( open: boolean, tab: keyof typeof GitSettingsTab, ) => { dispatch( - gitArtifactActions.toggleGitSettingsModal({ + gitArtifactActions.toggleSettingsModal({ ...basePayload, open, tab, @@ -88,6 +88,6 @@ export default function useGitSettings({ fetchProtectedBranchesError: protectedBranchesState.error, fetchProtectedBranches, protectedMode: protectedMode ?? false, - toggleGitSettingsModal, + toggleSettingsModal, }; } diff --git a/app/client/src/git/components/GitModals.tsx b/app/client/src/git/components/GitModals.tsx new file mode 100644 index 000000000000..556c8d2fa4bd --- /dev/null +++ b/app/client/src/git/components/GitModals.tsx @@ -0,0 +1,6 @@ +import React from "react"; +import CtxAwareGitOpsModal from "./CtxAwareGitOpsModal"; + +export default function GitModal() { + return ; +} diff --git a/app/client/src/git/components/GitOpsModal/TabDeploy/index.tsx b/app/client/src/git/components/GitOpsModal/TabDeploy/index.tsx new file mode 100644 index 000000000000..b83625c1a443 --- /dev/null +++ b/app/client/src/git/components/GitOpsModal/TabDeploy/index.tsx @@ -0,0 +1,5 @@ +import React from "react"; + +export default function TabDeploy() { + return
Test
; +} diff --git a/app/client/src/git/components/GitOpsModal/TabMerge/index.tsx b/app/client/src/git/components/GitOpsModal/TabMerge/index.tsx new file mode 100644 index 000000000000..c22f248bf400 --- /dev/null +++ b/app/client/src/git/components/GitOpsModal/TabMerge/index.tsx @@ -0,0 +1,5 @@ +import React from "react"; + +export default function TabMerge() { + return
Test
; +} diff --git a/app/client/src/git/components/GitOpsModal/index.tsx b/app/client/src/git/components/GitOpsModal/index.tsx new file mode 100644 index 000000000000..aa69d606d5e9 --- /dev/null +++ b/app/client/src/git/components/GitOpsModal/index.tsx @@ -0,0 +1,97 @@ +import React, { useCallback } from "react"; +import TabDeploy from "./TabDeploy"; +import TabMerge from "./TabMerge"; + +// import GitErrorPopup from "../components/GitErrorPopup"; + +import { createMessage, DEPLOY, MERGE } from "ee/constants/messages"; +import AnalyticsUtil from "ee/utils/AnalyticsUtil"; +import { + Modal, + ModalContent, + ModalHeader, + Tab, + Tabs, + TabsList, +} from "@appsmith/ads"; +import styled from "styled-components"; +// import ReconnectSSHError from "../components/ReconnectSSHError"; +import { GitOpsTab } from "git/constants/enums"; +import noop from "lodash/noop"; + +const StyledModalContent = styled(ModalContent)` + &&& { + width: 640px; + transform: none !important; + top: 100px; + left: calc(50% - 320px); + max-height: calc(100vh - 200px); + } +`; + +interface GitOpsModalProps { + isOpsModalOpen: boolean; + isProtectedMode: boolean; + opsModalTab: keyof typeof GitOpsTab; + repoName: string | null; + toggleOpsModal: (open: boolean, tab?: keyof typeof GitOpsTab) => void; +} + +function GitOpsModal({ + isOpsModalOpen = false, + isProtectedMode = false, + opsModalTab = GitOpsTab.Deploy, + repoName = null, + toggleOpsModal = noop, +}: GitOpsModalProps) { + const handleTabKeyChange = useCallback( + (tabKey: string) => { + if (tabKey === GitOpsTab.Deploy) { + AnalyticsUtil.logEvent("GS_DEPLOY_GIT_MODAL_TRIGGERED", { + source: `${tabKey.toUpperCase()}_TAB`, + }); + } else if (tabKey === GitOpsTab.Merge) { + AnalyticsUtil.logEvent("GS_MERGE_GIT_MODAL_TRIGGERED", { + source: `${tabKey.toUpperCase()}_TAB`, + }); + } + + toggleOpsModal(true, tabKey as GitOpsTab); + }, + [toggleOpsModal], + ); + + return ( + <> + + + {repoName} + {/* {isGitConnected && } */} + + + + {createMessage(DEPLOY)} + + + {createMessage(MERGE)} + + + + {opsModalTab === GitOpsTab.Deploy && } + {opsModalTab === GitOpsTab.Merge && } + + + {/* */} + + ); +} + +export default GitOpsModal; diff --git a/app/client/src/git/components/GitQuickActions/index.test.tsx b/app/client/src/git/components/GitQuickActions/index.test.tsx index 4e04554ec92c..ce4b943a5d1e 100644 --- a/app/client/src/git/components/GitQuickActions/index.test.tsx +++ b/app/client/src/git/components/GitQuickActions/index.test.tsx @@ -35,9 +35,9 @@ describe("QuickActions Component", () => { pull: jest.fn(), statusBehindCount: 0, statusChangeCount: 0, - toggleGitConnectModal: jest.fn(), - toggleGitOpsModal: jest.fn(), - toggleGitSettingsModal: jest.fn(), + toggleConnectModal: jest.fn(), + toggleOpsModal: jest.fn(), + toggleSettingsModal: jest.fn(), }; afterEach(() => { @@ -115,10 +115,7 @@ describe("QuickActions Component", () => { )[0]; fireEvent.click(commitButton); - expect(props.toggleGitOpsModal).toHaveBeenCalledWith( - true, - GitOpsTab.Deploy, - ); + expect(props.toggleOpsModal).toHaveBeenCalledWith(true, GitOpsTab.Deploy); expect(AnalyticsUtil.logEvent).toHaveBeenCalledWith( "GS_DEPLOY_GIT_MODAL_TRIGGERED", { @@ -177,7 +174,7 @@ describe("QuickActions Component", () => { source: "BOTTOM_BAR_GIT_MERGE_BUTTON", }, ); - expect(props.toggleGitOpsModal).toHaveBeenCalledWith(true, GitOpsTab.Merge); + expect(props.toggleOpsModal).toHaveBeenCalledWith(true, GitOpsTab.Merge); }); it("should call onSettingsClick when settings button is clicked", () => { @@ -199,7 +196,7 @@ describe("QuickActions Component", () => { expect(AnalyticsUtil.logEvent).toHaveBeenCalledWith("GS_SETTING_CLICK", { source: "BOTTOM_BAR_GIT_SETTING_BUTTON", }); - expect(props.toggleGitSettingsModal).toHaveBeenCalledWith( + expect(props.toggleSettingsModal).toHaveBeenCalledWith( true, GitSettingsTab.General, ); diff --git a/app/client/src/git/components/GitQuickActions/index.tsx b/app/client/src/git/components/GitQuickActions/index.tsx index f874f781fa64..e7b1e1b72411 100644 --- a/app/client/src/git/components/GitQuickActions/index.tsx +++ b/app/client/src/git/components/GitQuickActions/index.tsx @@ -38,9 +38,9 @@ interface GitQuickActionsProps { pull: () => void; statusBehindCount: number; statusChangeCount: number; - toggleGitConnectModal: (open: boolean) => void; - toggleGitOpsModal: (open: boolean, tab: keyof typeof GitOpsTab) => void; - toggleGitSettingsModal: ( + toggleConnectModal: (open: boolean) => void; + toggleOpsModal: (open: boolean, tab: keyof typeof GitOpsTab) => void; + toggleSettingsModal: ( open: boolean, tab: keyof typeof GitSettingsTab, ) => void; @@ -61,9 +61,9 @@ function GitQuickActions({ pull = noop, statusBehindCount = 0, statusChangeCount = 0, - toggleGitConnectModal = noop, - toggleGitOpsModal = noop, - toggleGitSettingsModal = noop, + toggleConnectModal = noop, + toggleOpsModal = noop, + toggleSettingsModal = noop, }: GitQuickActionsProps) { const { isDisabled: isPullDisabled, message: pullTooltipMessage } = getPullBtnStatus({ @@ -78,13 +78,13 @@ function GitQuickActions({ const onCommitBtnClick = useCallback(() => { if (!isFetchStatusLoading && !isProtectedMode) { - toggleGitOpsModal(true, GitOpsTab.Deploy); + toggleOpsModal(true, GitOpsTab.Deploy); AnalyticsUtil.logEvent("GS_DEPLOY_GIT_MODAL_TRIGGERED", { source: "BOTTOM_BAR_GIT_COMMIT_BUTTON", }); } - }, [isFetchStatusLoading, isProtectedMode, toggleGitOpsModal]); + }, [isFetchStatusLoading, isProtectedMode, toggleOpsModal]); const onPullBtnClick = useCallback(() => { if (!isPullButtonLoading && !isPullDisabled) { @@ -106,23 +106,23 @@ function GitQuickActions({ AnalyticsUtil.logEvent("GS_MERGE_GIT_MODAL_TRIGGERED", { source: "BOTTOM_BAR_GIT_MERGE_BUTTON", }); - toggleGitOpsModal(true, GitOpsTab.Merge); - }, [toggleGitOpsModal]); + toggleOpsModal(true, GitOpsTab.Merge); + }, [toggleOpsModal]); const onSettingsClick = useCallback(() => { - toggleGitSettingsModal(true, GitSettingsTab.General); + toggleSettingsModal(true, GitSettingsTab.General); AnalyticsUtil.logEvent("GS_SETTING_CLICK", { source: "BOTTOM_BAR_GIT_SETTING_BUTTON", }); - }, [toggleGitSettingsModal]); + }, [toggleSettingsModal]); const onConnectBtnClick = useCallback(() => { AnalyticsUtil.logEvent("GS_CONNECT_GIT_CLICK", { source: "BOTTOM_BAR_GIT_CONNECT_BUTTON", }); - toggleGitConnectModal(true); - }, [toggleGitConnectModal]); + toggleConnectModal(true); + }, [toggleConnectModal]); return isGitConnected ? ( diff --git a/app/client/src/git/sagas/checkoutBranchSaga.ts b/app/client/src/git/sagas/checkoutBranchSaga.ts index 506ecae653d3..bacb2a283c38 100644 --- a/app/client/src/git/sagas/checkoutBranchSaga.ts +++ b/app/client/src/git/sagas/checkoutBranchSaga.ts @@ -46,7 +46,7 @@ export default function* checkoutBranchSaga( ); yield put( - gitArtifactActions.toggleGitBranchListPopup({ + gitArtifactActions.toggleBranchListPopup({ ...basePayload, open: false, }), diff --git a/app/client/src/git/store/actions/uiActions.ts b/app/client/src/git/store/actions/uiActions.ts index fe77a5684e51..9f0659770998 100644 --- a/app/client/src/git/store/actions/uiActions.ts +++ b/app/client/src/git/store/actions/uiActions.ts @@ -18,7 +18,7 @@ interface BranchListPopupPayload { open: boolean; } -export const toggleGitBranchListPopupAction = +export const toggleBranchListPopupAction = createSingleArtifactAction((state, action) => { const { open } = action.payload; @@ -27,28 +27,28 @@ export const toggleGitBranchListPopupAction = return state; }); -export interface ToggleGitOpsModalPayload { +export interface ToggleOpsModalPayload { open: boolean; tab: keyof typeof GitOpsTab; } -export const toggleGitOpsModalAction = - createSingleArtifactAction((state, action) => { +export const toggleOpsModalAction = + createSingleArtifactAction((state, action) => { const { open, tab } = action.payload; - state.ui.opsModal.open = open; - state.ui.opsModal.tab = tab; + state.ui.opsModalOpen = open; + state.ui.opsModalTab = tab; return state; }); -export interface ToggleGitSettingsModalPayload { +export interface ToggleSettingsModalPayload { open: boolean; tab: keyof typeof GitSettingsTab; } -export const toggleGitSettingsModalAction = - createSingleArtifactAction((state, action) => { +export const toggleSettingsModalAction = + createSingleArtifactAction((state, action) => { const { open, tab } = action.payload; state.ui.settingsModal.open = open; @@ -57,12 +57,12 @@ export const toggleGitSettingsModalAction = return state; }); -export interface ToggleGitConnectModalPayload { +export interface ToggleConnectModalPayload { open: boolean; } -export const toggleGitConnectModalAction = - createSingleArtifactAction((state, action) => { +export const toggleConnectModalAction = + createSingleArtifactAction((state, action) => { const { open } = action.payload; state.ui.connectModal.open = open; diff --git a/app/client/src/git/store/gitArtifactSlice.ts b/app/client/src/git/store/gitArtifactSlice.ts index 425b6421d403..a1bb0f5c56e2 100644 --- a/app/client/src/git/store/gitArtifactSlice.ts +++ b/app/client/src/git/store/gitArtifactSlice.ts @@ -53,10 +53,10 @@ import { deleteBranchSuccessAction, } from "./actions/deleteBranchActions"; import { - toggleGitBranchListPopupAction, - toggleGitConnectModalAction, - toggleGitOpsModalAction, - toggleGitSettingsModalAction, + toggleBranchListPopupAction, + toggleConnectModalAction, + toggleOpsModalAction, + toggleSettingsModalAction, toggleRepoLimitErrorModalAction, } from "./actions/uiActions"; import { @@ -127,7 +127,7 @@ export const gitArtifactSlice = createSlice({ connectInit: connectInitAction, connectSuccess: connectSuccessAction, connectError: connectErrorAction, - toggleGitConnectModal: toggleGitConnectModalAction, + toggleConnectModal: toggleConnectModalAction, toggleRepoLimitErrorModal: toggleRepoLimitErrorModalAction, // git ops @@ -149,7 +149,7 @@ export const gitArtifactSlice = createSlice({ pullInit: pullInitAction, pullSuccess: pullSuccessAction, pullError: pullErrorAction, - toggleGitOpsModal: toggleGitOpsModalAction, + toggleOpsModal: toggleOpsModalAction, // branches fetchBranchesInit: fetchBranchesInitAction, @@ -164,10 +164,10 @@ export const gitArtifactSlice = createSlice({ checkoutBranchInit: checkoutBranchInitAction, checkoutBranchSuccess: checkoutBranchSuccessAction, checkoutBranchError: checkoutBranchErrorAction, - toggleGitBranchListPopup: toggleGitBranchListPopupAction, + toggleBranchListPopup: toggleBranchListPopupAction, // settings - toggleGitSettingsModal: toggleGitSettingsModalAction, + toggleSettingsModal: toggleSettingsModalAction, fetchLocalProfileInit: fetchLocalProfileInitAction, fetchLocalProfileSuccess: fetchLocalProfileSuccessAction, fetchLocalProfileError: fetchLocalProfileErrorAction, diff --git a/app/client/src/git/store/helpers/gitSingleArtifactInitialState.ts b/app/client/src/git/store/helpers/gitSingleArtifactInitialState.ts index 589eb44be8de..4d3366ea662f 100644 --- a/app/client/src/git/store/helpers/gitSingleArtifactInitialState.ts +++ b/app/client/src/git/store/helpers/gitSingleArtifactInitialState.ts @@ -22,10 +22,8 @@ const gitSingleArtifactInitialUIState: GitSingleArtifactUIReduxState = { branchListPopup: { open: false, }, - opsModal: { - open: false, - tab: GitOpsTab.Deploy, - }, + opsModalOpen: false, + opsModalTab: GitOpsTab.Deploy, settingsModal: { open: false, tab: GitSettingsTab.General, diff --git a/app/client/src/git/store/selectors/gitSingleArtifactSelectors.ts b/app/client/src/git/store/selectors/gitSingleArtifactSelectors.ts index 6e36c250d148..3bfbfbce3e9f 100644 --- a/app/client/src/git/store/selectors/gitSingleArtifactSelectors.ts +++ b/app/client/src/git/store/selectors/gitSingleArtifactSelectors.ts @@ -27,6 +27,16 @@ export const selectGitConnected = ( ) => !!selectGitMetadata(state, artifactDef).value; // git ops +export const selectOpsModalOpen = ( + state: GitRootState, + artifactDef: GitArtifactDef, +) => selectSingleArtifact(state, artifactDef)?.ui.opsModalOpen; + +export const selectOpsModalTab = ( + state: GitRootState, + artifactDef: GitArtifactDef, +) => selectSingleArtifact(state, artifactDef)?.ui.opsModalTab; + export const selectCommit = ( state: GitRootState, artifactDef: GitArtifactDef, diff --git a/app/client/src/git/store/types.ts b/app/client/src/git/store/types.ts index b3a8c18fc02a..94481f1b2c72 100644 --- a/app/client/src/git/store/types.ts +++ b/app/client/src/git/store/types.ts @@ -63,10 +63,8 @@ export interface GitSingleArtifactUIReduxState { branchListPopup: { open: boolean; }; - opsModal: { - open: boolean; - tab: keyof typeof GitOpsTab; - }; + opsModalOpen: boolean; + opsModalTab: keyof typeof GitOpsTab; settingsModal: { open: boolean; tab: keyof typeof GitSettingsTab; From c6343d3a60ef21fb2100a242a9230fa26f99638b Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Wed, 11 Dec 2024 19:04:29 +0800 Subject: [PATCH 030/143] fix: arranging dumb components in a better fashion --- .../components/CtxAwareGitOpsModal/index.tsx | 25 -- .../CtxAwareGitQuickActions/index.tsx | 53 ----- app/client/src/git/components/GitModals.tsx | 6 +- .../GitOpsModal/DumbGitOpsModal.tsx | 97 ++++++++ .../src/git/components/GitOpsModal/index.tsx | 110 ++------- ....test.tsx => DumbGitQuickActions.test.tsx} | 30 +-- .../GitQuickActions/DumbGitQuickActions.tsx | 180 ++++++++++++++ .../hooks/useStatusChangeCount.ts | 0 .../git/components/GitQuickActions/index.tsx | 223 ++++-------------- 9 files changed, 362 insertions(+), 362 deletions(-) delete mode 100644 app/client/src/git/components/CtxAwareGitOpsModal/index.tsx delete mode 100644 app/client/src/git/components/CtxAwareGitQuickActions/index.tsx create mode 100644 app/client/src/git/components/GitOpsModal/DumbGitOpsModal.tsx rename app/client/src/git/components/GitQuickActions/{index.test.tsx => DumbGitQuickActions.test.tsx} (92%) create mode 100644 app/client/src/git/components/GitQuickActions/DumbGitQuickActions.tsx rename app/client/src/git/components/{CtxAwareGitQuickActions => GitQuickActions}/hooks/useStatusChangeCount.ts (100%) diff --git a/app/client/src/git/components/CtxAwareGitOpsModal/index.tsx b/app/client/src/git/components/CtxAwareGitOpsModal/index.tsx deleted file mode 100644 index b45cb1553646..000000000000 --- a/app/client/src/git/components/CtxAwareGitOpsModal/index.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import React from "react"; -import GitOpsModal from "../GitOpsModal"; -import { useGitContext } from "../GitContextProvider"; - -export default function CtxAwareGitOpsModal() { - const { - gitMetadata, - opsModalOpen, - opsModalTab, - protectedMode, - toggleOpsModal, - } = useGitContext(); - - const repoName = gitMetadata?.repoName ?? null; - - return ( - - ); -} diff --git a/app/client/src/git/components/CtxAwareGitQuickActions/index.tsx b/app/client/src/git/components/CtxAwareGitQuickActions/index.tsx deleted file mode 100644 index 0a58fce1fed6..000000000000 --- a/app/client/src/git/components/CtxAwareGitQuickActions/index.tsx +++ /dev/null @@ -1,53 +0,0 @@ -import React from "react"; -import GitQuickActions from "../GitQuickActions"; -import { useGitContext } from "../GitContextProvider"; -import useStatusChangeCount from "./hooks/useStatusChangeCount"; - -function CtxAwareGitQuickActions() { - const { - autocommitEnabled, - autocommitPolling, - discard, - discardLoading, - fetchStatusLoading, - gitConnected, - protectedMode, - pull, - pullError, - pullLoading, - status, - toggleConnectModal, - toggleOpsModal, - toggleSettingsModal, - } = useGitContext(); - - const connectPermitted = true; - const isPullFailing = !!pullError; - const isStatusClean = status?.isClean ?? false; - const statusBehindCount = status?.behindCount ?? 0; - const statusChangeCount = useStatusChangeCount(status); - - return ( - - ); -} - -export default CtxAwareGitQuickActions; diff --git a/app/client/src/git/components/GitModals.tsx b/app/client/src/git/components/GitModals.tsx index 556c8d2fa4bd..5f7bbc18e6f9 100644 --- a/app/client/src/git/components/GitModals.tsx +++ b/app/client/src/git/components/GitModals.tsx @@ -1,6 +1,6 @@ import React from "react"; -import CtxAwareGitOpsModal from "./CtxAwareGitOpsModal"; +import GitOpsModal from "./GitOpsModal"; -export default function GitModal() { - return ; +export default function GitModals() { + return ; } diff --git a/app/client/src/git/components/GitOpsModal/DumbGitOpsModal.tsx b/app/client/src/git/components/GitOpsModal/DumbGitOpsModal.tsx new file mode 100644 index 000000000000..b1e1fc835073 --- /dev/null +++ b/app/client/src/git/components/GitOpsModal/DumbGitOpsModal.tsx @@ -0,0 +1,97 @@ +import React, { useCallback } from "react"; +import TabDeploy from "./TabDeploy"; +import TabMerge from "./TabMerge"; + +// import GitErrorPopup from "../components/GitErrorPopup"; + +import { createMessage, DEPLOY, MERGE } from "ee/constants/messages"; +import AnalyticsUtil from "ee/utils/AnalyticsUtil"; +import { + Modal, + ModalContent, + ModalHeader, + Tab, + Tabs, + TabsList, +} from "@appsmith/ads"; +import styled from "styled-components"; +// import ReconnectSSHError from "../components/ReconnectSSHError"; +import { GitOpsTab } from "git/constants/enums"; +import noop from "lodash/noop"; + +const StyledModalContent = styled(ModalContent)` + &&& { + width: 640px; + transform: none !important; + top: 100px; + left: calc(50% - 320px); + max-height: calc(100vh - 200px); + } +`; + +interface DumbGitOpsModalProps { + isOpsModalOpen: boolean; + isProtectedMode: boolean; + opsModalTab: keyof typeof GitOpsTab; + repoName: string | null; + toggleOpsModal: (open: boolean, tab?: keyof typeof GitOpsTab) => void; +} + +function DumbGitOpsModal({ + isOpsModalOpen = false, + isProtectedMode = false, + opsModalTab = GitOpsTab.Deploy, + repoName = null, + toggleOpsModal = noop, +}: DumbGitOpsModalProps) { + const handleTabKeyChange = useCallback( + (tabKey: string) => { + if (tabKey === GitOpsTab.Deploy) { + AnalyticsUtil.logEvent("GS_DEPLOY_GIT_MODAL_TRIGGERED", { + source: `${tabKey.toUpperCase()}_TAB`, + }); + } else if (tabKey === GitOpsTab.Merge) { + AnalyticsUtil.logEvent("GS_MERGE_GIT_MODAL_TRIGGERED", { + source: `${tabKey.toUpperCase()}_TAB`, + }); + } + + toggleOpsModal(true, tabKey as GitOpsTab); + }, + [toggleOpsModal], + ); + + return ( + <> + + + {repoName} + {/* {isGitConnected && } */} + + + + {createMessage(DEPLOY)} + + + {createMessage(MERGE)} + + + + {opsModalTab === GitOpsTab.Deploy && } + {opsModalTab === GitOpsTab.Merge && } + + + {/* */} + + ); +} + +export default DumbGitOpsModal; diff --git a/app/client/src/git/components/GitOpsModal/index.tsx b/app/client/src/git/components/GitOpsModal/index.tsx index aa69d606d5e9..9820aec6656a 100644 --- a/app/client/src/git/components/GitOpsModal/index.tsx +++ b/app/client/src/git/components/GitOpsModal/index.tsx @@ -1,97 +1,25 @@ -import React, { useCallback } from "react"; -import TabDeploy from "./TabDeploy"; -import TabMerge from "./TabMerge"; +import React from "react"; +import DumbGitOpsModal from "./DumbGitOpsModal"; +import { useGitContext } from "../GitContextProvider"; -// import GitErrorPopup from "../components/GitErrorPopup"; +export default function GitOpsModal() { + const { + gitMetadata, + opsModalOpen, + opsModalTab, + protectedMode, + toggleOpsModal, + } = useGitContext(); -import { createMessage, DEPLOY, MERGE } from "ee/constants/messages"; -import AnalyticsUtil from "ee/utils/AnalyticsUtil"; -import { - Modal, - ModalContent, - ModalHeader, - Tab, - Tabs, - TabsList, -} from "@appsmith/ads"; -import styled from "styled-components"; -// import ReconnectSSHError from "../components/ReconnectSSHError"; -import { GitOpsTab } from "git/constants/enums"; -import noop from "lodash/noop"; - -const StyledModalContent = styled(ModalContent)` - &&& { - width: 640px; - transform: none !important; - top: 100px; - left: calc(50% - 320px); - max-height: calc(100vh - 200px); - } -`; - -interface GitOpsModalProps { - isOpsModalOpen: boolean; - isProtectedMode: boolean; - opsModalTab: keyof typeof GitOpsTab; - repoName: string | null; - toggleOpsModal: (open: boolean, tab?: keyof typeof GitOpsTab) => void; -} - -function GitOpsModal({ - isOpsModalOpen = false, - isProtectedMode = false, - opsModalTab = GitOpsTab.Deploy, - repoName = null, - toggleOpsModal = noop, -}: GitOpsModalProps) { - const handleTabKeyChange = useCallback( - (tabKey: string) => { - if (tabKey === GitOpsTab.Deploy) { - AnalyticsUtil.logEvent("GS_DEPLOY_GIT_MODAL_TRIGGERED", { - source: `${tabKey.toUpperCase()}_TAB`, - }); - } else if (tabKey === GitOpsTab.Merge) { - AnalyticsUtil.logEvent("GS_MERGE_GIT_MODAL_TRIGGERED", { - source: `${tabKey.toUpperCase()}_TAB`, - }); - } - - toggleOpsModal(true, tabKey as GitOpsTab); - }, - [toggleOpsModal], - ); + const repoName = gitMetadata?.repoName ?? null; return ( - <> - - - {repoName} - {/* {isGitConnected && } */} - - - - {createMessage(DEPLOY)} - - - {createMessage(MERGE)} - - - - {opsModalTab === GitOpsTab.Deploy && } - {opsModalTab === GitOpsTab.Merge && } - - - {/* */} - + ); } - -export default GitOpsModal; diff --git a/app/client/src/git/components/GitQuickActions/index.test.tsx b/app/client/src/git/components/GitQuickActions/DumbGitQuickActions.test.tsx similarity index 92% rename from app/client/src/git/components/GitQuickActions/index.test.tsx rename to app/client/src/git/components/GitQuickActions/DumbGitQuickActions.test.tsx index ce4b943a5d1e..94167f1d833d 100644 --- a/app/client/src/git/components/GitQuickActions/index.test.tsx +++ b/app/client/src/git/components/GitQuickActions/DumbGitQuickActions.test.tsx @@ -1,7 +1,7 @@ import React from "react"; import { render, screen, fireEvent } from "@testing-library/react"; import AnalyticsUtil from "ee/utils/AnalyticsUtil"; -import QuickActions from "."; +import DumbGitQuickActions from "./DumbGitQuickActions"; import { theme } from "constants/DefaultTheme"; import { ThemeProvider } from "styled-components"; import "@testing-library/jest-dom/extend-expect"; @@ -19,7 +19,7 @@ jest.mock("./AutocommitStatusbar", () => () => (
AutocommitStatusbar
)); -describe("QuickActions Component", () => { +describe("DumbGitQuickActions Component", () => { const defaultProps = { discard: jest.fn(), isAutocommitEnabled: false, @@ -47,7 +47,7 @@ describe("QuickActions Component", () => { it("should render ConnectButton when isGitConnected is false", () => { render( - + , ); expect(screen.getByTestId("connect-button")).toBeInTheDocument(); @@ -61,7 +61,7 @@ describe("QuickActions Component", () => { const { container } = render( - + , ); @@ -89,7 +89,7 @@ describe("QuickActions Component", () => { const { container } = render( - + , ); @@ -107,7 +107,7 @@ describe("QuickActions Component", () => { const { container } = render( - + , ); const commitButton = container.querySelectorAll( @@ -139,7 +139,7 @@ describe("QuickActions Component", () => { const { container } = render( - + , ); const pullButton = container.querySelectorAll( @@ -160,7 +160,7 @@ describe("QuickActions Component", () => { const { container } = render( - + , ); const mergeButton = container.querySelectorAll( @@ -185,7 +185,7 @@ describe("QuickActions Component", () => { const { container } = render( - + , ); const settingsButton = container.querySelectorAll( @@ -211,7 +211,7 @@ describe("QuickActions Component", () => { const { container } = render( - + , ); const commitButton = container.querySelectorAll( @@ -230,7 +230,7 @@ describe("QuickActions Component", () => { const { container } = render( - + , ); @@ -252,7 +252,7 @@ describe("QuickActions Component", () => { render( - + , ); const countElement = screen.getByTestId("t--bottom-bar-count"); @@ -270,7 +270,7 @@ describe("QuickActions Component", () => { render( - + , ); expect(screen.queryByTestId("t--bottom-bar-count")).not.toBeInTheDocument(); @@ -293,7 +293,7 @@ describe("QuickActions Component", () => { const { container } = render( - + , ); const pullButton = container.querySelectorAll( @@ -313,7 +313,7 @@ describe("QuickActions Component", () => { render( - + , ); const countElement = screen.getByTestId("t--bottom-bar-count"); diff --git a/app/client/src/git/components/GitQuickActions/DumbGitQuickActions.tsx b/app/client/src/git/components/GitQuickActions/DumbGitQuickActions.tsx new file mode 100644 index 000000000000..0c2a40270b0d --- /dev/null +++ b/app/client/src/git/components/GitQuickActions/DumbGitQuickActions.tsx @@ -0,0 +1,180 @@ +import React, { useCallback } from "react"; +import styled from "styled-components"; + +import { + COMMIT_CHANGES, + createMessage, + GIT_SETTINGS, + MERGE, +} from "ee/constants/messages"; + +import AnalyticsUtil from "ee/utils/AnalyticsUtil"; +import { GitOpsTab } from "../../constants/enums"; +import { GitSettingsTab } from "../../constants/enums"; +import ConnectButton from "./ConnectButton"; +import QuickActionButton from "./QuickActionButton"; +import AutocommitStatusbar from "./AutocommitStatusbar"; +import getPullBtnStatus from "./helpers/getPullButtonStatus"; +import noop from "lodash/noop"; + +const Container = styled.div` + height: 100%; + display: flex; + align-items: center; +`; + +interface DumbGitQuickActionsProps { + discard: () => void; + isAutocommitEnabled: boolean; + isAutocommitPolling: boolean; + isConnectPermitted: boolean; + isDiscardLoading: boolean; + isFetchStatusLoading: boolean; + isGitConnected: boolean; + isProtectedMode: boolean; + isPullFailing: boolean; + isPullLoading: boolean; + isStatusClean: boolean; + pull: () => void; + statusBehindCount: number; + statusChangeCount: number; + toggleConnectModal: (open: boolean) => void; + toggleOpsModal: (open: boolean, tab: keyof typeof GitOpsTab) => void; + toggleSettingsModal: ( + open: boolean, + tab: keyof typeof GitSettingsTab, + ) => void; +} + +function DumbGitQuickActions({ + discard = noop, + isAutocommitEnabled = false, + isAutocommitPolling = false, + isConnectPermitted = false, + isDiscardLoading = false, + isFetchStatusLoading = false, + isGitConnected = false, + isProtectedMode = false, + isPullFailing = false, + isPullLoading = false, + isStatusClean = false, + pull = noop, + statusBehindCount = 0, + statusChangeCount = 0, + toggleConnectModal = noop, + toggleOpsModal = noop, + toggleSettingsModal = noop, +}: DumbGitQuickActionsProps) { + const { isDisabled: isPullDisabled, message: pullTooltipMessage } = + getPullBtnStatus({ + isStatusClean, + isProtectedMode, + isPullFailing, + statusBehindCount, + }); + + const isPullButtonLoading = + isDiscardLoading || isPullLoading || isFetchStatusLoading; + + const onCommitBtnClick = useCallback(() => { + if (!isFetchStatusLoading && !isProtectedMode) { + toggleOpsModal(true, GitOpsTab.Deploy); + + AnalyticsUtil.logEvent("GS_DEPLOY_GIT_MODAL_TRIGGERED", { + source: "BOTTOM_BAR_GIT_COMMIT_BUTTON", + }); + } + }, [isFetchStatusLoading, isProtectedMode, toggleOpsModal]); + + const onPullBtnClick = useCallback(() => { + if (!isPullButtonLoading && !isPullDisabled) { + AnalyticsUtil.logEvent("GS_PULL_GIT_CLICK", { + source: "BOTTOM_BAR_GIT_PULL_BUTTON", + }); + + if (isProtectedMode) { + discard(); + } else { + // ! case: why is triggeredFromBottomBar this needed? + // pull({ triggeredFromBottomBar: true }); + pull(); + } + } + }, [discard, isProtectedMode, pull, isPullDisabled, isPullButtonLoading]); + + const onMergeBtnClick = useCallback(() => { + AnalyticsUtil.logEvent("GS_MERGE_GIT_MODAL_TRIGGERED", { + source: "BOTTOM_BAR_GIT_MERGE_BUTTON", + }); + toggleOpsModal(true, GitOpsTab.Merge); + }, [toggleOpsModal]); + + const onSettingsClick = useCallback(() => { + toggleSettingsModal(true, GitSettingsTab.General); + AnalyticsUtil.logEvent("GS_SETTING_CLICK", { + source: "BOTTOM_BAR_GIT_SETTING_BUTTON", + }); + }, [toggleSettingsModal]); + + const onConnectBtnClick = useCallback(() => { + AnalyticsUtil.logEvent("GS_CONNECT_GIT_CLICK", { + source: "BOTTOM_BAR_GIT_CONNECT_BUTTON", + }); + + toggleConnectModal(true); + }, [toggleConnectModal]); + + return isGitConnected ? ( + + {/* */} + {isAutocommitEnabled && isAutocommitPolling ? ( + + ) : ( + <> + + + + + + )} + + ) : ( + + ); +} + +export default DumbGitQuickActions; diff --git a/app/client/src/git/components/CtxAwareGitQuickActions/hooks/useStatusChangeCount.ts b/app/client/src/git/components/GitQuickActions/hooks/useStatusChangeCount.ts similarity index 100% rename from app/client/src/git/components/CtxAwareGitQuickActions/hooks/useStatusChangeCount.ts rename to app/client/src/git/components/GitQuickActions/hooks/useStatusChangeCount.ts diff --git a/app/client/src/git/components/GitQuickActions/index.tsx b/app/client/src/git/components/GitQuickActions/index.tsx index e7b1e1b72411..d3d1acbd1a49 100644 --- a/app/client/src/git/components/GitQuickActions/index.tsx +++ b/app/client/src/git/components/GitQuickActions/index.tsx @@ -1,178 +1,51 @@ -import React, { useCallback } from "react"; -import styled from "styled-components"; - -import { - COMMIT_CHANGES, - createMessage, - GIT_SETTINGS, - MERGE, -} from "ee/constants/messages"; - -import AnalyticsUtil from "ee/utils/AnalyticsUtil"; -import { GitOpsTab } from "../../constants/enums"; -import { GitSettingsTab } from "../../constants/enums"; -import ConnectButton from "./ConnectButton"; -import QuickActionButton from "./QuickActionButton"; -import AutocommitStatusbar from "./AutocommitStatusbar"; -import getPullBtnStatus from "./helpers/getPullButtonStatus"; -import noop from "lodash/noop"; - -const Container = styled.div` - height: 100%; - display: flex; - align-items: center; -`; - -interface GitQuickActionsProps { - discard: () => void; - isAutocommitEnabled: boolean; - isAutocommitPolling: boolean; - isConnectPermitted: boolean; - isDiscardLoading: boolean; - isFetchStatusLoading: boolean; - isGitConnected: boolean; - isProtectedMode: boolean; - isPullFailing: boolean; - isPullLoading: boolean; - isStatusClean: boolean; - pull: () => void; - statusBehindCount: number; - statusChangeCount: number; - toggleConnectModal: (open: boolean) => void; - toggleOpsModal: (open: boolean, tab: keyof typeof GitOpsTab) => void; - toggleSettingsModal: ( - open: boolean, - tab: keyof typeof GitSettingsTab, - ) => void; -} - -function GitQuickActions({ - discard = noop, - isAutocommitEnabled = false, - isAutocommitPolling = false, - isConnectPermitted = false, - isDiscardLoading = false, - isFetchStatusLoading = false, - isGitConnected = false, - isProtectedMode = false, - isPullFailing = false, - isPullLoading = false, - isStatusClean = false, - pull = noop, - statusBehindCount = 0, - statusChangeCount = 0, - toggleConnectModal = noop, - toggleOpsModal = noop, - toggleSettingsModal = noop, -}: GitQuickActionsProps) { - const { isDisabled: isPullDisabled, message: pullTooltipMessage } = - getPullBtnStatus({ - isStatusClean, - isProtectedMode, - isPullFailing, - statusBehindCount, - }); - - const isPullButtonLoading = - isDiscardLoading || isPullLoading || isFetchStatusLoading; - - const onCommitBtnClick = useCallback(() => { - if (!isFetchStatusLoading && !isProtectedMode) { - toggleOpsModal(true, GitOpsTab.Deploy); - - AnalyticsUtil.logEvent("GS_DEPLOY_GIT_MODAL_TRIGGERED", { - source: "BOTTOM_BAR_GIT_COMMIT_BUTTON", - }); - } - }, [isFetchStatusLoading, isProtectedMode, toggleOpsModal]); - - const onPullBtnClick = useCallback(() => { - if (!isPullButtonLoading && !isPullDisabled) { - AnalyticsUtil.logEvent("GS_PULL_GIT_CLICK", { - source: "BOTTOM_BAR_GIT_PULL_BUTTON", - }); - - if (isProtectedMode) { - discard(); - } else { - // ! case: why is triggeredFromBottomBar this needed? - // pull({ triggeredFromBottomBar: true }); - pull(); - } - } - }, [discard, isProtectedMode, pull, isPullDisabled, isPullButtonLoading]); - - const onMergeBtnClick = useCallback(() => { - AnalyticsUtil.logEvent("GS_MERGE_GIT_MODAL_TRIGGERED", { - source: "BOTTOM_BAR_GIT_MERGE_BUTTON", - }); - toggleOpsModal(true, GitOpsTab.Merge); - }, [toggleOpsModal]); - - const onSettingsClick = useCallback(() => { - toggleSettingsModal(true, GitSettingsTab.General); - AnalyticsUtil.logEvent("GS_SETTING_CLICK", { - source: "BOTTOM_BAR_GIT_SETTING_BUTTON", - }); - }, [toggleSettingsModal]); - - const onConnectBtnClick = useCallback(() => { - AnalyticsUtil.logEvent("GS_CONNECT_GIT_CLICK", { - source: "BOTTOM_BAR_GIT_CONNECT_BUTTON", - }); - - toggleConnectModal(true); - }, [toggleConnectModal]); - - return isGitConnected ? ( - - {/* */} - {isAutocommitEnabled && isAutocommitPolling ? ( - - ) : ( - <> - - - - - - )} - - ) : ( - ); } From c5c95855b08a562849dd6a0628cb1af1ad74ab72 Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Wed, 11 Dec 2024 20:21:43 +0800 Subject: [PATCH 031/143] fix: adding conflicterror and conflicterrormodal --- .../GitConflictError/DumbGitConflictError.tsx | 72 +++++++++++++++ .../git/components/GitConflictError/index.tsx | 14 +++ .../DumbGitConflictErrorModal.tsx | 92 +++++++++++++++++++ .../GitConflictErrorModal/index.tsx | 14 +++ .../GitContextProvider/hooks/useGitOps.ts | 19 ++++ app/client/src/git/components/GitModals.tsx | 8 +- .../GitOpsModal/DumbGitOpsModal.tsx | 3 - app/client/src/git/store/actions/uiActions.ts | 15 +++ app/client/src/git/store/gitArtifactSlice.ts | 2 + .../helpers/gitSingleArtifactInitialState.ts | 1 + .../selectors/gitSingleArtifactSelectors.ts | 25 +++-- app/client/src/git/store/types.ts | 1 + 12 files changed, 252 insertions(+), 14 deletions(-) create mode 100644 app/client/src/git/components/GitConflictError/DumbGitConflictError.tsx create mode 100644 app/client/src/git/components/GitConflictError/index.tsx create mode 100644 app/client/src/git/components/GitConflictErrorModal/DumbGitConflictErrorModal.tsx create mode 100644 app/client/src/git/components/GitConflictErrorModal/index.tsx diff --git a/app/client/src/git/components/GitConflictError/DumbGitConflictError.tsx b/app/client/src/git/components/GitConflictError/DumbGitConflictError.tsx new file mode 100644 index 000000000000..0813971f04d5 --- /dev/null +++ b/app/client/src/git/components/GitConflictError/DumbGitConflictError.tsx @@ -0,0 +1,72 @@ +import React, { useCallback, useMemo } from "react"; +import styled from "styled-components"; +import { + createMessage, + GIT_CONFLICTING_INFO, + LEARN_MORE, + OPEN_REPO, +} from "ee/constants/messages"; +import { Button, Callout } from "@appsmith/ads"; + +const Row = styled.div` + display: flex; + align-items: center; +`; + +const StyledButton = styled(Button)` + margin-right: ${(props) => props.theme.spaces[3]}px; +`; + +const StyledCallout = styled(Callout)` + margin-bottom: 12px; +`; + +const ConflictInfoContainer = styled.div` + margin-top: ${(props) => props.theme.spaces[7]}px; + margin-bottom: ${(props) => props.theme.spaces[7]}px; +`; + +interface DumbGitConflictErrorProps { + learnMoreUrl: string; + repoUrl: string; +} + +export default function DumbGitConflictError({ + learnMoreUrl, + repoUrl, +}: DumbGitConflictErrorProps) { + const handleClickOnOpenRepo = useCallback(() => { + window.open(repoUrl, "_blank"); + }, [repoUrl]); + + const calloutLinks = useMemo( + () => [ + { + children: createMessage(LEARN_MORE), + to: learnMoreUrl, + }, + ], + [learnMoreUrl], + ); + + return ( + + + {createMessage(GIT_CONFLICTING_INFO)} + + + + {createMessage(OPEN_REPO)} + + + + ); +} diff --git a/app/client/src/git/components/GitConflictError/index.tsx b/app/client/src/git/components/GitConflictError/index.tsx new file mode 100644 index 000000000000..e4667bf8d444 --- /dev/null +++ b/app/client/src/git/components/GitConflictError/index.tsx @@ -0,0 +1,14 @@ +import React from "react"; + +import { useGitContext } from "../GitContextProvider"; +import DumbGitConflictError from "./DumbGitConflictError"; + +export default function GitConflictError() { + const { gitMetadata } = useGitContext(); + + const learnMoreUrl = + "https://docs.appsmith.com/advanced-concepts/version-control-with-git"; + const repoUrl = gitMetadata?.browserSupportedRemoteUrl || ""; + + return ; +} diff --git a/app/client/src/git/components/GitConflictErrorModal/DumbGitConflictErrorModal.tsx b/app/client/src/git/components/GitConflictErrorModal/DumbGitConflictErrorModal.tsx new file mode 100644 index 000000000000..e30768f3316b --- /dev/null +++ b/app/client/src/git/components/GitConflictErrorModal/DumbGitConflictErrorModal.tsx @@ -0,0 +1,92 @@ +import React, { useCallback } from "react"; +import styled from "styled-components"; +import { Overlay, Classes } from "@blueprintjs/core"; +import { + createMessage, + CONFLICTS_FOUND_WHILE_PULLING_CHANGES, +} from "ee/constants/messages"; + +import { Button } from "@appsmith/ads"; +import noop from "lodash/noop"; +import GitConflictError from "../GitConflictError"; + +const StyledGitErrorPopup = styled.div` + & { + .${Classes.OVERLAY} { + position: fixed; + bottom: 0; + left: 0; + right: 0; + display: flex; + justify-content: center; + + .${Classes.OVERLAY_CONTENT} { + overflow: hidden; + bottom: 52px; + left: 12px; + background-color: #ffffff; + } + } + + .git-error-popup { + width: 364px; + padding: ${(props) => props.theme.spaces[7]}px; + + display: flex; + flex-direction: column; + } + } +`; + +interface DumbGitConflictErrorModalProps { + isConfictErrorModalOpen?: boolean; + toggleConflictErrorModal?: (open: boolean) => void; +} + +function DumbGitConflictErrorModal({ + isConfictErrorModalOpen = false, + toggleConflictErrorModal = noop, +}: DumbGitConflictErrorModalProps) { + const handleClose = useCallback(() => { + toggleConflictErrorModal(false); + }, [toggleConflictErrorModal]); + + return ( + + +
+
+
+
+ + {createMessage(CONFLICTS_FOUND_WHILE_PULLING_CHANGES)} + +
+
+ +
+
+
+
+ ); +} + +export default DumbGitConflictErrorModal; diff --git a/app/client/src/git/components/GitConflictErrorModal/index.tsx b/app/client/src/git/components/GitConflictErrorModal/index.tsx new file mode 100644 index 000000000000..46697200f458 --- /dev/null +++ b/app/client/src/git/components/GitConflictErrorModal/index.tsx @@ -0,0 +1,14 @@ +import React from "react"; +import DumbGitConflictErrorModal from "./DumbGitConflictErrorModal"; +import { useGitContext } from "../GitContextProvider"; + +export default function GitConflictErrorModal() { + const { conflictErrorModalOpen, toggleConflictErrorModal } = useGitContext(); + + return ( + + ); +} diff --git a/app/client/src/git/components/GitContextProvider/hooks/useGitOps.ts b/app/client/src/git/components/GitContextProvider/hooks/useGitOps.ts index 503c45072f70..60e4e244dbb1 100644 --- a/app/client/src/git/components/GitContextProvider/hooks/useGitOps.ts +++ b/app/client/src/git/components/GitContextProvider/hooks/useGitOps.ts @@ -4,6 +4,7 @@ import type { FetchStatusResponseData } from "git/requests/fetchStatusRequest.ty import { gitArtifactActions } from "git/store/gitArtifactSlice"; import { selectCommit, + selectConflictErrorModalOpen, selectDiscard, selectMerge, selectMergeStatus, @@ -45,6 +46,8 @@ export interface UseGitOpsReturnValue { opsModalTab: keyof typeof GitOpsTab; opsModalOpen: boolean; toggleOpsModal: (open: boolean, tab?: keyof typeof GitOpsTab) => void; + conflictErrorModalOpen: boolean; + toggleConflictErrorModal: (open: boolean) => void; } export default function useGitOps({ @@ -143,6 +146,20 @@ export default function useGitOps({ [basePayload, dispatch], ); + // conflict error modal + const conflictErrorModalOpen = useSelector((state: GitRootState) => + selectConflictErrorModalOpen(state, basePayload), + ); + + const toggleConflictErrorModal = useCallback( + (open: boolean) => { + dispatch( + gitArtifactActions.toggleConflictErrorModal({ ...basePayload, open }), + ); + }, + [basePayload, dispatch], + ); + return { commitLoading: commitState?.loading ?? false, commitError: commitState?.error, @@ -167,5 +184,7 @@ export default function useGitOps({ opsModalTab, opsModalOpen, toggleOpsModal, + conflictErrorModalOpen, + toggleConflictErrorModal, }; } diff --git a/app/client/src/git/components/GitModals.tsx b/app/client/src/git/components/GitModals.tsx index 5f7bbc18e6f9..52b2097eee16 100644 --- a/app/client/src/git/components/GitModals.tsx +++ b/app/client/src/git/components/GitModals.tsx @@ -1,6 +1,12 @@ import React from "react"; import GitOpsModal from "./GitOpsModal"; +import GitConflictErrorModal from "./GitConflictErrorModal"; export default function GitModals() { - return ; + return ( + <> + + + + ); } diff --git a/app/client/src/git/components/GitOpsModal/DumbGitOpsModal.tsx b/app/client/src/git/components/GitOpsModal/DumbGitOpsModal.tsx index b1e1fc835073..039ab835d204 100644 --- a/app/client/src/git/components/GitOpsModal/DumbGitOpsModal.tsx +++ b/app/client/src/git/components/GitOpsModal/DumbGitOpsModal.tsx @@ -1,9 +1,6 @@ import React, { useCallback } from "react"; import TabDeploy from "./TabDeploy"; import TabMerge from "./TabMerge"; - -// import GitErrorPopup from "../components/GitErrorPopup"; - import { createMessage, DEPLOY, MERGE } from "ee/constants/messages"; import AnalyticsUtil from "ee/utils/AnalyticsUtil"; import { diff --git a/app/client/src/git/store/actions/uiActions.ts b/app/client/src/git/store/actions/uiActions.ts index 9f0659770998..c4e47fe2fe33 100644 --- a/app/client/src/git/store/actions/uiActions.ts +++ b/app/client/src/git/store/actions/uiActions.ts @@ -14,6 +14,21 @@ export const toggleRepoLimitErrorModalAction = return state; }); +interface ToggleConflictErrorModalPayload { + open: boolean; +} + +export const toggleConflictErrorModalAction = + createSingleArtifactAction( + (state, action) => { + const { open } = action.payload; + + state.ui.conflictErrorModalOpen = open; + + return state; + }, + ); + interface BranchListPopupPayload { open: boolean; } diff --git a/app/client/src/git/store/gitArtifactSlice.ts b/app/client/src/git/store/gitArtifactSlice.ts index a1bb0f5c56e2..2da393f49e04 100644 --- a/app/client/src/git/store/gitArtifactSlice.ts +++ b/app/client/src/git/store/gitArtifactSlice.ts @@ -58,6 +58,7 @@ import { toggleOpsModalAction, toggleSettingsModalAction, toggleRepoLimitErrorModalAction, + toggleConflictErrorModalAction, } from "./actions/uiActions"; import { checkoutBranchErrorAction, @@ -150,6 +151,7 @@ export const gitArtifactSlice = createSlice({ pullSuccess: pullSuccessAction, pullError: pullErrorAction, toggleOpsModal: toggleOpsModalAction, + toggleConflictErrorModal: toggleConflictErrorModalAction, // branches fetchBranchesInit: fetchBranchesInitAction, diff --git a/app/client/src/git/store/helpers/gitSingleArtifactInitialState.ts b/app/client/src/git/store/helpers/gitSingleArtifactInitialState.ts index 4d3366ea662f..9266e852ff7a 100644 --- a/app/client/src/git/store/helpers/gitSingleArtifactInitialState.ts +++ b/app/client/src/git/store/helpers/gitSingleArtifactInitialState.ts @@ -24,6 +24,7 @@ const gitSingleArtifactInitialUIState: GitSingleArtifactUIReduxState = { }, opsModalOpen: false, opsModalTab: GitOpsTab.Deploy, + conflictErrorModalOpen: false, settingsModal: { open: false, tab: GitSettingsTab.General, diff --git a/app/client/src/git/store/selectors/gitSingleArtifactSelectors.ts b/app/client/src/git/store/selectors/gitSingleArtifactSelectors.ts index 3bfbfbce3e9f..4ff29711e662 100644 --- a/app/client/src/git/store/selectors/gitSingleArtifactSelectors.ts +++ b/app/client/src/git/store/selectors/gitSingleArtifactSelectors.ts @@ -27,16 +27,6 @@ export const selectGitConnected = ( ) => !!selectGitMetadata(state, artifactDef).value; // git ops -export const selectOpsModalOpen = ( - state: GitRootState, - artifactDef: GitArtifactDef, -) => selectSingleArtifact(state, artifactDef)?.ui.opsModalOpen; - -export const selectOpsModalTab = ( - state: GitRootState, - artifactDef: GitArtifactDef, -) => selectSingleArtifact(state, artifactDef)?.ui.opsModalTab; - export const selectCommit = ( state: GitRootState, artifactDef: GitArtifactDef, @@ -63,6 +53,21 @@ export const selectMergeStatus = ( export const selectPull = (state: GitRootState, artifactDef: GitArtifactDef) => selectSingleArtifact(state, artifactDef)?.apiResponses?.pull; +export const selectOpsModalOpen = ( + state: GitRootState, + artifactDef: GitArtifactDef, +) => selectSingleArtifact(state, artifactDef)?.ui.opsModalOpen; + +export const selectOpsModalTab = ( + state: GitRootState, + artifactDef: GitArtifactDef, +) => selectSingleArtifact(state, artifactDef)?.ui.opsModalTab; + +export const selectConflictErrorModalOpen = ( + state: GitRootState, + artifactDef: GitArtifactDef, +) => selectSingleArtifact(state, artifactDef)?.ui.conflictErrorModalOpen; + // git branches export const selectCurrentBranch = ( diff --git a/app/client/src/git/store/types.ts b/app/client/src/git/store/types.ts index 94481f1b2c72..c15d52dc5107 100644 --- a/app/client/src/git/store/types.ts +++ b/app/client/src/git/store/types.ts @@ -65,6 +65,7 @@ export interface GitSingleArtifactUIReduxState { }; opsModalOpen: boolean; opsModalTab: keyof typeof GitOpsTab; + conflictErrorModalOpen: boolean; settingsModal: { open: boolean; tab: keyof typeof GitSettingsTab; From c5b8cf357b6d57b968d208e318671a5cec33338f Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Wed, 11 Dec 2024 21:55:39 +0800 Subject: [PATCH 032/143] fix: adding pull sagas --- .../git/components/GitConflictError/index.tsx | 1 + .../GitContextProvider/hooks/useGitConnect.ts | 4 ++ .../hooks/useGitContextValue.ts | 18 ++++-- .../GitContextProvider/hooks/useGitOps.ts | 11 +++- .../components/GitContextProvider/index.tsx | 18 +++--- app/client/src/git/requests/pullRequest.ts | 4 +- .../src/git/requests/pullRequest.types.ts | 2 +- app/client/src/git/sagas/pullSaga.ts | 56 +++++++++++++++++++ .../src/git/store/actions/pullActions.ts | 22 +++++--- 9 files changed, 108 insertions(+), 28 deletions(-) create mode 100644 app/client/src/git/sagas/pullSaga.ts diff --git a/app/client/src/git/components/GitConflictError/index.tsx b/app/client/src/git/components/GitConflictError/index.tsx index e4667bf8d444..c1da1aa6f6a0 100644 --- a/app/client/src/git/components/GitConflictError/index.tsx +++ b/app/client/src/git/components/GitConflictError/index.tsx @@ -6,6 +6,7 @@ import DumbGitConflictError from "./DumbGitConflictError"; export default function GitConflictError() { const { gitMetadata } = useGitContext(); + // ! case: learnMoreUrl comes from pullError const learnMoreUrl = "https://docs.appsmith.com/advanced-concepts/version-control-with-git"; const repoUrl = gitMetadata?.browserSupportedRemoteUrl || ""; diff --git a/app/client/src/git/components/GitContextProvider/hooks/useGitConnect.ts b/app/client/src/git/components/GitContextProvider/hooks/useGitConnect.ts index 9741a857e7a3..4f7c5ffc395b 100644 --- a/app/client/src/git/components/GitContextProvider/hooks/useGitConnect.ts +++ b/app/client/src/git/components/GitContextProvider/hooks/useGitConnect.ts @@ -6,15 +6,18 @@ import { useDispatch } from "react-redux"; interface UseGitConnectParams { artifactType: keyof typeof GitArtifactType; baseArtifactId: string; + connectPermitted: boolean; } export interface UseGitConnectReturnValue { toggleConnectModal: (open: boolean) => void; + connectPermitted: boolean; } export default function useGitConnect({ artifactType, baseArtifactId, + connectPermitted, }: UseGitConnectParams): UseGitConnectReturnValue { const dispatch = useDispatch(); const basePayload = useMemo( @@ -33,5 +36,6 @@ export default function useGitConnect({ return { toggleConnectModal, + connectPermitted, }; } diff --git a/app/client/src/git/components/GitContextProvider/hooks/useGitContextValue.ts b/app/client/src/git/components/GitContextProvider/hooks/useGitContextValue.ts index 0945eea223f0..4d5d213c2ca3 100644 --- a/app/client/src/git/components/GitContextProvider/hooks/useGitContextValue.ts +++ b/app/client/src/git/components/GitContextProvider/hooks/useGitContextValue.ts @@ -11,9 +11,11 @@ import { useMemo } from "react"; import type { UseGitMetadataReturnValue } from "./useGitMetadata"; import useGitMetadata from "./useGitMetadata"; -interface UseGitContextValueParams { +export interface UseGitContextValueParams { artifactType: keyof typeof GitArtifactType; baseArtifactId: string; + artifact: { id: string; baseId: string } | null; + connectPermitted: boolean; } export interface GitContextValue @@ -24,16 +26,24 @@ export interface GitContextValue UseGitBranchesReturnValue {} export default function useGitContextValue({ + artifact, artifactType, - baseArtifactId, + baseArtifactId = "", + connectPermitted, }: UseGitContextValueParams): GitContextValue { const basePayload = useMemo( () => ({ artifactType, baseArtifactId }), [artifactType, baseArtifactId], ); const useGitMetadataReturnValue = useGitMetadata(basePayload); - const useGitConnectReturnValue = useGitConnect(basePayload); - const useGitOpsReturnValue = useGitOps(basePayload); + const useGitConnectReturnValue = useGitConnect({ + ...basePayload, + connectPermitted, + }); + const useGitOpsReturnValue = useGitOps({ + ...basePayload, + artifactId: artifact?.id ?? null, + }); const useGitBranchesReturnValue = useGitBranches(basePayload); const useGitSettingsReturnValue = useGitSettings(basePayload); diff --git a/app/client/src/git/components/GitContextProvider/hooks/useGitOps.ts b/app/client/src/git/components/GitContextProvider/hooks/useGitOps.ts index 60e4e244dbb1..b1fe82c8f43e 100644 --- a/app/client/src/git/components/GitContextProvider/hooks/useGitOps.ts +++ b/app/client/src/git/components/GitContextProvider/hooks/useGitOps.ts @@ -20,6 +20,7 @@ import { useDispatch, useSelector } from "react-redux"; interface UseGitOpsParams { artifactType: keyof typeof GitArtifactType; baseArtifactId: string; + artifactId: string | null; } export interface UseGitOpsReturnValue { @@ -51,6 +52,7 @@ export interface UseGitOpsReturnValue { } export default function useGitOps({ + artifactId, artifactType, baseArtifactId, }: UseGitOpsParams): UseGitOpsReturnValue { @@ -125,8 +127,13 @@ export default function useGitOps({ ); const pull = useCallback(() => { - dispatch(gitArtifactActions.pullInit(basePayload)); - }, [basePayload, dispatch]); + dispatch( + gitArtifactActions.pullInit({ + ...basePayload, + artifactId: artifactId ?? "", + }), + ); + }, [basePayload, artifactId, dispatch]); // ops modal const opsModalOpen = useSelector((state: GitRootState) => diff --git a/app/client/src/git/components/GitContextProvider/index.tsx b/app/client/src/git/components/GitContextProvider/index.tsx index afb9f010a50c..40a260e07c60 100644 --- a/app/client/src/git/components/GitContextProvider/index.tsx +++ b/app/client/src/git/components/GitContextProvider/index.tsx @@ -1,6 +1,8 @@ import React, { createContext, useContext } from "react"; -import type { GitArtifactType } from "git/constants/enums"; -import type { GitContextValue } from "./hooks/useGitContextValue"; +import type { + GitContextValue, + UseGitContextValueParams, +} from "./hooks/useGitContextValue"; import useGitContextValue from "./hooks/useGitContextValue"; const gitContextInitialValue = {} as GitContextValue; @@ -11,21 +13,15 @@ export const useGitContext = () => { return useContext(GitContext); }; -interface GitContextProviderProps { - artifactType: keyof typeof GitArtifactType; - baseArtifactId: string; +interface GitContextProviderProps extends UseGitContextValueParams { children: React.ReactNode; - // extra - // connectPermitted?: boolean; } export default function GitContextProvider({ - artifactType, - baseArtifactId, children, - // connectPermitted = true, + ...useContextValueParams }: GitContextProviderProps) { - const contextValue = useGitContextValue({ artifactType, baseArtifactId }); + const contextValue = useGitContextValue(useContextValueParams); return ( {children} diff --git a/app/client/src/git/requests/pullRequest.ts b/app/client/src/git/requests/pullRequest.ts index 18870918c0cd..cd533f6d7679 100644 --- a/app/client/src/git/requests/pullRequest.ts +++ b/app/client/src/git/requests/pullRequest.ts @@ -1,10 +1,10 @@ import Api from "api/Api"; import { GIT_BASE_URL } from "./constants"; import type { AxiosPromise } from "axios"; -import type { PullRequestResponse } from "./pullRequest.types"; +import type { PullResponse } from "./pullRequest.types"; export default async function pullRequest( branchedApplicationId: string, -): AxiosPromise { +): AxiosPromise { return Api.get(`${GIT_BASE_URL}/pull/app/${branchedApplicationId}`); } diff --git a/app/client/src/git/requests/pullRequest.types.ts b/app/client/src/git/requests/pullRequest.types.ts index abfb2586ca8e..fe71cee94a52 100644 --- a/app/client/src/git/requests/pullRequest.types.ts +++ b/app/client/src/git/requests/pullRequest.types.ts @@ -1,4 +1,4 @@ -export interface PullRequestResponse { +export interface PullResponse { mergeStatus: { isMergeAble: boolean; status: string; // pull merge status diff --git a/app/client/src/git/sagas/pullSaga.ts b/app/client/src/git/sagas/pullSaga.ts new file mode 100644 index 000000000000..a5d68032d626 --- /dev/null +++ b/app/client/src/git/sagas/pullSaga.ts @@ -0,0 +1,56 @@ +import { call, put, select } from "redux-saga/effects"; +import pullRequest from "git/requests/pullRequest"; +import type { PullResponse } from "git/requests/pullRequest.types"; +import type { PullInitPayload } from "git/store/actions/pullActions"; +import { gitArtifactActions } from "git/store/gitArtifactSlice"; +import type { GitArtifactPayloadAction } from "git/store/types"; +import { selectCurrentBranch } from "git/store/selectors/gitSingleArtifactSelectors"; + +// internal dependencies +import { validateResponse } from "sagas/ErrorSagas"; +import { getCurrentBasePageId } from "selectors/editorSelectors"; +import { initEditorAction } from "actions/initActions"; +import { APP_MODE } from "entities/App"; + +export default function* pullSaga( + action: GitArtifactPayloadAction, +) { + const { artifactId, artifactType, baseArtifactId } = action.payload; + const basePayload = { artifactType, baseArtifactId }; + let response: PullResponse | undefined; + + try { + response = yield call(pullRequest, artifactId); + const isValidResponse: boolean = yield validateResponse(response); + + if (response && isValidResponse) { + yield put(gitArtifactActions.pullSuccess(basePayload)); + + const currentBasePageId: string = yield select(getCurrentBasePageId); + const currentBranch: string = yield select( + selectCurrentBranch, + basePayload, + ); + + yield put( + initEditorAction({ + basePageId: currentBasePageId, + branch: currentBranch, + mode: APP_MODE.EDIT, + }), + ); + } + } catch (e) { + // !case: handle this with error + // if (triggeredFromBottomBar) { + // yield put(setIsGitErrorPopupVisible({ isVisible: true })); + // } + + yield put( + gitArtifactActions.pullError({ + ...basePayload, + error: e as string, + }), + ); + } +} diff --git a/app/client/src/git/store/actions/pullActions.ts b/app/client/src/git/store/actions/pullActions.ts index 5acb7dc30f98..00a0d00f2033 100644 --- a/app/client/src/git/store/actions/pullActions.ts +++ b/app/client/src/git/store/actions/pullActions.ts @@ -1,12 +1,18 @@ import { createSingleArtifactAction } from "../helpers/createSingleArtifactAction"; -import type { GitArtifactErrorPayloadAction } from "../types"; +import type { GitAsyncErrorPayload } from "../types"; -export const pullInitAction = createSingleArtifactAction((state) => { - state.apiResponses.pull.loading = true; - state.apiResponses.pull.error = null; +export interface PullInitPayload { + artifactId: string; +} - return state; -}); +export const pullInitAction = createSingleArtifactAction( + (state) => { + state.apiResponses.pull.loading = true; + state.apiResponses.pull.error = null; + + return state; + }, +); export const pullSuccessAction = createSingleArtifactAction((state) => { state.apiResponses.pull.loading = false; @@ -14,8 +20,8 @@ export const pullSuccessAction = createSingleArtifactAction((state) => { return state; }); -export const pullErrorAction = createSingleArtifactAction( - (state, action: GitArtifactErrorPayloadAction) => { +export const pullErrorAction = createSingleArtifactAction( + (state, action) => { const { error } = action.payload; state.apiResponses.pull.loading = false; From bcef9f5a2a8c217b35df4ca6be5354e8150d4172 Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Thu, 12 Dec 2024 01:35:22 +0800 Subject: [PATCH 033/143] chore: adding deploy tab --- .../hooks/useGitBranches.ts | 8 + .../hooks/useGitContextValue.ts | 10 +- .../GitContextProvider/hooks/useGitOps.ts | 12 + .../GitOpsModal/TabDeploy/DeployPreview.tsx | 82 ++++ .../TabDeploy/DiscardChangesWarning.tsx | 43 ++ .../TabDeploy/DiscardFailedWarning.tsx | 30 ++ .../GitOpsModal/TabDeploy/DumbTabDeploy.tsx | 424 ++++++++++++++++++ .../TabDeploy/PushFailedWarning.tsx | 24 + .../GitOpsModal/TabDeploy/SubmitWrapper.tsx | 26 ++ .../GitOpsModal/TabDeploy/UpstreamWarning.tsx | 33 ++ .../GitOpsModal/TabDeploy/index.tsx | 49 +- .../git/components/GitStatus/StatusLoader.tsx | 23 + .../src/git/components/GitStatus/index.tsx | 7 + .../src/git/store/actions/commitActions.ts | 6 + .../src/git/store/actions/discardActions.ts | 6 + app/client/src/git/store/gitArtifactSlice.ts | 4 + 16 files changed, 784 insertions(+), 3 deletions(-) create mode 100644 app/client/src/git/components/GitOpsModal/TabDeploy/DeployPreview.tsx create mode 100644 app/client/src/git/components/GitOpsModal/TabDeploy/DiscardChangesWarning.tsx create mode 100644 app/client/src/git/components/GitOpsModal/TabDeploy/DiscardFailedWarning.tsx create mode 100644 app/client/src/git/components/GitOpsModal/TabDeploy/DumbTabDeploy.tsx create mode 100644 app/client/src/git/components/GitOpsModal/TabDeploy/PushFailedWarning.tsx create mode 100644 app/client/src/git/components/GitOpsModal/TabDeploy/SubmitWrapper.tsx create mode 100644 app/client/src/git/components/GitOpsModal/TabDeploy/UpstreamWarning.tsx create mode 100644 app/client/src/git/components/GitStatus/StatusLoader.tsx create mode 100644 app/client/src/git/components/GitStatus/index.tsx diff --git a/app/client/src/git/components/GitContextProvider/hooks/useGitBranches.ts b/app/client/src/git/components/GitContextProvider/hooks/useGitBranches.ts index bc670004b7c3..2ec719175189 100644 --- a/app/client/src/git/components/GitContextProvider/hooks/useGitBranches.ts +++ b/app/client/src/git/components/GitContextProvider/hooks/useGitBranches.ts @@ -5,6 +5,7 @@ import { selectBranches, selectCheckoutBranch, selectCreateBranch, + selectCurrentBranch, selectDeleteBranch, } from "git/store/selectors/gitSingleArtifactSelectors"; import type { GitRootState } from "git/store/types"; @@ -30,6 +31,7 @@ export interface UseGitBranchesReturnValue { checkoutBranchLoading: boolean; checkoutBranchError: string | null; checkoutBranch: (branchName: string) => void; + currentBranch: string | null; toggleBranchListPopup: (open: boolean) => void; } @@ -102,6 +104,11 @@ export default function useGitBranches({ [basePayload, dispatch], ); + // derived + const currentBranch = useSelector((state: GitRootState) => + selectCurrentBranch(state, basePayload), + ); + // git branch list popup const toggleBranchListPopup = (open: boolean) => { dispatch( @@ -126,6 +133,7 @@ export default function useGitBranches({ checkoutBranchLoading: checkoutBranchState?.loading ?? false, checkoutBranchError: checkoutBranchState?.error, checkoutBranch, + currentBranch: currentBranch ?? null, toggleBranchListPopup, }; } diff --git a/app/client/src/git/components/GitContextProvider/hooks/useGitContextValue.ts b/app/client/src/git/components/GitContextProvider/hooks/useGitContextValue.ts index 4d5d213c2ca3..2fb0d0666e46 100644 --- a/app/client/src/git/components/GitContextProvider/hooks/useGitContextValue.ts +++ b/app/client/src/git/components/GitContextProvider/hooks/useGitContextValue.ts @@ -11,10 +11,13 @@ import { useMemo } from "react"; import type { UseGitMetadataReturnValue } from "./useGitMetadata"; import useGitMetadata from "./useGitMetadata"; +// internal dependencies +import type { ApplicationPayload } from "entities/Application"; + export interface UseGitContextValueParams { artifactType: keyof typeof GitArtifactType; baseArtifactId: string; - artifact: { id: string; baseId: string } | null; + artifact: ApplicationPayload | null; connectPermitted: boolean; } @@ -23,7 +26,9 @@ export interface GitContextValue UseGitConnectReturnValue, UseGitOpsReturnValue, UseGitSettingsReturnValue, - UseGitBranchesReturnValue {} + UseGitBranchesReturnValue { + artifact: ApplicationPayload | null; +} export default function useGitContextValue({ artifact, @@ -48,6 +53,7 @@ export default function useGitContextValue({ const useGitSettingsReturnValue = useGitSettings(basePayload); return { + artifact, ...useGitMetadataReturnValue, ...useGitOpsReturnValue, ...useGitBranchesReturnValue, diff --git a/app/client/src/git/components/GitContextProvider/hooks/useGitOps.ts b/app/client/src/git/components/GitContextProvider/hooks/useGitOps.ts index b1fe82c8f43e..c14761087505 100644 --- a/app/client/src/git/components/GitContextProvider/hooks/useGitOps.ts +++ b/app/client/src/git/components/GitContextProvider/hooks/useGitOps.ts @@ -27,9 +27,11 @@ export interface UseGitOpsReturnValue { commitLoading: boolean; commitError: string | null; commit: (commitMessage: string) => void; + clearCommitError: () => void; discardLoading: boolean; discardError: string | null; discard: () => void; + clearDiscardError: () => void; status: FetchStatusResponseData | null; fetchStatusLoading: boolean; fetchStatusError: string | null; @@ -80,6 +82,10 @@ export default function useGitOps({ [basePayload, dispatch], ); + const clearCommitError = useCallback(() => { + dispatch(gitArtifactActions.clearCommitError(basePayload)); + }, [basePayload, dispatch]); + // discard const discardState = useSelector((state: GitRootState) => selectDiscard(state, basePayload), @@ -89,6 +95,10 @@ export default function useGitOps({ dispatch(gitArtifactActions.discardInit(basePayload)); }, [basePayload, dispatch]); + const clearDiscardError = useCallback(() => { + dispatch(gitArtifactActions.clearDiscardError(basePayload)); + }, [basePayload, dispatch]); + // status const statusState = useSelector((state: GitRootState) => selectStatus(state, basePayload), @@ -171,9 +181,11 @@ export default function useGitOps({ commitLoading: commitState?.loading ?? false, commitError: commitState?.error, commit, + clearCommitError, discardLoading: discardState?.loading ?? false, discardError: discardState?.error, discard, + clearDiscardError, status: statusState?.value, fetchStatusLoading: statusState?.loading ?? false, fetchStatusError: statusState?.error, diff --git a/app/client/src/git/components/GitOpsModal/TabDeploy/DeployPreview.tsx b/app/client/src/git/components/GitOpsModal/TabDeploy/DeployPreview.tsx new file mode 100644 index 000000000000..79abbe1439dc --- /dev/null +++ b/app/client/src/git/components/GitOpsModal/TabDeploy/DeployPreview.tsx @@ -0,0 +1,82 @@ +import React from "react"; + +import styled from "styled-components"; +import { useSelector } from "react-redux"; +import { + getApplicationLastDeployedAt, + getCurrentBasePageId, +} from "selectors/editorSelectors"; +import { + createMessage, + LATEST_DP_SUBTITLE, + LATEST_DP_TITLE, +} from "ee/constants/messages"; +import SuccessTick from "pages/common/SuccessTick"; +import { howMuchTimeBeforeText } from "utils/helpers"; +import AnalyticsUtil from "ee/utils/AnalyticsUtil"; +import { viewerURL } from "ee/RouteBuilder"; +import { Link, Text } from "@appsmith/ads"; +import { importSvg } from "@appsmith/ads-old"; + +const CloudyIcon = importSvg( + async () => import("assets/icons/ads/cloudy-line.svg"), +); + +const Container = styled.div` + display: flex; + flex: 1; + flex-direction: row; + gap: ${(props) => props.theme.spaces[6]}px; + + .cloud-icon { + stroke: var(--ads-v2-color-fg); + } +`; + +export default function DeployPreview() { + // ! case: should reset after timer + const showSuccess = false; + + const basePageId = useSelector(getCurrentBasePageId); + const lastDeployedAt = useSelector(getApplicationLastDeployedAt); + + const showDeployPreview = () => { + AnalyticsUtil.logEvent("GS_LAST_DEPLOYED_PREVIEW_LINK_CLICK", { + source: "GIT_DEPLOY_MODAL", + }); + const path = viewerURL({ + basePageId, + }); + + window.open(path, "_blank"); + }; + + const lastDeployedAtMsg = lastDeployedAt + ? `${createMessage(LATEST_DP_SUBTITLE)} ${howMuchTimeBeforeText( + lastDeployedAt, + { + lessThanAMinute: true, + }, + )} ago` + : ""; + + return lastDeployedAt ? ( + +
+ {showSuccess ? ( + + ) : ( + + )} +
+
+ + {createMessage(LATEST_DP_TITLE)} + + + {lastDeployedAtMsg} + +
+
+ ) : null; +} diff --git a/app/client/src/git/components/GitOpsModal/TabDeploy/DiscardChangesWarning.tsx b/app/client/src/git/components/GitOpsModal/TabDeploy/DiscardChangesWarning.tsx new file mode 100644 index 000000000000..730a419655db --- /dev/null +++ b/app/client/src/git/components/GitOpsModal/TabDeploy/DiscardChangesWarning.tsx @@ -0,0 +1,43 @@ +import React from "react"; +import { + createMessage, + DISCARD_CHANGES_WARNING, + DISCARD_MESSAGE, +} from "ee/constants/messages"; +import { Callout, Text } from "@appsmith/ads"; +import styled from "styled-components"; + +const Container = styled.div` + margin: 8px 0 16px; +`; + +export default function DiscardChangesWarning({ + onCloseDiscardChangesWarning, // TODO: Fix this the next time the file is edited + // eslint-disable-next-line @typescript-eslint/no-explicit-any +}: any) { + const discardDocUrl = + "https://docs.appsmith.com/advanced-concepts/version-control-with-git/commit-and-push"; + + return ( + + + {createMessage(DISCARD_CHANGES_WARNING)} +
+ {createMessage(DISCARD_MESSAGE)} +
+
+ ); +} diff --git a/app/client/src/git/components/GitOpsModal/TabDeploy/DiscardFailedWarning.tsx b/app/client/src/git/components/GitOpsModal/TabDeploy/DiscardFailedWarning.tsx new file mode 100644 index 000000000000..d5397c625b32 --- /dev/null +++ b/app/client/src/git/components/GitOpsModal/TabDeploy/DiscardFailedWarning.tsx @@ -0,0 +1,30 @@ +import React from "react"; +import styled from "styled-components"; +import { Callout } from "@appsmith/ads"; +import type { CalloutProps } from "@appsmith/ads"; + +const Container = styled.div` + margin: 8px 0 16px; +`; + +export default function DiscardFailedWarning({ + closeHandler, + error, +}: { + closeHandler: () => void; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + error: any; +}) { + const calloutOptions: CalloutProps = { + isClosable: true, + kind: "error", + onClose: () => closeHandler(), + children: error?.message ?? "", + }; + + return ( + + + + ); +} diff --git a/app/client/src/git/components/GitOpsModal/TabDeploy/DumbTabDeploy.tsx b/app/client/src/git/components/GitOpsModal/TabDeploy/DumbTabDeploy.tsx new file mode 100644 index 000000000000..e512a515df90 --- /dev/null +++ b/app/client/src/git/components/GitOpsModal/TabDeploy/DumbTabDeploy.tsx @@ -0,0 +1,424 @@ +import React, { + useCallback, + useEffect, + useMemo, + useRef, + useState, +} from "react"; +import { + ARE_YOU_SURE, + CHANGES_SINCE_LAST_DEPLOYMENT, + COMMIT_AND_PUSH, + COMMIT_TO, + COMMITTING_AND_PUSHING_CHANGES, + createMessage, + DISCARD_CHANGES, + DISCARDING_AND_PULLING_CHANGES, + GIT_NO_UPDATED_TOOLTIP, + PULL_CHANGES, +} from "ee/constants/messages"; +import styled from "styled-components"; +import { + Button, + Input, + ModalBody, + ModalFooter, + Text, + Tooltip, +} from "@appsmith/ads"; +import DeployPreview from "./DeployPreview"; +import Statusbar, { + StatusbarWrapper, +} from "pages/Editor/gitSync/components/Statusbar"; + +import { isEllipsisActive } from "utils/helpers"; +import AnalyticsUtil from "ee/utils/AnalyticsUtil"; +import GIT_ERROR_CODES from "constants/GitErrorCodes"; +import DiscardChangesWarning from "./DiscardChangesWarning"; +import PushFailedWarning from "./PushFailedWarning"; +import DiscardFailedWarning from "./DiscardFailedWarning"; +import GitStatus from "git/components/GitStatus"; +import GitConflictError from "git/components/GitConflictError"; +import SubmitWrapper from "./SubmitWrapper"; +import UpstreamWarning from "./UpstreamWarning"; +import noop from "lodash/noop"; + +const Section = styled.div` + margin-top: 0; + margin-bottom: ${(props) => props.theme.spaces[7]}px; +`; + +const Row = styled.div` + display: flex; + align-items: center; +`; + +const StyledModalFooter = styled(ModalFooter)` + min-height: 52px; +`; + +const CommitLabelText = styled(Text)` + min-width: fit-content; +`; + +const CommitLabelBranchText = styled(Text)` + overflow: hidden; + textoverflow: ellipsis; + whitespace: nowrap; +`; + +const FIRST_COMMIT = "First Commit"; +const NO_CHANGES_TO_COMMIT = "No changes to commit"; + +interface DumbTabDeployProps { + clearCommitError: () => void; + clearDiscardError: () => void; + commit: (commitMessage: string) => void; + // ! case: improve error handling + // eslint-disable-next-line @typescript-eslint/no-explicit-any + commitError: any; + currentBranch: string | null; + discard: () => void; + discardError: string | null; + isCommitLoading: boolean; + isDiscardLoading: boolean; + isFetchStatusLoading: boolean; + isPullFailing: boolean; + isPullLoading: boolean; + lastDeployedAt: string | null; + pull: () => void; + remoteUrl: string | null; + statusBehindCount: number; + statusIsClean: boolean; +} + +function DumbTabDeploy({ + clearCommitError = noop, + clearDiscardError = noop, + commit = noop, + commitError = null, + currentBranch = null, + discard = noop, + discardError = null, + isCommitLoading = false, + isDiscardLoading = false, + isFetchStatusLoading = false, + isPullFailing = false, + isPullLoading = false, + lastDeployedAt = null, + pull = noop, + remoteUrl = null, + statusBehindCount = 0, + statusIsClean = false, +}: DumbTabDeployProps) { + const hasChangesToCommit = !statusIsClean; + const commitInputRef = useRef(null); + const [commitMessage, setCommitMessage] = useState( + remoteUrl && lastDeployedAt ? "" : FIRST_COMMIT, + ); + const [shouldDiscard, setShouldDiscard] = useState(false); + const [isDiscarding, setIsDiscarding] = useState(isDiscardLoading); + const [showDiscardWarning, setShowDiscardWarning] = useState(false); + + const commitButtonDisabled = + !hasChangesToCommit || !commitMessage || commitMessage.trim().length < 1; + const commitButtonLoading = isCommitLoading; + + const commitRequired = !statusIsClean; + const isConflicting = !isFetchStatusLoading && !!isPullFailing; + const commitInputDisabled = + isConflicting || !hasChangesToCommit || isCommitLoading || isDiscarding; + const pullRequired = + commitError?.code === + GIT_ERROR_CODES.PUSH_FAILED_REMOTE_COUNTERPART_IS_AHEAD; + + const showCommitButton = + !isConflicting && + !pullRequired && + !isFetchStatusLoading && + !isCommitLoading && + !isDiscarding; + + const isCommitting = + !!commitButtonLoading && + (commitRequired || showCommitButton) && + !isDiscarding; + + const showDiscardChangesButton = + !isFetchStatusLoading && + !isCommitLoading && + hasChangesToCommit && + !isDiscarding && + !isCommitting; + + const commitMessageDisplay = hasChangesToCommit + ? commitMessage + : NO_CHANGES_TO_COMMIT; + + const showPullButton = + !isFetchStatusLoading && + ((pullRequired && !isConflicting) || + (statusBehindCount > 0 && statusIsClean)); + + useEffect( + function focusCommitInputEffect() { + if (!commitInputDisabled && commitInputRef.current) { + commitInputRef.current.focus(); + } + }, + [commitInputDisabled], + ); + + useEffect( + function discardErrorChangeEffect() { + if (discardError) { + setIsDiscarding(false); + setShouldDiscard(false); + } + }, + [discardError], + ); + + const scrollWrapperRef = React.createRef(); + + useEffect( + function scrollContainerToTopEffect() { + if (scrollWrapperRef.current) { + setTimeout(() => { + const top = scrollWrapperRef.current?.scrollHeight || 0; + + scrollWrapperRef.current?.scrollTo({ + top: top, + }); + }, 100); + } + }, + [scrollWrapperRef], + ); + + const triggerCommit = useCallback(() => { + setShowDiscardWarning(false); + AnalyticsUtil.logEvent("GS_COMMIT_AND_PUSH_BUTTON_CLICK", { + source: "GIT_DEPLOY_MODAL", + }); + + if (currentBranch) { + commit(commitMessage.trim()); + } + }, [commit, commitMessage, currentBranch]); + + const handleCommitViaKeyPress = useCallback(() => { + if (!commitButtonDisabled) { + triggerCommit(); + } + }, [commitButtonDisabled, triggerCommit]); + + const triggerPull = useCallback(() => { + AnalyticsUtil.logEvent("GS_PULL_GIT_CLICK", { + source: "GIT_DEPLOY_MODAL", + }); + + if (currentBranch) { + pull(); + } + }, [currentBranch, pull]); + + const triggerDiscardInit = useCallback(() => { + AnalyticsUtil.logEvent("GIT_DISCARD_WARNING", { + source: "GIT_DISCARD_BUTTON_PRESS_1", + }); + setShowDiscardWarning(true); + setShouldDiscard(true); + clearDiscardError(); + }, [clearDiscardError]); + + const triggerDiscardChanges = useCallback(() => { + AnalyticsUtil.logEvent("GIT_DISCARD", { + source: "GIT_DISCARD_BUTTON_PRESS_2", + }); + discard(); + setShowDiscardWarning(false); + setShouldDiscard(true); + setIsDiscarding(true); + }, [discard]); + + const handleDiscardBtnClick = useCallback(() => { + if (shouldDiscard) { + triggerDiscardChanges(); + } else { + triggerDiscardInit(); + } + }, [shouldDiscard, triggerDiscardChanges, triggerDiscardInit]); + + const onCloseDiscardWarning = useCallback(() => { + AnalyticsUtil.logEvent("GIT_DISCARD_CANCEL", { + source: "GIT_DISCARD_WARNING_BANNER_CLOSE_CLICK", + }); + setShowDiscardWarning(false); + setShouldDiscard(false); + }, []); + + function handleCommitAndPushErrorClose() { + clearCommitError(); + } + + function handleDiscardErrorClose() { + clearDiscardError(); + } + + const inputLabel = useMemo( + () => ( + + {createMessage(COMMIT_TO)} + + +  {currentBranch} + + + + ), + [currentBranch], + ); + + return ( + <> + +
+
+ {hasChangesToCommit && ( + + {createMessage(CHANGES_SINCE_LAST_DEPLOYMENT)} + + )} + + + + + {/* // ! case: should be removed from here */} + {/* {isFetchStatusLoading && ( + + )} */} + {pullRequired && !isConflicting && } + {isConflicting && } + {commitError && ( + + )} + {isCommitting && !isDiscarding && ( + + + + )} + {isDiscarding && !isCommitting && ( + + + + )} +
+ + {discardError && ( + + )} + + {showDiscardWarning && ( + + )} + + {!pullRequired && !isConflicting && } +
+
+ + {showPullButton && ( + + )} + + {showDiscardChangesButton && ( + + )} + {showCommitButton && ( + + + + )} + + + ); +} + +export default DumbTabDeploy; diff --git a/app/client/src/git/components/GitOpsModal/TabDeploy/PushFailedWarning.tsx b/app/client/src/git/components/GitOpsModal/TabDeploy/PushFailedWarning.tsx new file mode 100644 index 000000000000..4be7ecd2c299 --- /dev/null +++ b/app/client/src/git/components/GitOpsModal/TabDeploy/PushFailedWarning.tsx @@ -0,0 +1,24 @@ +import { Callout } from "@appsmith/ads"; +import { Text, TextType } from "@appsmith/ads-old"; +import React from "react"; +import styled from "styled-components"; + +const Container = styled.div` + margin: 8px 0 16px; +`; + +// TODO: Fix this the next time the file is edited +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export default function PushFailedWarning({ closeHandler, error }: any) { + return ( + + + <> + {error.errorType} +
+ {error.message} + +
+
+ ); +} diff --git a/app/client/src/git/components/GitOpsModal/TabDeploy/SubmitWrapper.tsx b/app/client/src/git/components/GitOpsModal/TabDeploy/SubmitWrapper.tsx new file mode 100644 index 000000000000..93e98dbdb36e --- /dev/null +++ b/app/client/src/git/components/GitOpsModal/TabDeploy/SubmitWrapper.tsx @@ -0,0 +1,26 @@ +import noop from "lodash/noop"; +import React, { useCallback } from "react"; +import { isMacOrIOS } from "utils/helpers"; + +interface SubmitWrapperProps { + children: React.ReactNode; + onSubmit: () => void; +} + +export default function SubmitWrapper({ + children = null, + onSubmit = noop, +}: SubmitWrapperProps) { + const onKeyDown = useCallback( + (e: React.KeyboardEvent) => { + const triggerSubmit = isMacOrIOS() + ? e.metaKey && e.key === "Enter" + : e.ctrlKey && e.key === "Enter"; + + if (triggerSubmit) onSubmit(); + }, + [onSubmit], + ); + + return
{children}
; +} diff --git a/app/client/src/git/components/GitOpsModal/TabDeploy/UpstreamWarning.tsx b/app/client/src/git/components/GitOpsModal/TabDeploy/UpstreamWarning.tsx new file mode 100644 index 000000000000..61d5e1244316 --- /dev/null +++ b/app/client/src/git/components/GitOpsModal/TabDeploy/UpstreamWarning.tsx @@ -0,0 +1,33 @@ +import React from "react"; + +import { Callout } from "@appsmith/ads"; +import AnalyticsUtil from "ee/utils/AnalyticsUtil"; +import { + createMessage, + GIT_UPSTREAM_CHANGES, + READ_DOCUMENTATION, +} from "ee/constants/messages"; + +export default function UpstreamWarning() { + return ( + { + AnalyticsUtil.logEvent("GS_GIT_DOCUMENTATION_LINK_CLICK", { + source: "UPSTREAM_CHANGES_LINK_ON_GIT_DEPLOY_MODAL", + }); + }, + // ! case: should be a constant + to: "https://docs.appsmith.com/advanced-concepts/version-control-with-git", + target: "_blank", + }, + ]} + style={{ marginBottom: 12 }} + > + {createMessage(GIT_UPSTREAM_CHANGES)} + + ); +} diff --git a/app/client/src/git/components/GitOpsModal/TabDeploy/index.tsx b/app/client/src/git/components/GitOpsModal/TabDeploy/index.tsx index b83625c1a443..f6b13f6b9997 100644 --- a/app/client/src/git/components/GitOpsModal/TabDeploy/index.tsx +++ b/app/client/src/git/components/GitOpsModal/TabDeploy/index.tsx @@ -1,5 +1,52 @@ import React from "react"; +import DumbTabDeploy from "./DumbTabDeploy"; +import { useGitContext } from "git/components/GitContextProvider"; export default function TabDeploy() { - return
Test
; + const { + artifact, + clearCommitError, + clearDiscardError, + commit, + commitError, + commitLoading, + currentBranch, + discard, + discardError, + discardLoading, + fetchStatusLoading, + gitMetadata, + pull, + pullError, + pullLoading, + status, + } = useGitContext(); + + const lastDeployedAt = artifact?.lastDeployedAt ?? null; + const isPullFailing = !!pullError; + const statusIsClean = status?.isClean ?? false; + const statusBehindCount = status?.behindCount ?? 0; + const remoteUrl = gitMetadata?.remoteUrl ?? ""; + + return ( + + ); } diff --git a/app/client/src/git/components/GitStatus/StatusLoader.tsx b/app/client/src/git/components/GitStatus/StatusLoader.tsx new file mode 100644 index 000000000000..bc0427bd6521 --- /dev/null +++ b/app/client/src/git/components/GitStatus/StatusLoader.tsx @@ -0,0 +1,23 @@ +import React from "react"; +import styled from "styled-components"; +import { Spinner, Text } from "@appsmith/ads"; + +const LoaderWrapper = styled.div` + display: flex; + flex-direction: row; + align-items: center; + margin-top: ${(props) => `${props.theme.spaces[3]}px`}; +`; + +function StatusLoader({ loaderMsg }: { loaderMsg: string }) { + return ( + + + + {loaderMsg} + + + ); +} + +export default StatusLoader; diff --git a/app/client/src/git/components/GitStatus/index.tsx b/app/client/src/git/components/GitStatus/index.tsx new file mode 100644 index 000000000000..79b38815fa5f --- /dev/null +++ b/app/client/src/git/components/GitStatus/index.tsx @@ -0,0 +1,7 @@ +import React from "react"; + +function GitStatus() { + return
GitStatus
; +} + +export default GitStatus; diff --git a/app/client/src/git/store/actions/commitActions.ts b/app/client/src/git/store/actions/commitActions.ts index 24c5b17267f4..9ebb8d37db60 100644 --- a/app/client/src/git/store/actions/commitActions.ts +++ b/app/client/src/git/store/actions/commitActions.ts @@ -28,3 +28,9 @@ export const commitErrorAction = return state; }); + +export const clearCommitErrorAction = createSingleArtifactAction((state) => { + state.apiResponses.commit.error = null; + + return state; +}); diff --git a/app/client/src/git/store/actions/discardActions.ts b/app/client/src/git/store/actions/discardActions.ts index c12b236f06ef..35d37c0a6d0e 100644 --- a/app/client/src/git/store/actions/discardActions.ts +++ b/app/client/src/git/store/actions/discardActions.ts @@ -24,3 +24,9 @@ export const discardErrorAction = createSingleArtifactAction( return state; }, ); + +export const clearDiscardErrorAction = createSingleArtifactAction((state) => { + state.apiResponses.discard.error = null; + + return state; +}); diff --git a/app/client/src/git/store/gitArtifactSlice.ts b/app/client/src/git/store/gitArtifactSlice.ts index 2da393f49e04..5d15d23c0c9b 100644 --- a/app/client/src/git/store/gitArtifactSlice.ts +++ b/app/client/src/git/store/gitArtifactSlice.ts @@ -23,6 +23,7 @@ import { fetchStatusSuccessAction, } from "./actions/fetchStatusActions"; import { + clearCommitErrorAction, commitErrorAction, commitInitAction, commitSuccessAction, @@ -66,6 +67,7 @@ import { checkoutBranchSuccessAction, } from "./actions/checkoutBranchActions"; import { + clearDiscardErrorAction, discardErrorAction, discardInitAction, discardSuccessAction, @@ -135,9 +137,11 @@ export const gitArtifactSlice = createSlice({ commitInit: commitInitAction, commitSuccess: commitSuccessAction, commitError: commitErrorAction, + clearCommitError: clearCommitErrorAction, discardInit: discardInitAction, discardSuccess: discardSuccessAction, discardError: discardErrorAction, + clearDiscardError: clearDiscardErrorAction, fetchStatusInit: fetchStatusInitAction, fetchStatusSuccess: fetchStatusSuccessAction, fetchStatusError: fetchStatusErrorAction, From 0e84fb81e38a3d9db498a9f716b87234255ab8a4 Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Thu, 12 Dec 2024 03:54:40 +0800 Subject: [PATCH 034/143] chore: adding merge tab --- .../GitContextProvider/hooks/useGitOps.ts | 22 +- .../GitOpsModal/DumbGitOpsModal.tsx | 13 +- .../GitOpsModal/TabMerge/DumbTabMerge.tsx | 328 ++++++++++++++++++ .../GitOpsModal/TabMerge/MergeStatus.tsx | 77 ++++ .../TabMerge/MergeSuccessIndicator.tsx | 21 ++ .../components/GitOpsModal/TabMerge/index.tsx | 45 ++- .../src/git/components/GitOpsModal/index.tsx | 2 + app/client/src/git/constants/enums.ts | 10 +- .../fetchAutocommitProgressRequest.types.ts | 4 +- .../requests/fetchMergeStatusRequest.types.ts | 1 + .../triggerAutocommitRequest.types.ts | 4 +- .../src/git/sagas/fetchMergeStatusSaga.ts | 44 +++ app/client/src/git/sagas/index.ts | 4 + .../src/git/sagas/triggerAutocommitSaga.ts | 11 +- .../store/actions/fetchMergeStatusActions.ts | 25 +- app/client/src/git/store/gitArtifactSlice.ts | 2 + 16 files changed, 594 insertions(+), 19 deletions(-) create mode 100644 app/client/src/git/components/GitOpsModal/TabMerge/DumbTabMerge.tsx create mode 100644 app/client/src/git/components/GitOpsModal/TabMerge/MergeStatus.tsx create mode 100644 app/client/src/git/components/GitOpsModal/TabMerge/MergeSuccessIndicator.tsx create mode 100644 app/client/src/git/sagas/fetchMergeStatusSaga.ts diff --git a/app/client/src/git/components/GitContextProvider/hooks/useGitOps.ts b/app/client/src/git/components/GitContextProvider/hooks/useGitOps.ts index c14761087505..9bb9daf59d1c 100644 --- a/app/client/src/git/components/GitContextProvider/hooks/useGitOps.ts +++ b/app/client/src/git/components/GitContextProvider/hooks/useGitOps.ts @@ -42,7 +42,8 @@ export interface UseGitOpsReturnValue { mergeStatus: FetchMergeStatusResponseData | null; fetchMergeStatusLoading: boolean; fetchMergeStatusError: string | null; - fetchMergeStatus: () => void; + fetchMergeStatus: (sourceBranch: string, destinationBranch: string) => void; + clearMergeStatus: () => void; pullLoading: boolean; pullError: string | null; pull: () => void; @@ -127,8 +128,22 @@ export default function useGitOps({ selectMergeStatus(state, basePayload), ); - const fetchMergeStatus = useCallback(() => { - dispatch(gitArtifactActions.fetchMergeStatusInit(basePayload)); + const fetchMergeStatus = useCallback( + (sourceBranch: string, destinationBranch: string) => { + dispatch( + gitArtifactActions.fetchMergeStatusInit({ + ...basePayload, + artifactId: artifactId ?? "", + sourceBranch, + destinationBranch, + }), + ); + }, + [artifactId, basePayload, dispatch], + ); + + const clearMergeStatus = useCallback(() => { + dispatch(gitArtifactActions.clearMergeStatus(basePayload)); }, [basePayload, dispatch]); // pull @@ -197,6 +212,7 @@ export default function useGitOps({ fetchMergeStatusLoading: mergeStatusState?.loading ?? false, fetchMergeStatusError: mergeStatusState?.error, fetchMergeStatus, + clearMergeStatus, pullLoading: pullState?.loading ?? false, pullError: pullState?.error, pull, diff --git a/app/client/src/git/components/GitOpsModal/DumbGitOpsModal.tsx b/app/client/src/git/components/GitOpsModal/DumbGitOpsModal.tsx index 039ab835d204..0c7e28762b67 100644 --- a/app/client/src/git/components/GitOpsModal/DumbGitOpsModal.tsx +++ b/app/client/src/git/components/GitOpsModal/DumbGitOpsModal.tsx @@ -1,4 +1,4 @@ -import React, { useCallback } from "react"; +import React, { useCallback, useEffect } from "react"; import TabDeploy from "./TabDeploy"; import TabMerge from "./TabMerge"; import { createMessage, DEPLOY, MERGE } from "ee/constants/messages"; @@ -27,6 +27,7 @@ const StyledModalContent = styled(ModalContent)` `; interface DumbGitOpsModalProps { + fetchStatus: () => void; isOpsModalOpen: boolean; isProtectedMode: boolean; opsModalTab: keyof typeof GitOpsTab; @@ -35,12 +36,22 @@ interface DumbGitOpsModalProps { } function DumbGitOpsModal({ + fetchStatus = noop, isOpsModalOpen = false, isProtectedMode = false, opsModalTab = GitOpsTab.Deploy, repoName = null, toggleOpsModal = noop, }: DumbGitOpsModalProps) { + useEffect( + function fetchStatusOnMountEffect() { + if (isOpsModalOpen) { + fetchStatus(); + } + }, + [isOpsModalOpen, fetchStatus], + ); + const handleTabKeyChange = useCallback( (tabKey: string) => { if (tabKey === GitOpsTab.Deploy) { diff --git a/app/client/src/git/components/GitOpsModal/TabMerge/DumbTabMerge.tsx b/app/client/src/git/components/GitOpsModal/TabMerge/DumbTabMerge.tsx new file mode 100644 index 000000000000..9e77e3fc9afd --- /dev/null +++ b/app/client/src/git/components/GitOpsModal/TabMerge/DumbTabMerge.tsx @@ -0,0 +1,328 @@ +import React, { useCallback, useEffect, useMemo, useState } from "react"; + +import { + BRANCH_PROTECTION_PROTECTED, + CANNOT_MERGE_DUE_TO_UNCOMMITTED_CHANGES, + createMessage, + FETCH_GIT_STATUS, + FETCH_MERGE_STATUS, + IS_MERGING, + MERGE_CHANGES, + SELECT_BRANCH_TO_MERGE, +} from "ee/constants/messages"; + +import styled from "styled-components"; +import Statusbar, { + StatusbarWrapper, +} from "pages/Editor/gitSync/components/Statusbar"; +import { getIsStartingWithRemoteBranches } from "pages/Editor/gitSync/utils"; +import { + Button, + Option, + Select, + Text, + Icon, + ModalFooter, + ModalBody, +} from "@appsmith/ads"; +import AnalyticsUtil from "ee/utils/AnalyticsUtil"; +import { Space } from "pages/Editor/gitSync/components/StyledComponents"; +import { MergeStatusState } from "git/constants/enums"; +import MergeStatus from "./MergeStatus"; +import GitConflictError from "git/components/GitConflictError"; +import MergeSuccessIndicator from "./MergeSuccessIndicator"; +import { noop } from "lodash"; +import type { FetchBranchesResponseData } from "git/requests/fetchBranchesRequest.types"; +import type { FetchProtectedBranchesResponseData } from "git/requests/fetchProtectedBranchesRequest.types"; + +const Container = styled.div` + min-height: 360px; + overflow: unset; + padding-bottom: 4px; +`; + +const SelectContainer = styled.div` + display: flex; + align-items: center; + overflow: unset; + padding-bottom: 4px; +`; + +const StyledModalFooter = styled(ModalFooter)` + min-height: 52px; +`; + +interface BranchOption { + label: string; + value: string; +} + +interface DumbTabMergeProps { + branches: FetchBranchesResponseData | null; + clearMergeStatus: () => void; + currentBranch: string | null; + fetchBranches: () => void; + fetchMergeStatus: (sourceBranch: string, destinationBranch: string) => void; + isFetchBranchesLoading: boolean; + isFetchMergeStatusLoading: boolean; + isFetchStatusLoading: boolean; + isMergeLoading: boolean; + isMergeStatusMergeable: boolean; + isStatusClean: boolean; + merge: (sourceBranch: string, destinationBranch: string) => void; + // ! case: should add proper type + // eslint-disable-next-line @typescript-eslint/no-explicit-any + mergeError: any; + mergeStatusConflictingFiles: string[] | null; + mergeStatusMessage: string | null; + protectedBranches: FetchProtectedBranchesResponseData | null; +} + +export default function DumbTabMerge({ + branches = null, + clearMergeStatus = noop, + currentBranch = null, + fetchBranches = noop, + fetchMergeStatus = noop, + isFetchBranchesLoading = false, + isFetchMergeStatusLoading = false, + isFetchStatusLoading = false, + isMergeLoading = false, + isMergeStatusMergeable = false, + isStatusClean = false, + merge = noop, + mergeError = null, + mergeStatusConflictingFiles = null, + mergeStatusMessage = null, + protectedBranches = null, +}: DumbTabMergeProps) { + const [showMergeSuccessIndicator, setShowMergeSuccessIndicator] = + useState(false); + const [selectedBranchOption, setSelectedBranchOption] = + useState(); + + const isMergeable = isMergeStatusMergeable && isStatusClean; + let message = !isStatusClean + ? createMessage(CANNOT_MERGE_DUE_TO_UNCOMMITTED_CHANGES) + : mergeStatusMessage; + + const mergeBtnDisabled = isFetchMergeStatusLoading || !isMergeable; + + let status = MergeStatusState.NONE; + + if (isFetchStatusLoading) { + status = MergeStatusState.FETCHING; + message = createMessage(FETCH_GIT_STATUS); + } else if (!isStatusClean) { + status = MergeStatusState.NOT_MERGEABLE; + } else if (isFetchMergeStatusLoading) { + status = MergeStatusState.FETCHING; + message = createMessage(FETCH_MERGE_STATUS); + } else if (isMergeStatusMergeable) { + status = MergeStatusState.MERGEABLE; + } else if (!isMergeStatusMergeable) { + status = MergeStatusState.NOT_MERGEABLE; + } else if (mergeError) { + status = MergeStatusState.ERROR; + message = mergeError.error.message; + } + + // should check after added error code for conflicting + const isConflicting = (mergeStatusConflictingFiles?.length || 0) > 0; + const showMergeButton = + !isConflicting && !mergeError && !isFetchStatusLoading && !isMergeLoading; + + const branchList = useMemo(() => { + const branchOptions = [] as BranchOption[]; + + if (!branches) return branchOptions; + + let index = 0; + + while (true) { + if (index === branches.length) break; + + const branchObj = branches[index]; + + if (currentBranch !== branchObj.branchName) { + if (!branchObj.default) { + branchOptions.push({ + label: branchObj.branchName, + value: branchObj.branchName, + }); + } else { + branchOptions.unshift({ + label: branchObj.branchName, + value: branchObj.branchName, + }); + } + } + + const nextBranchObj = branches[index + 1]; + + if ( + getIsStartingWithRemoteBranches( + branchObj.branchName, + nextBranchObj?.branchName, + ) + ) { + break; + } + + index++; + } + + return branchOptions; + }, [branches, currentBranch]); + + const currentBranchDropdownOptions = useMemo( + () => [ + { + label: currentBranch || "", + value: currentBranch || "", + }, + ], + [currentBranch], + ); + + // ! case how to do this + // const handleMergeSuccess = () => { + // setShowMergeSuccessIndicator(true); + // }; + + useEffect( + function fetchBranchesOnMountffect() { + fetchBranches(); + }, + [fetchBranches], + ); + + useEffect( + function clearMergeStatusOnUnmountEffect() { + return () => { + clearMergeStatus(); + }; + }, + [clearMergeStatus], + ); + + useEffect( + function fetchMergeStatusOnChangeEffect() { + // when user selects a branch to merge + if (currentBranch && selectedBranchOption?.value) { + fetchMergeStatus(currentBranch, selectedBranchOption?.value); + setShowMergeSuccessIndicator(false); + } + }, + [currentBranch, selectedBranchOption?.value, fetchMergeStatus], + ); + + const handleMergeBtnClick = useCallback(() => { + AnalyticsUtil.logEvent("GS_MERGE_CHANGES_BUTTON_CLICK", { + source: "GIT_MERGE_MODAL", + }); + + if (currentBranch && selectedBranchOption?.value) { + merge(currentBranch, selectedBranchOption?.value); + } + }, [currentBranch, merge, selectedBranchOption?.value]); + + const handleSelectBranchOption = useCallback((value?: string) => { + if (value) setSelectedBranchOption({ label: value, value: value }); + }, []); + + const handleGetPopupContainer = useCallback((triggerNode) => { + return triggerNode.parentNode; + }, []); + + return ( + <> + + + + {createMessage(SELECT_BRANCH_TO_MERGE)} + + + + + + + + + + + + + {isConflicting ? : null} + + {showMergeSuccessIndicator ? : null} + {isMergeLoading ? ( + + + + ) : null} + + + + {!showMergeSuccessIndicator && showMergeButton ? ( + + ) : null} + + + ); +} diff --git a/app/client/src/git/components/GitOpsModal/TabMerge/MergeStatus.tsx b/app/client/src/git/components/GitOpsModal/TabMerge/MergeStatus.tsx new file mode 100644 index 000000000000..1970332600ed --- /dev/null +++ b/app/client/src/git/components/GitOpsModal/TabMerge/MergeStatus.tsx @@ -0,0 +1,77 @@ +import React from "react"; +import styled from "styled-components"; +import { Icon, Spinner, Text } from "@appsmith/ads"; +import { MergeStatusState } from "git/constants/enums"; + +const LoaderWrapper = styled.div` + display: flex; + flex-direction: row; + align-items: center; + margin-top: ${(props) => `${props.theme.spaces[3]}px`}; +`; + +const Flex = styled.div` + display: flex; +`; + +const Wrapper = styled.div` + display: flex; + flex-direction: row; + margin-top: ${(props) => `${props.theme.spaces[3]}px`}; + width: 45%; + align-items: flex-start; + gap: 5px; + .ads-v2-icon { + margin-top: 3px; + } +`; + +function MergeStatus({ + message = "", + status, +}: { + status: string; + message: string | null; +}) { + switch (status) { + case MergeStatusState.FETCHING: + return ( + + + + {message} + + + ); + case MergeStatusState.MERGEABLE: + return ( + + + + {message} + + + + ); + case MergeStatusState.NOT_MERGEABLE: + case MergeStatusState.ERROR: + return ( + + + + + {message} + + + + ); + default: + return null; + } +} + +export default MergeStatus; diff --git a/app/client/src/git/components/GitOpsModal/TabMerge/MergeSuccessIndicator.tsx b/app/client/src/git/components/GitOpsModal/TabMerge/MergeSuccessIndicator.tsx new file mode 100644 index 000000000000..2515513c0fa9 --- /dev/null +++ b/app/client/src/git/components/GitOpsModal/TabMerge/MergeSuccessIndicator.tsx @@ -0,0 +1,21 @@ +import { Text } from "@appsmith/ads"; +import { createMessage, MERGED_SUCCESSFULLY } from "ee/constants/messages"; +import React from "react"; + +// internal dependencies +import SuccessTick from "pages/common/SuccessTick"; + +export default function MergeSuccessIndicator() { + return ( +
+ + + {createMessage(MERGED_SUCCESSFULLY)} + +
+ ); +} diff --git a/app/client/src/git/components/GitOpsModal/TabMerge/index.tsx b/app/client/src/git/components/GitOpsModal/TabMerge/index.tsx index c22f248bf400..101b137d3455 100644 --- a/app/client/src/git/components/GitOpsModal/TabMerge/index.tsx +++ b/app/client/src/git/components/GitOpsModal/TabMerge/index.tsx @@ -1,5 +1,48 @@ import React from "react"; +import DumbTabMerge from "./DumbTabMerge"; +import { useGitContext } from "git/components/GitContextProvider"; export default function TabMerge() { - return
Test
; + const { + branches, + clearMergeStatus, + currentBranch, + fetchBranches, + fetchBranchesLoading, + fetchMergeStatus, + fetchMergeStatusLoading, + fetchStatusLoading, + merge, + mergeError, + mergeLoading, + mergeStatus, + protectedBranches, + status, + } = useGitContext(); + + const isStatusClean = status?.isClean ?? false; + const isMergeStatusMergeable = mergeStatus?.isMergeAble ?? false; + const mergeStatusConflictingFiles = mergeStatus?.conflictingFiles ?? null; + const mergeStatusMessage = mergeStatus?.message ?? null; + + return ( + + ); } diff --git a/app/client/src/git/components/GitOpsModal/index.tsx b/app/client/src/git/components/GitOpsModal/index.tsx index 9820aec6656a..e1fa2feddb96 100644 --- a/app/client/src/git/components/GitOpsModal/index.tsx +++ b/app/client/src/git/components/GitOpsModal/index.tsx @@ -4,6 +4,7 @@ import { useGitContext } from "../GitContextProvider"; export default function GitOpsModal() { const { + fetchStatus, gitMetadata, opsModalOpen, opsModalTab, @@ -15,6 +16,7 @@ export default function GitOpsModal() { return ( , +) { + const { artifactId, artifactType, baseArtifactId } = action.payload; + const basePayload = { artifactType, baseArtifactId }; + let response: FetchMergeStatusResponse | undefined; + + try { + const params: FetchMergeStatusRequestParams = { + destinationBranch: action.payload.destinationBranch, + sourceBranch: action.payload.sourceBranch, + }; + + response = yield call(fetchMergeStatusRequest, artifactId, params); + const isValidResponse: boolean = yield validateResponse(response); + + if (response && isValidResponse) { + yield put( + gitArtifactActions.fetchMergeStatusSuccess({ + ...basePayload, + responseData: response.data, + }), + ); + } + } catch (error) { + yield put( + gitArtifactActions.fetchMergeStatusError({ + ...basePayload, + error: error as string, + }), + ); + } +} diff --git a/app/client/src/git/sagas/index.ts b/app/client/src/git/sagas/index.ts index 60108c4d068b..acb2111a7520 100644 --- a/app/client/src/git/sagas/index.ts +++ b/app/client/src/git/sagas/index.ts @@ -22,6 +22,8 @@ import fetchGitMetadataSaga from "./fetchGitMetadataSaga"; import triggerAutocommitSaga from "./triggerAutocommitSaga"; import fetchStatusSaga from "./fetchStatusSaga"; import fetchProtectedBranchesSaga from "./fetchProtectedBranchesSaga"; +import pullSaga from "./pullSaga"; +import fetchMergeStatusSaga from "./fetchMergeStatusSaga"; const gitRequestBlockingActions: Record< string, @@ -37,6 +39,8 @@ const gitRequestBlockingActions: Record< // ops [gitArtifactActions.commitInit.type]: commitSaga, [gitArtifactActions.fetchStatusInit.type]: fetchStatusSaga, + [gitArtifactActions.pullInit.type]: pullSaga, + [gitArtifactActions.fetchMergeStatusInit.type]: fetchMergeStatusSaga, // branches [gitArtifactActions.fetchBranchesInit.type]: fetchBranchesSaga, diff --git a/app/client/src/git/sagas/triggerAutocommitSaga.ts b/app/client/src/git/sagas/triggerAutocommitSaga.ts index fb4c6185406b..94561dd7b49d 100644 --- a/app/client/src/git/sagas/triggerAutocommitSaga.ts +++ b/app/client/src/git/sagas/triggerAutocommitSaga.ts @@ -1,5 +1,8 @@ import { triggerAutocommitSuccessAction } from "actions/gitSyncActions"; -import { AutocommitStatus, type GitArtifactType } from "git/constants/enums"; +import { + AutocommitStatusState, + type GitArtifactType, +} from "git/constants/enums"; import fetchAutocommitProgressRequest from "git/requests/fetchAutocommitProgressRequest"; import type { FetchAutocommitProgressResponse, @@ -40,9 +43,9 @@ function isAutocommitHappening( ): boolean { return ( !!responseData && - (responseData.autoCommitResponse === AutocommitStatus.PUBLISHED || - responseData.autoCommitResponse === AutocommitStatus.IN_PROGRESS || - responseData.autoCommitResponse === AutocommitStatus.LOCKED) + (responseData.autoCommitResponse === AutocommitStatusState.PUBLISHED || + responseData.autoCommitResponse === AutocommitStatusState.IN_PROGRESS || + responseData.autoCommitResponse === AutocommitStatusState.LOCKED) ); } diff --git a/app/client/src/git/store/actions/fetchMergeStatusActions.ts b/app/client/src/git/store/actions/fetchMergeStatusActions.ts index 71ae8fccf107..65ed313114cb 100644 --- a/app/client/src/git/store/actions/fetchMergeStatusActions.ts +++ b/app/client/src/git/store/actions/fetchMergeStatusActions.ts @@ -1,15 +1,22 @@ import type { GitAsyncSuccessPayload, GitAsyncErrorPayload } from "../types"; import { createSingleArtifactAction } from "../helpers/createSingleArtifactAction"; -import type { FetchMergeStatusResponseData } from "git/requests/fetchMergeStatusRequest.types"; +import type { + FetchMergeStatusRequestParams, + FetchMergeStatusResponseData, +} from "git/requests/fetchMergeStatusRequest.types"; -export const fetchMergeStatusInitAction = createSingleArtifactAction( - (state) => { +export interface FetchMergeStatusInitPayload + extends FetchMergeStatusRequestParams { + artifactId: string; +} + +export const fetchMergeStatusInitAction = + createSingleArtifactAction((state) => { state.apiResponses.mergeStatus.loading = true; state.apiResponses.mergeStatus.error = null; return state; - }, -); + }); export const fetchMergeStatusSuccessAction = createSingleArtifactAction< GitAsyncSuccessPayload @@ -29,3 +36,11 @@ export const fetchMergeStatusErrorAction = return state; }); + +export const clearMergeStatusAction = createSingleArtifactAction((state) => { + state.apiResponses.mergeStatus.loading = false; + state.apiResponses.mergeStatus.error = null; + state.apiResponses.mergeStatus.value = null; + + return state; +}); diff --git a/app/client/src/git/store/gitArtifactSlice.ts b/app/client/src/git/store/gitArtifactSlice.ts index 5d15d23c0c9b..16aa5d6d4162 100644 --- a/app/client/src/git/store/gitArtifactSlice.ts +++ b/app/client/src/git/store/gitArtifactSlice.ts @@ -73,6 +73,7 @@ import { discardSuccessAction, } from "./actions/discardActions"; import { + clearMergeStatusAction, fetchMergeStatusErrorAction, fetchMergeStatusInitAction, fetchMergeStatusSuccessAction, @@ -148,6 +149,7 @@ export const gitArtifactSlice = createSlice({ fetchMergeStatusInit: fetchMergeStatusInitAction, fetchMergeStatusSuccess: fetchMergeStatusSuccessAction, fetchMergeStatusError: fetchMergeStatusErrorAction, + clearMergeStatus: clearMergeStatusAction, mergeInit: mergeInitAction, mergeSuccess: mergeSuccessAction, mergeError: mergeErrorAction, From c88bc0bcc0d85ebd251b2875774e9d4f0f4b06ed Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Thu, 12 Dec 2024 17:57:07 +0800 Subject: [PATCH 035/143] fix: review changes --- .../fetchAutocommitProgressRequest.types.ts | 2 +- .../git/requests/triggerAutocommitRequest.types.ts | 2 +- app/client/src/git/sagas/triggerAutocommitSaga.ts | 13 +++++++++---- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/app/client/src/git/requests/fetchAutocommitProgressRequest.types.ts b/app/client/src/git/requests/fetchAutocommitProgressRequest.types.ts index 3745c107dd22..e59d7a64d547 100644 --- a/app/client/src/git/requests/fetchAutocommitProgressRequest.types.ts +++ b/app/client/src/git/requests/fetchAutocommitProgressRequest.types.ts @@ -2,7 +2,7 @@ import type { ApiResponse } from "api/types"; import type { AutocommitStatus } from "../constants/enums"; export interface FetchAutocommitProgressResponseData { - autoCommitResponse: keyof typeof AutocommitStatus; + autoCommitResponse: AutocommitStatus; progress: number; branchName: string; } diff --git a/app/client/src/git/requests/triggerAutocommitRequest.types.ts b/app/client/src/git/requests/triggerAutocommitRequest.types.ts index cbb28d3610f8..7a3959478280 100644 --- a/app/client/src/git/requests/triggerAutocommitRequest.types.ts +++ b/app/client/src/git/requests/triggerAutocommitRequest.types.ts @@ -2,7 +2,7 @@ import type { ApiResponse } from "api/types"; import type { AutocommitStatus } from "../constants/enums"; export interface TriggerAutocommitResponseData { - autoCommitResponse: keyof typeof AutocommitStatus; + autoCommitResponse: AutocommitStatus; progress: number; branchName: string; } diff --git a/app/client/src/git/sagas/triggerAutocommitSaga.ts b/app/client/src/git/sagas/triggerAutocommitSaga.ts index fb4c6185406b..ac50a6b03c08 100644 --- a/app/client/src/git/sagas/triggerAutocommitSaga.ts +++ b/app/client/src/git/sagas/triggerAutocommitSaga.ts @@ -26,6 +26,13 @@ import { import type { Task } from "redux-saga"; import { validateResponse } from "sagas/ErrorSagas"; +const AUTOCOMMIT_POLL_DELAY = 1000; +const AUTOCOMMIT_WHITELISTED_STATES = [ + AutocommitStatus.PUBLISHED, + AutocommitStatus.IN_PROGRESS, + AutocommitStatus.LOCKED, +]; + interface PollAutocommitProgressParams { artifactType: keyof typeof GitArtifactType; baseArtifactId: string; @@ -40,9 +47,7 @@ function isAutocommitHappening( ): boolean { return ( !!responseData && - (responseData.autoCommitResponse === AutocommitStatus.PUBLISHED || - responseData.autoCommitResponse === AutocommitStatus.IN_PROGRESS || - responseData.autoCommitResponse === AutocommitStatus.LOCKED) + AUTOCOMMIT_WHITELISTED_STATES.includes(responseData.autoCommitResponse) ); } @@ -88,7 +93,7 @@ function* pollAutocommitProgressSaga(params: PollAutocommitProgressParams) { yield put(gitArtifactActions.pollAutocommitProgressStop(basePayload)); } - yield delay(1000); + yield delay(AUTOCOMMIT_POLL_DELAY); } } else { yield put(gitArtifactActions.pollAutocommitProgressStop(basePayload)); From e106d43ae668b27bb05948de6fa2b44080dcdbd0 Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Thu, 12 Dec 2024 18:22:54 +0800 Subject: [PATCH 036/143] fix: better handling of ctx values --- .../components/GitContextProvider/hooks/useGitConnect.ts | 4 ---- .../GitContextProvider/hooks/useGitContextValue.ts | 8 ++++---- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/app/client/src/git/components/GitContextProvider/hooks/useGitConnect.ts b/app/client/src/git/components/GitContextProvider/hooks/useGitConnect.ts index 4f7c5ffc395b..9741a857e7a3 100644 --- a/app/client/src/git/components/GitContextProvider/hooks/useGitConnect.ts +++ b/app/client/src/git/components/GitContextProvider/hooks/useGitConnect.ts @@ -6,18 +6,15 @@ import { useDispatch } from "react-redux"; interface UseGitConnectParams { artifactType: keyof typeof GitArtifactType; baseArtifactId: string; - connectPermitted: boolean; } export interface UseGitConnectReturnValue { toggleConnectModal: (open: boolean) => void; - connectPermitted: boolean; } export default function useGitConnect({ artifactType, baseArtifactId, - connectPermitted, }: UseGitConnectParams): UseGitConnectReturnValue { const dispatch = useDispatch(); const basePayload = useMemo( @@ -36,6 +33,5 @@ export default function useGitConnect({ return { toggleConnectModal, - connectPermitted, }; } diff --git a/app/client/src/git/components/GitContextProvider/hooks/useGitContextValue.ts b/app/client/src/git/components/GitContextProvider/hooks/useGitContextValue.ts index 2fb0d0666e46..7bb86e652263 100644 --- a/app/client/src/git/components/GitContextProvider/hooks/useGitContextValue.ts +++ b/app/client/src/git/components/GitContextProvider/hooks/useGitContextValue.ts @@ -28,6 +28,7 @@ export interface GitContextValue UseGitSettingsReturnValue, UseGitBranchesReturnValue { artifact: ApplicationPayload | null; + connectPermitted: boolean; } export default function useGitContextValue({ @@ -40,11 +41,9 @@ export default function useGitContextValue({ () => ({ artifactType, baseArtifactId }), [artifactType, baseArtifactId], ); + const useGitMetadataReturnValue = useGitMetadata(basePayload); - const useGitConnectReturnValue = useGitConnect({ - ...basePayload, - connectPermitted, - }); + const useGitConnectReturnValue = useGitConnect(basePayload); const useGitOpsReturnValue = useGitOps({ ...basePayload, artifactId: artifact?.id ?? null, @@ -54,6 +53,7 @@ export default function useGitContextValue({ return { artifact, + connectPermitted, ...useGitMetadataReturnValue, ...useGitOpsReturnValue, ...useGitBranchesReturnValue, From 005a655b799a10c2564304bf5ada47acbed8d8ad Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Thu, 12 Dec 2024 19:06:38 +0800 Subject: [PATCH 037/143] fix: minor fixes to merge comp --- .../GitOpsModal/TabMerge/DumbTabMerge.tsx | 42 +++++++++---------- .../components/GitOpsModal/TabMerge/index.tsx | 7 +--- 2 files changed, 21 insertions(+), 28 deletions(-) diff --git a/app/client/src/git/components/GitOpsModal/TabMerge/DumbTabMerge.tsx b/app/client/src/git/components/GitOpsModal/TabMerge/DumbTabMerge.tsx index 9e77e3fc9afd..ecaa99775405 100644 --- a/app/client/src/git/components/GitOpsModal/TabMerge/DumbTabMerge.tsx +++ b/app/client/src/git/components/GitOpsModal/TabMerge/DumbTabMerge.tsx @@ -1,4 +1,5 @@ import React, { useCallback, useEffect, useMemo, useState } from "react"; +import styled from "styled-components"; import { BRANCH_PROTECTION_PROTECTED, @@ -11,7 +12,6 @@ import { SELECT_BRANCH_TO_MERGE, } from "ee/constants/messages"; -import styled from "styled-components"; import Statusbar, { StatusbarWrapper, } from "pages/Editor/gitSync/components/Statusbar"; @@ -26,7 +26,6 @@ import { ModalBody, } from "@appsmith/ads"; import AnalyticsUtil from "ee/utils/AnalyticsUtil"; -import { Space } from "pages/Editor/gitSync/components/StyledComponents"; import { MergeStatusState } from "git/constants/enums"; import MergeStatus from "./MergeStatus"; import GitConflictError from "git/components/GitConflictError"; @@ -34,6 +33,7 @@ import MergeSuccessIndicator from "./MergeSuccessIndicator"; import { noop } from "lodash"; import type { FetchBranchesResponseData } from "git/requests/fetchBranchesRequest.types"; import type { FetchProtectedBranchesResponseData } from "git/requests/fetchProtectedBranchesRequest.types"; +import type { FetchMergeStatusResponseData } from "git/requests/fetchMergeStatusRequest.types"; const Container = styled.div` min-height: 360px; @@ -41,6 +41,11 @@ const Container = styled.div` padding-bottom: 4px; `; +const MergeSelectLabel = styled(Text)` + margin-bottom: 12px; + color: var(--ads-v2-color-fg-emphasis); +`; + const SelectContainer = styled.div` display: flex; align-items: center; @@ -67,14 +72,12 @@ interface DumbTabMergeProps { isFetchMergeStatusLoading: boolean; isFetchStatusLoading: boolean; isMergeLoading: boolean; - isMergeStatusMergeable: boolean; isStatusClean: boolean; merge: (sourceBranch: string, destinationBranch: string) => void; // ! case: should add proper type // eslint-disable-next-line @typescript-eslint/no-explicit-any mergeError: any; - mergeStatusConflictingFiles: string[] | null; - mergeStatusMessage: string | null; + mergeStatus: FetchMergeStatusResponseData | null; protectedBranches: FetchProtectedBranchesResponseData | null; } @@ -88,12 +91,10 @@ export default function DumbTabMerge({ isFetchMergeStatusLoading = false, isFetchStatusLoading = false, isMergeLoading = false, - isMergeStatusMergeable = false, isStatusClean = false, merge = noop, mergeError = null, - mergeStatusConflictingFiles = null, - mergeStatusMessage = null, + mergeStatus = null, protectedBranches = null, }: DumbTabMergeProps) { const [showMergeSuccessIndicator, setShowMergeSuccessIndicator] = @@ -101,10 +102,10 @@ export default function DumbTabMerge({ const [selectedBranchOption, setSelectedBranchOption] = useState(); - const isMergeable = isMergeStatusMergeable && isStatusClean; + const isMergeable = mergeStatus?.isMergeAble && isStatusClean; let message = !isStatusClean ? createMessage(CANNOT_MERGE_DUE_TO_UNCOMMITTED_CHANGES) - : mergeStatusMessage; + : mergeStatus?.message ?? null; const mergeBtnDisabled = isFetchMergeStatusLoading || !isMergeable; @@ -118,9 +119,9 @@ export default function DumbTabMerge({ } else if (isFetchMergeStatusLoading) { status = MergeStatusState.FETCHING; message = createMessage(FETCH_MERGE_STATUS); - } else if (isMergeStatusMergeable) { + } else if (mergeStatus && mergeStatus?.isMergeAble) { status = MergeStatusState.MERGEABLE; - } else if (!isMergeStatusMergeable) { + } else if (mergeStatus && !mergeStatus?.isMergeAble) { status = MergeStatusState.NOT_MERGEABLE; } else if (mergeError) { status = MergeStatusState.ERROR; @@ -128,7 +129,7 @@ export default function DumbTabMerge({ } // should check after added error code for conflicting - const isConflicting = (mergeStatusConflictingFiles?.length || 0) > 0; + const isConflicting = (mergeStatus?.conflictingFiles?.length || 0) > 0; const showMergeButton = !isConflicting && !mergeError && !isFetchStatusLoading && !isMergeLoading; @@ -239,10 +240,9 @@ export default function DumbTabMerge({ <> - + {createMessage(SELECT_BRANCH_TO_MERGE)} - - + {currentBranchDropdownOptions[0].label} - - +
+ +
{isConflicting ? : null} - {showMergeSuccessIndicator ? : null} {isMergeLoading ? ( diff --git a/app/client/src/git/components/GitOpsModal/TabMerge/index.tsx b/app/client/src/git/components/GitOpsModal/TabMerge/index.tsx index 101b137d3455..483662570aa9 100644 --- a/app/client/src/git/components/GitOpsModal/TabMerge/index.tsx +++ b/app/client/src/git/components/GitOpsModal/TabMerge/index.tsx @@ -21,9 +21,6 @@ export default function TabMerge() { } = useGitContext(); const isStatusClean = status?.isClean ?? false; - const isMergeStatusMergeable = mergeStatus?.isMergeAble ?? false; - const mergeStatusConflictingFiles = mergeStatus?.conflictingFiles ?? null; - const mergeStatusMessage = mergeStatus?.message ?? null; return ( ); From ba6ac3764c50ec7159a70d3bbb4c29ad1d95f27f Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Thu, 12 Dec 2024 20:03:01 +0800 Subject: [PATCH 038/143] chore: adding skeleton for status --- .../components/GitStatus/DumbGitStatus.tsx | 36 ++++++++++++ .../git/components/GitStatus/StatusTree.tsx | 55 +++++++++++++++++++ .../src/git/components/GitStatus/index.tsx | 33 ++++++++++- 3 files changed, 123 insertions(+), 1 deletion(-) create mode 100644 app/client/src/git/components/GitStatus/DumbGitStatus.tsx create mode 100644 app/client/src/git/components/GitStatus/StatusTree.tsx diff --git a/app/client/src/git/components/GitStatus/DumbGitStatus.tsx b/app/client/src/git/components/GitStatus/DumbGitStatus.tsx new file mode 100644 index 000000000000..c2d6efda1a10 --- /dev/null +++ b/app/client/src/git/components/GitStatus/DumbGitStatus.tsx @@ -0,0 +1,36 @@ +import type { FetchStatusResponseData } from "git/requests/fetchStatusRequest.types"; +import React, { useMemo } from "react"; +import type { StatusTreeStruct } from "./StatusTree"; +import StatusTree from "./StatusTree"; + +const noopStatusTransformer = () => null; + +interface DumbGitStatusProps { + status: FetchStatusResponseData | null; + statusTransformer: ( + status: FetchStatusResponseData, + ) => StatusTreeStruct | null; + isFetchStatusLoading: boolean; +} + +export default function DumbGitStatus({ + isFetchStatusLoading = false, + status = null, + statusTransformer = noopStatusTransformer, +}: DumbGitStatusProps) { + const statusTree = useMemo(() => { + if (!status || isFetchStatusLoading) return null; + + statusTransformer(status); + }, [isFetchStatusLoading, status, statusTransformer]); + + if (isFetchStatusLoading) { + return
Loading...
; + } + + if (!status || !statusTree) { + return null; + } + + return ; +} diff --git a/app/client/src/git/components/GitStatus/StatusTree.tsx b/app/client/src/git/components/GitStatus/StatusTree.tsx new file mode 100644 index 000000000000..2ba210e2ac65 --- /dev/null +++ b/app/client/src/git/components/GitStatus/StatusTree.tsx @@ -0,0 +1,55 @@ +import React from "react"; +import { + Collapsible, + CollapsibleContent, + CollapsibleHeader, + Icon, + Text, +} from "@appsmith/ads"; + +export interface StatusTreeStruct { + icon: string; + message: string; + children?: StatusTreeStruct[]; +} + +interface StatusTreeNodeProps { + icon: string; + message: string; +} + +function StatusTreeNode({ icon, message }: StatusTreeNodeProps) { + return ( +
+ + {message} +
+ ); +} + +interface StatusTreeProps { + tree: StatusTreeStruct | null; +} + +function StatusTree({ tree }: StatusTreeProps) { + if (!tree) return null; + + if (!tree.children) { + return ; + } + + return ( + + + + + + {tree.children.map((child, index) => ( + + ))} + + + ); +} + +export default StatusTree; diff --git a/app/client/src/git/components/GitStatus/index.tsx b/app/client/src/git/components/GitStatus/index.tsx index 79b38815fa5f..a7bae57b1bbf 100644 --- a/app/client/src/git/components/GitStatus/index.tsx +++ b/app/client/src/git/components/GitStatus/index.tsx @@ -1,7 +1,38 @@ import React from "react"; +import DumbGitStatus from "./DumbGitStatus"; +import { useGitContext } from "../GitContextProvider"; + +const initialState = { + icon: "widget", + message: "Page 1 modified", + children: [ + { + icon: "query", + message: "2 queries modified", + children: [ + { + icon: "query", + message: "Query 1 modified", + }, + { + icon: "query", + message: "Query 2 modified", + }, + ], + }, + ], +}; function GitStatus() { - return
GitStatus
; + const { fetchStatusLoading, status } = useGitContext(); + + return ( + initialState} + /> + ); } export default GitStatus; From 54ac997b19c24152e4a8dee5c3265d57b5a9d09b Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Fri, 13 Dec 2024 02:11:48 +0800 Subject: [PATCH 039/143] chore: adding status component and transformer --- .../application/statusTransformer.ts | 199 ++++++++++++++++++ .../hooks/useGitContextValue.ts | 10 + .../GitOpsModal/TabDeploy/DumbTabDeploy.tsx | 10 - .../components/GitStatus/DumbGitStatus.tsx | 22 +- .../git/components/GitStatus/StatusTree.tsx | 53 ++++- .../src/git/components/GitStatus/index.tsx | 27 +-- 6 files changed, 273 insertions(+), 48 deletions(-) create mode 100644 app/client/src/git/artifactHelpers/application/statusTransformer.ts diff --git a/app/client/src/git/artifactHelpers/application/statusTransformer.ts b/app/client/src/git/artifactHelpers/application/statusTransformer.ts new file mode 100644 index 000000000000..8d5193373a6b --- /dev/null +++ b/app/client/src/git/artifactHelpers/application/statusTransformer.ts @@ -0,0 +1,199 @@ +import type { FetchStatusResponseData } from "git/requests/fetchStatusRequest.types"; +import { objectKeys } from "@appsmith/utils"; +import type { StatusTreeStruct } from "git/components/GitStatus/StatusTree"; + +const ICON_LOOKUP = { + query: "query", + jsObject: "js", + page: "page-line", + datasource: "database-2-line", + jsLib: "package", +}; + +interface TreeNodeDef { + subject: string; + verb: string; + type: keyof typeof ICON_LOOKUP; +} + +function createTreeNode(nodeDef: TreeNodeDef) { + return { + icon: ICON_LOOKUP[nodeDef.type], + message: `${nodeDef.subject} ${nodeDef.verb}`, + }; +} + +function determineVerbForDefs(defs: TreeNodeDef[]) { + const isRemoved = defs.some((def) => def.verb === "removed"); + const isAdded = defs.some((def) => def.verb === "added"); + const isModified = defs.some((def) => def.verb === "modified"); + + let action = ""; + + if (isRemoved && !isAdded && !isModified) { + action = "removed"; + } else if (isAdded && !isRemoved && !isModified) { + action = "added"; + } else { + action = "modified"; + } + + return action; +} + +function createTreeNodeGroup(nodeDefs: TreeNodeDef[], subject: string) { + return { + icon: ICON_LOOKUP[nodeDefs[0].type], + message: `${nodeDefs.length} ${subject} ${determineVerbForDefs(nodeDefs)}`, + children: nodeDefs.map(createTreeNode), + }; +} + +function statusPageTransformer(status: FetchStatusResponseData) { + const { + jsObjectsAdded, + jsObjectsModified, + jsObjectsRemoved, + pagesAdded, + pagesModified, + pagesRemoved, + queriesAdded, + queriesModified, + queriesRemoved, + } = status; + const pageEntityDefLookup: Record = {}; + const addToPageEntityDefLookup = ( + files: string[], + type: keyof typeof ICON_LOOKUP, + verb: string, + ) => { + files.forEach((file) => { + const [page, subject] = file.split("/"); + + pageEntityDefLookup[page] ??= []; + pageEntityDefLookup[page].push({ subject, verb, type }); + }); + }; + + addToPageEntityDefLookup(queriesModified, "query", "modified"); + addToPageEntityDefLookup(queriesAdded, "query", "added"); + addToPageEntityDefLookup(queriesRemoved, "query", "removed"); + addToPageEntityDefLookup(jsObjectsModified, "jsObject", "modified"); + addToPageEntityDefLookup(jsObjectsAdded, "jsObject", "added"); + addToPageEntityDefLookup(jsObjectsRemoved, "jsObject", "removed"); + + const pageDefLookup: Record = {}; + const addToPageDefLookup = (pages: string[], verb: string) => { + pages.forEach((page) => { + pageDefLookup[page] = { subject: page, verb, type: "page" }; + }); + }; + + addToPageDefLookup(pagesModified, "modified"); + addToPageDefLookup(pagesAdded, "added"); + addToPageDefLookup(pagesRemoved, "removed"); + + const tree = [] as StatusTreeStruct[]; + + objectKeys(pageEntityDefLookup).forEach((page) => { + const queryDefs = pageEntityDefLookup[page].filter( + (def) => def.type === "query", + ); + const jsObjectDefs = pageEntityDefLookup[page].filter( + (def) => def.type === "jsObject", + ); + const children = [] as StatusTreeStruct[]; + + if (queryDefs.length > 0) { + const subject = queryDefs.length === 1 ? "query" : "queries"; + + children.push(createTreeNodeGroup(queryDefs, subject)); + } + + if (jsObjectDefs.length > 0) { + const subject = jsObjectDefs.length === 1 ? "query" : "queries"; + + children.push(createTreeNodeGroup(jsObjectDefs, subject)); + } + + let pageDef = pageDefLookup[page]; + + if (!pageDef) { + pageDef = { subject: page, verb: "modified", type: "page" }; + } + + tree.push({ ...createTreeNode(pageDef), children }); + }); + + objectKeys(pageDefLookup).forEach((page) => { + if (!pageEntityDefLookup[page]) { + tree.push(createTreeNode(pageDefLookup[page])); + } + }); + + return tree; +} + +function statusDatasourceTransformer(status: FetchStatusResponseData) { + const { datasourcesAdded, datasourcesModified, datasourcesRemoved } = status; + const defs = [] as TreeNodeDef[]; + + datasourcesModified.forEach((datasource) => { + defs.push({ subject: datasource, verb: "modified", type: "datasource" }); + }); + + datasourcesAdded.forEach((datasource) => { + defs.push({ subject: datasource, verb: "added", type: "datasource" }); + }); + + datasourcesRemoved.forEach((datasource) => { + defs.push({ subject: datasource, verb: "removed", type: "datasource" }); + }); + + const tree = [] as StatusTreeStruct[]; + + if (defs.length > 0) { + tree.push(createTreeNodeGroup(defs, "datasource")); + } + + return tree; +} + +function statusJsLibTransformer(status: FetchStatusResponseData) { + const { jsLibsAdded, jsLibsModified, jsLibsRemoved } = status; + const defs = [] as TreeNodeDef[]; + + jsLibsModified.forEach((jsLib) => { + defs.push({ subject: jsLib, verb: "modified", type: "jsLib" }); + }); + + jsLibsAdded.forEach((jsLib) => { + defs.push({ subject: jsLib, verb: "added", type: "jsLib" }); + }); + + jsLibsRemoved.forEach((jsLib) => { + defs.push({ subject: jsLib, verb: "removed", type: "jsLib" }); + }); + + const tree = [] as StatusTreeStruct[]; + + if (defs.length > 0) { + const subject = defs.length === 1 ? "jsLib" : "jsLibs"; + + tree.push(createTreeNodeGroup(defs, subject)); + } + + return tree; +} + +export default function applicationStatusTransformer( + status: FetchStatusResponseData, +) { + const tree = [ + ...statusPageTransformer(status), + ...statusDatasourceTransformer(status), + ...statusJsLibTransformer(status), + ] as StatusTreeStruct[]; + + return tree; +} diff --git a/app/client/src/git/components/GitContextProvider/hooks/useGitContextValue.ts b/app/client/src/git/components/GitContextProvider/hooks/useGitContextValue.ts index 7bb86e652263..9a4bab4927d3 100644 --- a/app/client/src/git/components/GitContextProvider/hooks/useGitContextValue.ts +++ b/app/client/src/git/components/GitContextProvider/hooks/useGitContextValue.ts @@ -13,12 +13,17 @@ import useGitMetadata from "./useGitMetadata"; // internal dependencies import type { ApplicationPayload } from "entities/Application"; +import type { FetchStatusResponseData } from "git/requests/fetchStatusRequest.types"; +import type { StatusTreeStruct } from "git/components/GitStatus/StatusTree"; export interface UseGitContextValueParams { artifactType: keyof typeof GitArtifactType; baseArtifactId: string; artifact: ApplicationPayload | null; connectPermitted: boolean; + statusTransformer: ( + status: FetchStatusResponseData, + ) => StatusTreeStruct[] | null; } export interface GitContextValue @@ -29,6 +34,9 @@ export interface GitContextValue UseGitBranchesReturnValue { artifact: ApplicationPayload | null; connectPermitted: boolean; + statusTransformer: ( + status: FetchStatusResponseData, + ) => StatusTreeStruct[] | null; } export default function useGitContextValue({ @@ -36,6 +44,7 @@ export default function useGitContextValue({ artifactType, baseArtifactId = "", connectPermitted, + statusTransformer, }: UseGitContextValueParams): GitContextValue { const basePayload = useMemo( () => ({ artifactType, baseArtifactId }), @@ -52,6 +61,7 @@ export default function useGitContextValue({ const useGitSettingsReturnValue = useGitSettings(basePayload); return { + statusTransformer, artifact, connectPermitted, ...useGitMetadataReturnValue, diff --git a/app/client/src/git/components/GitOpsModal/TabDeploy/DumbTabDeploy.tsx b/app/client/src/git/components/GitOpsModal/TabDeploy/DumbTabDeploy.tsx index e512a515df90..19f80c37ed74 100644 --- a/app/client/src/git/components/GitOpsModal/TabDeploy/DumbTabDeploy.tsx +++ b/app/client/src/git/components/GitOpsModal/TabDeploy/DumbTabDeploy.tsx @@ -7,7 +7,6 @@ import React, { } from "react"; import { ARE_YOU_SURE, - CHANGES_SINCE_LAST_DEPLOYMENT, COMMIT_AND_PUSH, COMMIT_TO, COMMITTING_AND_PUSHING_CHANGES, @@ -300,15 +299,6 @@ function DumbTabDeploy({ style={{ minHeight: 360 }} >
- {hasChangesToCommit && ( - - {createMessage(CHANGES_SINCE_LAST_DEPLOYMENT)} - - )} null; @@ -9,7 +12,7 @@ interface DumbGitStatusProps { status: FetchStatusResponseData | null; statusTransformer: ( status: FetchStatusResponseData, - ) => StatusTreeStruct | null; + ) => StatusTreeStruct[] | null; isFetchStatusLoading: boolean; } @@ -21,16 +24,27 @@ export default function DumbGitStatus({ const statusTree = useMemo(() => { if (!status || isFetchStatusLoading) return null; - statusTransformer(status); + return statusTransformer(status); }, [isFetchStatusLoading, status, statusTransformer]); if (isFetchStatusLoading) { return
Loading...
; } - if (!status || !statusTree) { + if (!status || status.isClean || !statusTree) { return null; } - return ; + return ( +
+ + {createMessage(CHANGES_SINCE_LAST_DEPLOYMENT)} + + +
+ ); } diff --git a/app/client/src/git/components/GitStatus/StatusTree.tsx b/app/client/src/git/components/GitStatus/StatusTree.tsx index 2ba210e2ac65..289d2d28b796 100644 --- a/app/client/src/git/components/GitStatus/StatusTree.tsx +++ b/app/client/src/git/components/GitStatus/StatusTree.tsx @@ -6,6 +6,7 @@ import { Icon, Text, } from "@appsmith/ads"; +import clsx from "clsx"; export interface StatusTreeStruct { icon: string; @@ -16,40 +17,72 @@ export interface StatusTreeStruct { interface StatusTreeNodeProps { icon: string; message: string; + noEmphasis?: boolean; } -function StatusTreeNode({ icon, message }: StatusTreeNodeProps) { +function StatusTreeNode({ + icon, + message, + noEmphasis = false, +}: StatusTreeNodeProps) { return ( -
- - {message} +
+ + + {message} +
); } -interface StatusTreeProps { +interface SingleStatusTreeProps { tree: StatusTreeStruct | null; + depth?: number; } -function StatusTree({ tree }: StatusTreeProps) { +function SingleStatusTree({ depth = 1, tree }: SingleStatusTreeProps) { if (!tree) return null; if (!tree.children) { - return ; + return ( + 2} + /> + ); } return ( - + - + {tree.children.map((child, index) => ( - + ))} ); } +interface StatusTreeProps { + tree: StatusTreeStruct[] | null; +} + +function StatusTree({ tree }: StatusTreeProps) { + if (!tree) return null; + + return ( +
+ {tree.map((tree, index) => ( + + ))} +
+ ); +} + export default StatusTree; diff --git a/app/client/src/git/components/GitStatus/index.tsx b/app/client/src/git/components/GitStatus/index.tsx index a7bae57b1bbf..a45796ad9a11 100644 --- a/app/client/src/git/components/GitStatus/index.tsx +++ b/app/client/src/git/components/GitStatus/index.tsx @@ -1,36 +1,15 @@ import React from "react"; -import DumbGitStatus from "./DumbGitStatus"; import { useGitContext } from "../GitContextProvider"; - -const initialState = { - icon: "widget", - message: "Page 1 modified", - children: [ - { - icon: "query", - message: "2 queries modified", - children: [ - { - icon: "query", - message: "Query 1 modified", - }, - { - icon: "query", - message: "Query 2 modified", - }, - ], - }, - ], -}; +import DumbGitStatus from "./DumbGitStatus"; function GitStatus() { - const { fetchStatusLoading, status } = useGitContext(); + const { fetchStatusLoading, status, statusTransformer } = useGitContext(); return ( initialState} + statusTransformer={statusTransformer} /> ); } From 523296ba72c2cbc2f5058cead5c5a37a6d7d3747 Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Fri, 13 Dec 2024 02:23:56 +0800 Subject: [PATCH 040/143] fix: adding autocommit statusbar --- .../src/git/components/GitQuickActions/DumbGitQuickActions.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/client/src/git/components/GitQuickActions/DumbGitQuickActions.tsx b/app/client/src/git/components/GitQuickActions/DumbGitQuickActions.tsx index 0c2a40270b0d..3dc3459670ad 100644 --- a/app/client/src/git/components/GitQuickActions/DumbGitQuickActions.tsx +++ b/app/client/src/git/components/GitQuickActions/DumbGitQuickActions.tsx @@ -13,7 +13,7 @@ import { GitOpsTab } from "../../constants/enums"; import { GitSettingsTab } from "../../constants/enums"; import ConnectButton from "./ConnectButton"; import QuickActionButton from "./QuickActionButton"; -import AutocommitStatusbar from "./AutocommitStatusbar"; +import AutocommitStatusbar from "../Statusbar"; import getPullBtnStatus from "./helpers/getPullButtonStatus"; import noop from "lodash/noop"; From 9d57e5a668312d324a1f987f071cc199e6a4884d Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Fri, 13 Dec 2024 05:23:55 +0800 Subject: [PATCH 041/143] chore: adding git settings modal --- .../hooks/useGitContextValue.ts | 15 ++- .../hooks/useGitPermissions.ts | 56 ++++++++++ .../hooks/useGitSettings.ts | 20 +++- .../components/GitContextProvider/index.tsx | 8 +- app/client/src/git/components/GitModals.tsx | 2 + .../GitSettingsModal/DumbGitSettingsModal.tsx | 101 ++++++++++++++++++ .../GitSettingsModal/TabBranch/index.tsx | 7 ++ .../TabContinuousDelivery/index.tsx | 58 ++++++++++ .../GitSettingsModal/TabGeneral/index.tsx | 7 ++ .../git/components/GitSettingsModal/index.tsx | 25 +++++ app/client/src/git/constants/enums.ts | 1 + app/client/src/git/store/actions/uiActions.ts | 4 +- .../helpers/gitSingleArtifactInitialState.ts | 6 +- .../selectors/gitSingleArtifactSelectors.ts | 13 ++- app/client/src/git/store/types.ts | 6 +- 15 files changed, 303 insertions(+), 26 deletions(-) create mode 100644 app/client/src/git/components/GitContextProvider/hooks/useGitPermissions.ts create mode 100644 app/client/src/git/components/GitSettingsModal/DumbGitSettingsModal.tsx create mode 100644 app/client/src/git/components/GitSettingsModal/TabBranch/index.tsx create mode 100644 app/client/src/git/components/GitSettingsModal/TabContinuousDelivery/index.tsx create mode 100644 app/client/src/git/components/GitSettingsModal/TabGeneral/index.tsx create mode 100644 app/client/src/git/components/GitSettingsModal/index.tsx diff --git a/app/client/src/git/components/GitContextProvider/hooks/useGitContextValue.ts b/app/client/src/git/components/GitContextProvider/hooks/useGitContextValue.ts index bbfbf87215cb..f39b27a40722 100644 --- a/app/client/src/git/components/GitContextProvider/hooks/useGitContextValue.ts +++ b/app/client/src/git/components/GitContextProvider/hooks/useGitContextValue.ts @@ -15,12 +15,14 @@ import useGitMetadata from "./useGitMetadata"; import type { ApplicationPayload } from "entities/Application"; import type { FetchStatusResponseData } from "git/requests/fetchStatusRequest.types"; import type { StatusTreeStruct } from "git/components/GitStatus/StatusTree"; +import useGitPermissions, { + type UseGitPermissionsReturnValue, +} from "./useGitPermissions"; export interface UseGitContextValueParams { artifactType: keyof typeof GitArtifactType; baseArtifactId: string; artifact: ApplicationPayload | null; - connectPermitted: boolean; statusTransformer: ( status: FetchStatusResponseData, ) => StatusTreeStruct[] | null; @@ -31,9 +33,9 @@ export interface GitContextValue UseGitConnectReturnValue, UseGitOpsReturnValue, UseGitSettingsReturnValue, - UseGitBranchesReturnValue { + UseGitBranchesReturnValue, + UseGitPermissionsReturnValue { artifact: ApplicationPayload | null; - connectPermitted: boolean; statusTransformer: ( status: FetchStatusResponseData, ) => StatusTreeStruct[] | null; @@ -43,7 +45,6 @@ export default function useGitContextValue({ artifact, artifactType, baseArtifactId = "", - connectPermitted, statusTransformer, }: UseGitContextValueParams): GitContextValue { const basePayload = useMemo( @@ -58,15 +59,19 @@ export default function useGitContextValue({ }); const useGitBranchesReturnValue = useGitBranches(basePayload); const useGitSettingsReturnValue = useGitSettings(basePayload); + const useGitPermissionsReturnValue = useGitPermissions({ + ...basePayload, + artifact, + }); return { statusTransformer, artifact, - connectPermitted, ...useGitMetadataReturnValue, ...useGitOpsReturnValue, ...useGitBranchesReturnValue, ...useGitConnectReturnValue, ...useGitSettingsReturnValue, + ...useGitPermissionsReturnValue, }; } diff --git a/app/client/src/git/components/GitContextProvider/hooks/useGitPermissions.ts b/app/client/src/git/components/GitContextProvider/hooks/useGitPermissions.ts new file mode 100644 index 000000000000..b8295a9e2e81 --- /dev/null +++ b/app/client/src/git/components/GitContextProvider/hooks/useGitPermissions.ts @@ -0,0 +1,56 @@ +import { + hasConnectToGitPermission, + hasManageDefaultBranchPermission, + hasManageProtectedBranchesPermission, +} from "ee/utils/permissionHelpers"; +import type { ApplicationPayload } from "entities/Application"; +import { GitArtifactType } from "git/constants/enums"; +import { useMemo } from "react"; + +interface UseGitPermissionsParams { + artifactType: keyof typeof GitArtifactType; + baseArtifactId: string; + artifact: ApplicationPayload | null; +} + +export interface UseGitPermissionsReturnValue { + isConnectPermitted: boolean; + isManageDefaultBranchPermitted: boolean; + isManageProtectedBranchesPermitted: boolean; +} + +export default function useGitPermissions({ + artifact, + artifactType, +}: UseGitPermissionsParams): UseGitPermissionsReturnValue { + const isConnectPermitted = useMemo(() => { + if (artifact) { + if (artifactType === GitArtifactType.Application) { + return hasConnectToGitPermission(artifact.userPermissions); + } + } + }, [artifact, artifactType]); + + const isManageDefaultBranchPermitted = useMemo(() => { + if (artifact) { + if (artifactType === GitArtifactType.Application) { + return hasManageDefaultBranchPermission(artifact.userPermissions); + } + } + }, [artifact, artifactType]); + + const isManageProtectedBranchesPermitted = useMemo(() => { + if (artifact) { + if (artifactType === GitArtifactType.Application) { + return hasManageProtectedBranchesPermission(artifact.userPermissions); + } + } + }, [artifact, artifactType]); + + return { + isConnectPermitted: isConnectPermitted ?? false, + isManageDefaultBranchPermitted: isManageDefaultBranchPermitted ?? false, + isManageProtectedBranchesPermitted: + isManageProtectedBranchesPermitted ?? false, + }; +} diff --git a/app/client/src/git/components/GitContextProvider/hooks/useGitSettings.ts b/app/client/src/git/components/GitContextProvider/hooks/useGitSettings.ts index 54f1699f253c..bddd78180fb2 100644 --- a/app/client/src/git/components/GitContextProvider/hooks/useGitSettings.ts +++ b/app/client/src/git/components/GitContextProvider/hooks/useGitSettings.ts @@ -1,4 +1,4 @@ -import type { GitArtifactType, GitSettingsTab } from "git/constants/enums"; +import { GitSettingsTab, type GitArtifactType } from "git/constants/enums"; import type { FetchProtectedBranchesResponseData } from "git/requests/fetchProtectedBranchesRequest.types"; import { gitArtifactActions } from "git/store/gitArtifactSlice"; import { @@ -6,6 +6,8 @@ import { selectAutocommitPolling, selectProtectedBranches, selectProtectedMode, + selectSettingsModalOpen, + selectSettingsModalTab, } from "git/store/selectors/gitSingleArtifactSelectors"; import type { GitRootState } from "git/store/types"; import { useMemo } from "react"; @@ -24,9 +26,11 @@ export interface UseGitSettingsReturnValue { fetchProtectedBranchesError: string | null; fetchProtectedBranches: () => void; protectedMode: boolean; + settingsModalOpen: boolean; + settingsModalTab: keyof typeof GitSettingsTab; toggleSettingsModal: ( open: boolean, - tab: keyof typeof GitSettingsTab, + tab?: keyof typeof GitSettingsTab, ) => void; } @@ -67,9 +71,17 @@ export default function useGitSettings({ ); // ui + const settingsModalOpen = useSelector((state: GitRootState) => + selectSettingsModalOpen(state, basePayload), + ); + + const settingsModalTab = useSelector((state: GitRootState) => + selectSettingsModalTab(state, basePayload), + ); + const toggleSettingsModal = ( open: boolean, - tab: keyof typeof GitSettingsTab, + tab: keyof typeof GitSettingsTab = GitSettingsTab.General, ) => { dispatch( gitArtifactActions.toggleSettingsModal({ @@ -88,6 +100,8 @@ export default function useGitSettings({ fetchProtectedBranchesError: protectedBranchesState.error, fetchProtectedBranches, protectedMode: protectedMode ?? false, + settingsModalOpen: settingsModalOpen ?? false, + settingsModalTab: settingsModalTab ?? GitSettingsTab.General, toggleSettingsModal, }; } diff --git a/app/client/src/git/components/GitContextProvider/index.tsx b/app/client/src/git/components/GitContextProvider/index.tsx index 59d3094476c5..671f3b66a605 100644 --- a/app/client/src/git/components/GitContextProvider/index.tsx +++ b/app/client/src/git/components/GitContextProvider/index.tsx @@ -1,9 +1,7 @@ import React, { createContext, useContext } from "react"; -import type { - GitContextValue, - UseGitContextValueParams, -} from "./hooks/useGitContextValue"; import useGitContextValue from "./hooks/useGitContextValue"; +import type { UseGitContextValueParams } from "./hooks/useGitContextValue"; +import type { GitContextValue } from "./hooks/useGitContextValue"; const gitContextInitialValue = {} as GitContextValue; @@ -15,8 +13,6 @@ export const useGitContext = () => { interface GitContextProviderProps extends UseGitContextValueParams { children: React.ReactNode; - // extra - // connectPermitted?: boolean; } export default function GitContextProvider({ diff --git a/app/client/src/git/components/GitModals.tsx b/app/client/src/git/components/GitModals.tsx index 52b2097eee16..51d265dd71df 100644 --- a/app/client/src/git/components/GitModals.tsx +++ b/app/client/src/git/components/GitModals.tsx @@ -1,11 +1,13 @@ import React from "react"; import GitOpsModal from "./GitOpsModal"; import GitConflictErrorModal from "./GitConflictErrorModal"; +import GitSettingsModal from "pages/Editor/gitSync/GitSettingsModal"; export default function GitModals() { return ( <> + ); diff --git a/app/client/src/git/components/GitSettingsModal/DumbGitSettingsModal.tsx b/app/client/src/git/components/GitSettingsModal/DumbGitSettingsModal.tsx new file mode 100644 index 000000000000..94efd2d63ac2 --- /dev/null +++ b/app/client/src/git/components/GitSettingsModal/DumbGitSettingsModal.tsx @@ -0,0 +1,101 @@ +import React, { useCallback } from "react"; + +import { + Modal, + ModalBody, + ModalContent, + ModalHeader, + Tab, + Tabs, + TabsList, +} from "@appsmith/ads"; +import styled from "styled-components"; +import { + BRANCH, + GENERAL, + SETTINGS_GIT, + createMessage, +} from "ee/constants/messages"; +import TabGeneral from "./TabGeneral"; +import TabBranch from "./TabBranch"; +import { GitSettingsTab } from "git/constants/enums"; +import TabContinuousDelivery from "./TabContinuousDelivery"; +import noop from "lodash/noop"; + +const StyledModalContent = styled(ModalContent)` + &&& { + width: 600px; + transform: none !important; + top: 100px; + left: calc(50% - 300px); + max-height: calc(100vh - 200px); + } +`; + +interface DumbGitSettingsModalProps { + isManageDefaultBranchPermitted: boolean; + isManageProtectedBranchesPermitted: boolean; + isSettingsModalOpen: boolean; + settingsModalTab: keyof typeof GitSettingsTab; + toggleSettingsModal: ( + open: boolean, + tab?: keyof typeof GitSettingsTab, + ) => void; +} + +function DumbGitSettingsModal({ + isManageDefaultBranchPermitted = false, + isManageProtectedBranchesPermitted = false, + isSettingsModalOpen = false, + settingsModalTab = GitSettingsTab.General, + toggleSettingsModal = noop, +}: DumbGitSettingsModalProps) { + const showBranchTab = + isManageDefaultBranchPermitted || isManageProtectedBranchesPermitted; + + const handleTabKeyChange = useCallback( + (tabKey: string) => { + toggleSettingsModal(true, tabKey as GitSettingsTab); + }, + [toggleSettingsModal], + ); + + const handleModalOpenChange = useCallback( + () => (open: boolean) => { + toggleSettingsModal(open); + }, + [toggleSettingsModal], + ); + + return ( + + + {createMessage(SETTINGS_GIT)} + + + + {createMessage(GENERAL)} + + {showBranchTab && ( + + {createMessage(BRANCH)} + + )} + + {createMessage(BRANCH)} + + + + + {settingsModalTab === GitSettingsTab.General && } + {settingsModalTab === GitSettingsTab.Branch && } + {settingsModalTab === GitSettingsTab.ContinuousDelivery && ( + + )} + + + + ); +} + +export default DumbGitSettingsModal; diff --git a/app/client/src/git/components/GitSettingsModal/TabBranch/index.tsx b/app/client/src/git/components/GitSettingsModal/TabBranch/index.tsx new file mode 100644 index 000000000000..0a9296c6f226 --- /dev/null +++ b/app/client/src/git/components/GitSettingsModal/TabBranch/index.tsx @@ -0,0 +1,7 @@ +import React from "react"; + +function TabBranch() { + return
TabBranch
; +} + +export default TabBranch; diff --git a/app/client/src/git/components/GitSettingsModal/TabContinuousDelivery/index.tsx b/app/client/src/git/components/GitSettingsModal/TabContinuousDelivery/index.tsx new file mode 100644 index 000000000000..a75366b6e87a --- /dev/null +++ b/app/client/src/git/components/GitSettingsModal/TabContinuousDelivery/index.tsx @@ -0,0 +1,58 @@ +import { + CONFIGURE_CD_DESC, + CONFIGURE_CD_TITLE, + TRY_APPSMITH_ENTERPRISE, + createMessage, +} from "ee/constants/messages"; +import { Button, Text } from "@appsmith/ads"; +import { useAppsmithEnterpriseLink } from "pages/Editor/gitSync/GitSettingsModal/TabBranch/hooks"; +import React from "react"; +import styled from "styled-components"; + +export const Container = styled.div` + padding-top: 8px; + padding-bottom: 16px; + overflow: auto; + min-height: calc(360px + 52px); +`; + +export const SectionTitle = styled(Text)` + font-weight: 600; + margin-bottom: 4px; +`; + +export const SectionDesc = styled(Text)` + margin-bottom: 12px; +`; + +export const StyledButton = styled(Button)` + display: inline-block; +`; + +function TabContinuousDelivery() { + const enterprisePricingLink = useAppsmithEnterpriseLink( + "git_continuous_delivery", + ); + + return ( + + + {createMessage(CONFIGURE_CD_TITLE)} + + + {createMessage(CONFIGURE_CD_DESC)} + + + {createMessage(TRY_APPSMITH_ENTERPRISE)} + + + ); +} + +export default TabContinuousDelivery; diff --git a/app/client/src/git/components/GitSettingsModal/TabGeneral/index.tsx b/app/client/src/git/components/GitSettingsModal/TabGeneral/index.tsx new file mode 100644 index 000000000000..8fee5e0265b6 --- /dev/null +++ b/app/client/src/git/components/GitSettingsModal/TabGeneral/index.tsx @@ -0,0 +1,7 @@ +import React from "react"; + +function TabGeneral() { + return
TabGeneral
; +} + +export default TabGeneral; diff --git a/app/client/src/git/components/GitSettingsModal/index.tsx b/app/client/src/git/components/GitSettingsModal/index.tsx new file mode 100644 index 000000000000..ebe054ee7984 --- /dev/null +++ b/app/client/src/git/components/GitSettingsModal/index.tsx @@ -0,0 +1,25 @@ +import React from "react"; +import DumbGitSettingsModal from "./DumbGitSettingsModal"; +import { useGitContext } from "../GitContextProvider"; + +function GitSettingsModal() { + const { + isManageDefaultBranchPermitted, + isManageProtectedBranchesPermitted, + settingsModalOpen, + settingsModalTab, + toggleSettingsModal, + } = useGitContext(); + + return ( + + ); +} + +export default GitSettingsModal; diff --git a/app/client/src/git/constants/enums.ts b/app/client/src/git/constants/enums.ts index 848521ee58ad..244f2237a760 100644 --- a/app/client/src/git/constants/enums.ts +++ b/app/client/src/git/constants/enums.ts @@ -24,6 +24,7 @@ export enum GitOpsTab { export enum GitSettingsTab { General = "General", Branch = "Branch", + ContinuousDelivery = "ContinuousDelivery", } export enum AutocommitStatusState { diff --git a/app/client/src/git/store/actions/uiActions.ts b/app/client/src/git/store/actions/uiActions.ts index c4e47fe2fe33..3d5c76252e52 100644 --- a/app/client/src/git/store/actions/uiActions.ts +++ b/app/client/src/git/store/actions/uiActions.ts @@ -66,8 +66,8 @@ export const toggleSettingsModalAction = createSingleArtifactAction((state, action) => { const { open, tab } = action.payload; - state.ui.settingsModal.open = open; - state.ui.settingsModal.tab = tab; + state.ui.settingsModalOpen = open; + state.ui.settingsModalTab = tab; return state; }); diff --git a/app/client/src/git/store/helpers/gitSingleArtifactInitialState.ts b/app/client/src/git/store/helpers/gitSingleArtifactInitialState.ts index 9266e852ff7a..8b5f8bfc58d5 100644 --- a/app/client/src/git/store/helpers/gitSingleArtifactInitialState.ts +++ b/app/client/src/git/store/helpers/gitSingleArtifactInitialState.ts @@ -25,10 +25,8 @@ const gitSingleArtifactInitialUIState: GitSingleArtifactUIReduxState = { opsModalOpen: false, opsModalTab: GitOpsTab.Deploy, conflictErrorModalOpen: false, - settingsModal: { - open: false, - tab: GitSettingsTab.General, - }, + settingsModalOpen: false, + settingsModalTab: GitSettingsTab.General, repoLimitErrorModal: { open: false, }, diff --git a/app/client/src/git/store/selectors/gitSingleArtifactSelectors.ts b/app/client/src/git/store/selectors/gitSingleArtifactSelectors.ts index 4ff29711e662..03a36c5b3776 100644 --- a/app/client/src/git/store/selectors/gitSingleArtifactSelectors.ts +++ b/app/client/src/git/store/selectors/gitSingleArtifactSelectors.ts @@ -99,7 +99,7 @@ export const selectCheckoutBranch = ( artifactDef: GitArtifactDef, ) => selectSingleArtifact(state, artifactDef)?.apiResponses.checkoutBranch; -// autocommit +// settings export const selectAutocommitEnabled = ( state: GitRootState, artifactDef: GitArtifactDef, @@ -114,7 +114,6 @@ export const selectAutocommitPolling = ( artifactDef: GitArtifactDef, ) => selectSingleArtifact(state, artifactDef)?.ui.autocommitPolling; -// protected branches export const selectProtectedBranches = ( state: GitRootState, artifactDef: GitArtifactDef, @@ -129,3 +128,13 @@ export const selectProtectedMode = ( return protectedBranches?.includes(currentBranch ?? ""); }; + +export const selectSettingsModalOpen = ( + state: GitRootState, + artifactDef: GitArtifactDef, +) => selectSingleArtifact(state, artifactDef)?.ui.settingsModalOpen; + +export const selectSettingsModalTab = ( + state: GitRootState, + artifactDef: GitArtifactDef, +) => selectSingleArtifact(state, artifactDef)?.ui.settingsModalTab; diff --git a/app/client/src/git/store/types.ts b/app/client/src/git/store/types.ts index c15d52dc5107..31472a98c9c9 100644 --- a/app/client/src/git/store/types.ts +++ b/app/client/src/git/store/types.ts @@ -66,10 +66,8 @@ export interface GitSingleArtifactUIReduxState { opsModalOpen: boolean; opsModalTab: keyof typeof GitOpsTab; conflictErrorModalOpen: boolean; - settingsModal: { - open: boolean; - tab: keyof typeof GitSettingsTab; - }; + settingsModalOpen: boolean; + settingsModalTab: keyof typeof GitSettingsTab; repoLimitErrorModal: { open: boolean; }; From 44167c0b6d8ead80d4d1f970816922655de583e2 Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Fri, 13 Dec 2024 14:41:08 +0800 Subject: [PATCH 042/143] chore: wip - git settings modal --- .../GitDefaultBranch/DumbGitDefaultBranch.tsx | 146 ++++++++++++++++++ .../git/components/GitDefaultBranch/index.tsx | 7 + app/client/src/git/components/GitModals.tsx | 2 +- .../DumbGitProtectedBranches.tsx | 7 + .../components/GitProtectedBranches/index.tsx | 7 + .../GitSettingsModal/DumbGitSettingsModal.tsx | 26 ++-- .../GitSettingsModal/TabBranch/index.tsx | 27 +++- 7 files changed, 208 insertions(+), 14 deletions(-) create mode 100644 app/client/src/git/components/GitDefaultBranch/DumbGitDefaultBranch.tsx create mode 100644 app/client/src/git/components/GitDefaultBranch/index.tsx create mode 100644 app/client/src/git/components/GitProtectedBranches/DumbGitProtectedBranches.tsx create mode 100644 app/client/src/git/components/GitProtectedBranches/index.tsx diff --git a/app/client/src/git/components/GitDefaultBranch/DumbGitDefaultBranch.tsx b/app/client/src/git/components/GitDefaultBranch/DumbGitDefaultBranch.tsx new file mode 100644 index 000000000000..ea336115d2d8 --- /dev/null +++ b/app/client/src/git/components/GitDefaultBranch/DumbGitDefaultBranch.tsx @@ -0,0 +1,146 @@ +import { + APPSMITH_ENTERPRISE, + DEFAULT_BRANCH, + DEFAULT_BRANCH_DESC, + UPDATE, + createMessage, +} from "ee/constants/messages"; +// import { updateGitDefaultBranch } from "actions/gitSyncActions"; +import { Button, Link, Option, Select, Text } from "@appsmith/ads"; +import React, { useEffect, useMemo, useState } from "react"; +// import { useDispatch, useSelector } from "react-redux"; +// import { getGitBranches } from "selectors/gitSyncSelectors"; +import styled from "styled-components"; +// import { useFeatureFlag } from "utils/hooks/useFeatureFlag"; +// import { FEATURE_FLAG } from "ee/entities/FeatureFlag"; +import { useAppsmithEnterpriseLink } from "./hooks"; +import AnalyticsUtil from "ee/utils/AnalyticsUtil"; +import type { FetchBranchesResponseData } from "git/requests/fetchBranchesRequest.types"; + +const Container = styled.div` + padding-top: 8px; + padding-bottom: 16px; +`; + +const HeadContainer = styled.div` + margin-bottom: 16px; +`; + +const BodyContainer = styled.div` + display: flex; +`; + +const SectionTitle = styled(Text)` + font-weight: 600; + margin-bottom: 4px; +`; + +const SectionDesc = styled(Text)` + margin-bottom: 4px; +`; + +const StyledSelect = styled(Select)` + width: 240px; + margin-right: 12px; +`; + +interface DumbGitDefaultBranchProps { + branches: FetchBranchesResponseData | null; + isGitProtectedFeatureLicensed: boolean; +} + +function DumbGitDefaultBranch({ + branches = null, + isGitProtectedFeatureLicensed = false, +}: DumbGitDefaultBranchProps) { + const [selectedValue, setSelectedValue] = useState(); + + const currentDefaultBranch = useMemo(() => { + const defaultBranch = branches?.find((b) => b.default); + + return defaultBranch?.branchName; + }, [branches]); + + const enterprisePricingLink = useAppsmithEnterpriseLink( + "git_branch_protection", + ); + + useEffect( + function selectedValueOnInitEffect() { + const defaultBranch = branches?.find((b) => b.default); + + setSelectedValue(defaultBranch?.branchName); + }, + [branches], + ); + + const filteredBranches = branches?.filter( + (branch) => !branch.branchName.includes("origin/"), + ); + + const handleUpdate = () => { + if (selectedValue) { + AnalyticsUtil.logEvent("GS_DEFAULT_BRANCH_UPDATE", { + old_branch: currentDefaultBranch, + new_branch: selectedValue, + }); + // dispatch(updateGitDefaultBranch({ branchName: selectedValue })); + } + }; + + const updateIsDisabled = + !selectedValue || selectedValue === currentDefaultBranch; + + return ( + + + + {createMessage(DEFAULT_BRANCH)} + + + {createMessage(DEFAULT_BRANCH_DESC)} + + {!isGitProtectedFeatureLicensed && ( + + To change your default branch, try{" "} + + {createMessage(APPSMITH_ENTERPRISE)} + + + )} + + + triggerNode.parentNode} + isDisabled={!isGitProtectedFeatureLicensed} + onChange={(v) => setSelectedValue(v)} + value={selectedValue} + > + {filteredBranches?.map((b) => ( + + ))} + + + + + ); +} + +export default DumbGitDefaultBranch; diff --git a/app/client/src/git/components/GitDefaultBranch/index.tsx b/app/client/src/git/components/GitDefaultBranch/index.tsx new file mode 100644 index 000000000000..4cc7fadbddcc --- /dev/null +++ b/app/client/src/git/components/GitDefaultBranch/index.tsx @@ -0,0 +1,7 @@ +import React from "react"; + +function GitDefaultBranch() { + return
GitDefaultBranch
; +} + +export default GitDefaultBranch; diff --git a/app/client/src/git/components/GitModals.tsx b/app/client/src/git/components/GitModals.tsx index 51d265dd71df..866b92bb584c 100644 --- a/app/client/src/git/components/GitModals.tsx +++ b/app/client/src/git/components/GitModals.tsx @@ -1,7 +1,7 @@ import React from "react"; import GitOpsModal from "./GitOpsModal"; import GitConflictErrorModal from "./GitConflictErrorModal"; -import GitSettingsModal from "pages/Editor/gitSync/GitSettingsModal"; +import GitSettingsModal from "./GitSettingsModal"; export default function GitModals() { return ( diff --git a/app/client/src/git/components/GitProtectedBranches/DumbGitProtectedBranches.tsx b/app/client/src/git/components/GitProtectedBranches/DumbGitProtectedBranches.tsx new file mode 100644 index 000000000000..55bd9b574ed9 --- /dev/null +++ b/app/client/src/git/components/GitProtectedBranches/DumbGitProtectedBranches.tsx @@ -0,0 +1,7 @@ +import React from "react"; + +function DumbGitProtectedBranches() { + return
DumbGitProtectedBranches
; +} + +export default DumbGitProtectedBranches; diff --git a/app/client/src/git/components/GitProtectedBranches/index.tsx b/app/client/src/git/components/GitProtectedBranches/index.tsx new file mode 100644 index 000000000000..1fc45b461c4d --- /dev/null +++ b/app/client/src/git/components/GitProtectedBranches/index.tsx @@ -0,0 +1,7 @@ +import React from "react"; + +function GitProtectedBranches() { + return
GitProtectedBranches
; +} + +export default GitProtectedBranches; diff --git a/app/client/src/git/components/GitSettingsModal/DumbGitSettingsModal.tsx b/app/client/src/git/components/GitSettingsModal/DumbGitSettingsModal.tsx index 94efd2d63ac2..3b6404d69a2d 100644 --- a/app/client/src/git/components/GitSettingsModal/DumbGitSettingsModal.tsx +++ b/app/client/src/git/components/GitSettingsModal/DumbGitSettingsModal.tsx @@ -12,6 +12,7 @@ import { import styled from "styled-components"; import { BRANCH, + CONTINUOUS_DELIVERY, GENERAL, SETTINGS_GIT, createMessage, @@ -60,15 +61,8 @@ function DumbGitSettingsModal({ [toggleSettingsModal], ); - const handleModalOpenChange = useCallback( - () => (open: boolean) => { - toggleSettingsModal(open); - }, - [toggleSettingsModal], - ); - return ( - + {createMessage(SETTINGS_GIT)} @@ -81,14 +75,24 @@ function DumbGitSettingsModal({ {createMessage(BRANCH)} )} - - {createMessage(BRANCH)} + + {createMessage(CONTINUOUS_DELIVERY)} {settingsModalTab === GitSettingsTab.General && } - {settingsModalTab === GitSettingsTab.Branch && } + {settingsModalTab === GitSettingsTab.Branch && ( + + )} {settingsModalTab === GitSettingsTab.ContinuousDelivery && ( )} diff --git a/app/client/src/git/components/GitSettingsModal/TabBranch/index.tsx b/app/client/src/git/components/GitSettingsModal/TabBranch/index.tsx index 0a9296c6f226..01cf13881ee1 100644 --- a/app/client/src/git/components/GitSettingsModal/TabBranch/index.tsx +++ b/app/client/src/git/components/GitSettingsModal/TabBranch/index.tsx @@ -1,7 +1,30 @@ import React from "react"; +import styled from "styled-components"; +import GitDefaultBranch from "../../GitDefaultBranch"; +import GitProtectedBranches from "../../GitProtectedBranches"; -function TabBranch() { - return
TabBranch
; +const Container = styled.div` + overflow: auto; +`; + +interface TabBranchProps { + isManageDefaultBranchPermitted: boolean; + isManageProtectedBranchesPermitted: boolean; +} + +function TabBranch({ + isManageDefaultBranchPermitted = false, + isManageProtectedBranchesPermitted = false, +}: TabBranchProps) { + const showDefaultBranch = isManageDefaultBranchPermitted; + const showProtectedBranches = isManageProtectedBranchesPermitted; + + return ( + + {showDefaultBranch && } + {showProtectedBranches && } + + ); } export default TabBranch; From f698d26fa7f4214f9afad8ff02074275f61f9698 Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Fri, 13 Dec 2024 16:45:57 +0800 Subject: [PATCH 043/143] fix: fixing error handling --- .../hooks/useGitBranches.ts | 10 +-- .../hooks/useGitMetadata.ts | 4 +- .../GitContextProvider/hooks/useGitOps.ts | 14 ++-- .../hooks/useGitSettings.ts | 4 +- .../GitOpsModal/TabDeploy/DumbTabDeploy.tsx | 7 +- .../TabDeploy/PushFailedWarning.tsx | 13 +++- .../requests/fetchBranchesRequest.types.ts | 2 +- .../src/git/requests/pullRequest.types.ts | 6 +- .../src/git/sagas/checkoutBranchSaga.ts | 23 +++++-- app/client/src/git/sagas/commitSaga.ts | 39 +++++------ app/client/src/git/sagas/connectSaga.ts | 33 ++++++---- app/client/src/git/sagas/createBranchSaga.ts | 30 ++++++--- app/client/src/git/sagas/deleteBranchSaga.ts | 23 +++++-- app/client/src/git/sagas/fetchBranchesSaga.ts | 23 +++++-- .../src/git/sagas/fetchGitMetadataSaga.ts | 23 +++++-- .../src/git/sagas/fetchGlobalProfileSaga.ts | 21 ++++-- .../src/git/sagas/fetchLocalProfileSaga.ts | 20 ++++-- .../src/git/sagas/fetchMergeStatusSaga.ts | 23 +++++-- .../git/sagas/fetchProtectedBranchesSaga.ts | 23 +++++-- app/client/src/git/sagas/fetchStatusSaga.ts | 25 +++++--- app/client/src/git/sagas/pullSaga.ts | 26 ++++---- .../src/git/sagas/triggerAutocommitSaga.ts | 51 +++++++++------ .../src/git/sagas/updateGlobalProfileSaga.ts | 15 +++-- .../src/git/sagas/updateLocalProfileSaga.ts | 20 ++++-- app/client/src/git/store/types.ts | 64 ++++++++++--------- 25 files changed, 346 insertions(+), 196 deletions(-) diff --git a/app/client/src/git/components/GitContextProvider/hooks/useGitBranches.ts b/app/client/src/git/components/GitContextProvider/hooks/useGitBranches.ts index 2ec719175189..551338860fad 100644 --- a/app/client/src/git/components/GitContextProvider/hooks/useGitBranches.ts +++ b/app/client/src/git/components/GitContextProvider/hooks/useGitBranches.ts @@ -8,7 +8,7 @@ import { selectCurrentBranch, selectDeleteBranch, } from "git/store/selectors/gitSingleArtifactSelectors"; -import type { GitRootState } from "git/store/types"; +import type { GitApiError, GitRootState } from "git/store/types"; import { useCallback, useMemo } from "react"; import { useDispatch, useSelector } from "react-redux"; @@ -20,16 +20,16 @@ interface UseGitBranchesParams { export interface UseGitBranchesReturnValue { branches: FetchBranchesResponseData | null; fetchBranchesLoading: boolean; - fetchBranchesError: string | null; + fetchBranchesError: GitApiError | null; fetchBranches: () => void; createBranchLoading: boolean; - createBranchError: string | null; + createBranchError: GitApiError | null; createBranch: (branchName: string) => void; deleteBranchLoading: boolean; - deleteBranchError: string | null; + deleteBranchError: GitApiError | null; deleteBranch: (branchName: string) => void; checkoutBranchLoading: boolean; - checkoutBranchError: string | null; + checkoutBranchError: GitApiError | null; checkoutBranch: (branchName: string) => void; currentBranch: string | null; toggleBranchListPopup: (open: boolean) => void; diff --git a/app/client/src/git/components/GitContextProvider/hooks/useGitMetadata.ts b/app/client/src/git/components/GitContextProvider/hooks/useGitMetadata.ts index b1a10de4a1a5..aabc125c8382 100644 --- a/app/client/src/git/components/GitContextProvider/hooks/useGitMetadata.ts +++ b/app/client/src/git/components/GitContextProvider/hooks/useGitMetadata.ts @@ -4,7 +4,7 @@ import { selectGitConnected, selectGitMetadata, } from "git/store/selectors/gitSingleArtifactSelectors"; -import type { GitRootState } from "git/store/types"; +import type { GitApiError, GitRootState } from "git/store/types"; import { useMemo } from "react"; import { useSelector } from "react-redux"; @@ -16,7 +16,7 @@ interface UseGitMetadataParams { export interface UseGitMetadataReturnValue { gitMetadata: FetchGitMetadataResponseData | null; fetchGitMetadataLoading: boolean; - fetchGitMetadataError: string | null; + fetchGitMetadataError: GitApiError | null; gitConnected: boolean; } diff --git a/app/client/src/git/components/GitContextProvider/hooks/useGitOps.ts b/app/client/src/git/components/GitContextProvider/hooks/useGitOps.ts index 9bb9daf59d1c..97b224f33717 100644 --- a/app/client/src/git/components/GitContextProvider/hooks/useGitOps.ts +++ b/app/client/src/git/components/GitContextProvider/hooks/useGitOps.ts @@ -13,7 +13,7 @@ import { selectPull, selectStatus, } from "git/store/selectors/gitSingleArtifactSelectors"; -import type { GitRootState } from "git/store/types"; +import type { GitApiError, GitRootState } from "git/store/types"; import { useCallback, useMemo } from "react"; import { useDispatch, useSelector } from "react-redux"; @@ -25,27 +25,27 @@ interface UseGitOpsParams { export interface UseGitOpsReturnValue { commitLoading: boolean; - commitError: string | null; + commitError: GitApiError | null; commit: (commitMessage: string) => void; clearCommitError: () => void; discardLoading: boolean; - discardError: string | null; + discardError: GitApiError | null; discard: () => void; clearDiscardError: () => void; status: FetchStatusResponseData | null; fetchStatusLoading: boolean; - fetchStatusError: string | null; + fetchStatusError: GitApiError | null; fetchStatus: () => void; mergeLoading: boolean; - mergeError: string | null; + mergeError: GitApiError | null; merge: () => void; mergeStatus: FetchMergeStatusResponseData | null; fetchMergeStatusLoading: boolean; - fetchMergeStatusError: string | null; + fetchMergeStatusError: GitApiError | null; fetchMergeStatus: (sourceBranch: string, destinationBranch: string) => void; clearMergeStatus: () => void; pullLoading: boolean; - pullError: string | null; + pullError: GitApiError | null; pull: () => void; opsModalTab: keyof typeof GitOpsTab; opsModalOpen: boolean; diff --git a/app/client/src/git/components/GitContextProvider/hooks/useGitSettings.ts b/app/client/src/git/components/GitContextProvider/hooks/useGitSettings.ts index 54f1699f253c..521c2dac72c6 100644 --- a/app/client/src/git/components/GitContextProvider/hooks/useGitSettings.ts +++ b/app/client/src/git/components/GitContextProvider/hooks/useGitSettings.ts @@ -7,7 +7,7 @@ import { selectProtectedBranches, selectProtectedMode, } from "git/store/selectors/gitSingleArtifactSelectors"; -import type { GitRootState } from "git/store/types"; +import type { GitApiError, GitRootState } from "git/store/types"; import { useMemo } from "react"; import { useDispatch, useSelector } from "react-redux"; @@ -21,7 +21,7 @@ export interface UseGitSettingsReturnValue { autocommitPolling: boolean; protectedBranches: FetchProtectedBranchesResponseData | null; fetchProtectedBranchesLoading: boolean; - fetchProtectedBranchesError: string | null; + fetchProtectedBranchesError: GitApiError | null; fetchProtectedBranches: () => void; protectedMode: boolean; toggleSettingsModal: ( diff --git a/app/client/src/git/components/GitOpsModal/TabDeploy/DumbTabDeploy.tsx b/app/client/src/git/components/GitOpsModal/TabDeploy/DumbTabDeploy.tsx index 19f80c37ed74..44c809b2d5fd 100644 --- a/app/client/src/git/components/GitOpsModal/TabDeploy/DumbTabDeploy.tsx +++ b/app/client/src/git/components/GitOpsModal/TabDeploy/DumbTabDeploy.tsx @@ -41,6 +41,7 @@ import GitConflictError from "git/components/GitConflictError"; import SubmitWrapper from "./SubmitWrapper"; import UpstreamWarning from "./UpstreamWarning"; import noop from "lodash/noop"; +import type { GitApiError } from "git/store/types"; const Section = styled.div` margin-top: 0; @@ -73,12 +74,10 @@ interface DumbTabDeployProps { clearCommitError: () => void; clearDiscardError: () => void; commit: (commitMessage: string) => void; - // ! case: improve error handling - // eslint-disable-next-line @typescript-eslint/no-explicit-any - commitError: any; + commitError: GitApiError | null; currentBranch: string | null; discard: () => void; - discardError: string | null; + discardError: GitApiError | null; isCommitLoading: boolean; isDiscardLoading: boolean; isFetchStatusLoading: boolean; diff --git a/app/client/src/git/components/GitOpsModal/TabDeploy/PushFailedWarning.tsx b/app/client/src/git/components/GitOpsModal/TabDeploy/PushFailedWarning.tsx index 4be7ecd2c299..69297913ad99 100644 --- a/app/client/src/git/components/GitOpsModal/TabDeploy/PushFailedWarning.tsx +++ b/app/client/src/git/components/GitOpsModal/TabDeploy/PushFailedWarning.tsx @@ -1,5 +1,6 @@ import { Callout } from "@appsmith/ads"; import { Text, TextType } from "@appsmith/ads-old"; +import type { GitApiError } from "git/store/types"; import React from "react"; import styled from "styled-components"; @@ -7,9 +8,15 @@ const Container = styled.div` margin: 8px 0 16px; `; -// TODO: Fix this the next time the file is edited -// eslint-disable-next-line @typescript-eslint/no-explicit-any -export default function PushFailedWarning({ closeHandler, error }: any) { +export interface PushFailedWarningProps { + closeHandler: () => void; + error: GitApiError; +} + +export default function PushFailedWarning({ + closeHandler, + error, +}: PushFailedWarningProps) { return ( diff --git a/app/client/src/git/requests/fetchBranchesRequest.types.ts b/app/client/src/git/requests/fetchBranchesRequest.types.ts index 0ea1aeed64cf..f23bcc8ee757 100644 --- a/app/client/src/git/requests/fetchBranchesRequest.types.ts +++ b/app/client/src/git/requests/fetchBranchesRequest.types.ts @@ -1,4 +1,4 @@ -import type { ApiResponse } from "api/ApiResponses"; +import type { ApiResponse } from "api/types"; export interface FetchBranchesRequestParams { pruneBranches?: boolean; diff --git a/app/client/src/git/requests/pullRequest.types.ts b/app/client/src/git/requests/pullRequest.types.ts index fe71cee94a52..57f936391cc8 100644 --- a/app/client/src/git/requests/pullRequest.types.ts +++ b/app/client/src/git/requests/pullRequest.types.ts @@ -1,6 +1,10 @@ -export interface PullResponse { +import type { ApiResponse } from "api/types"; + +export interface PullResponseData { mergeStatus: { isMergeAble: boolean; status: string; // pull merge status }; } + +export type PullResponse = ApiResponse; diff --git a/app/client/src/git/sagas/checkoutBranchSaga.ts b/app/client/src/git/sagas/checkoutBranchSaga.ts index bacb2a283c38..18eaea3532ab 100644 --- a/app/client/src/git/sagas/checkoutBranchSaga.ts +++ b/app/client/src/git/sagas/checkoutBranchSaga.ts @@ -19,6 +19,8 @@ import { FocusEntity, identifyEntityFromPath } from "navigation/FocusEntity"; import { validateResponse } from "sagas/ErrorSagas"; import history from "utils/history"; import type { JSCollectionDataState } from "ee/reducers/entityReducers/jsActionsReducer"; +import log from "loglevel"; +import { captureException } from "@sentry/react"; export default function* checkoutBranchSaga( action: GitArtifactPayloadAction, @@ -110,12 +112,19 @@ export default function* checkoutBranchSaga( } } } - } catch (error) { - yield put( - gitArtifactActions.checkoutBranchError({ - ...basePayload, - error: error as string, - }), - ); + } catch (e) { + if (response && response.responseMeta.error) { + const { error } = response.responseMeta; + + yield put( + gitArtifactActions.checkoutBranchError({ + ...basePayload, + error, + }), + ); + } else { + log.error(e); + captureException(e); + } } } diff --git a/app/client/src/git/sagas/commitSaga.ts b/app/client/src/git/sagas/commitSaga.ts index e609a8f5145a..159021acc145 100644 --- a/app/client/src/git/sagas/commitSaga.ts +++ b/app/client/src/git/sagas/commitSaga.ts @@ -1,3 +1,6 @@ +import { call, put } from "redux-saga/effects"; +import { captureException } from "@sentry/react"; +import log from "loglevel"; import type { CommitInitPayload } from "../store/actions/commitActions"; import { GitArtifactType, GitErrorCodes } from "../constants/enums"; import commitRequest from "../requests/commitRequest"; @@ -7,7 +10,6 @@ import type { } from "../requests/commitRequest.types"; import { gitArtifactActions } from "../store/gitArtifactSlice"; import type { GitArtifactPayloadAction } from "../store/types"; -import { call, put } from "redux-saga/effects"; // internal dependencies import { validateResponse } from "sagas/ErrorSagas"; @@ -17,6 +19,7 @@ export default function* commitSaga( ) { const { artifactType, baseArtifactId } = action.payload; const basePayload = { artifactType, baseArtifactId }; + let response: CommitResponse | undefined; try { @@ -42,23 +45,23 @@ export default function* commitSaga( // ! case for updating lastDeployedAt in application manually? } } - } catch (error) { - if ( - GitErrorCodes.REPO_LIMIT_REACHED === response?.responseMeta?.error?.code - ) { - yield put( - gitArtifactActions.toggleRepoLimitErrorModal({ - ...basePayload, - open: true, - }), - ); - } + } catch (e) { + if (response && response.responseMeta.error) { + const { error } = response.responseMeta; - yield put( - gitArtifactActions.commitError({ - ...basePayload, - error: error as string, - }), - ); + if (error.code === GitErrorCodes.REPO_LIMIT_REACHED) { + yield put( + gitArtifactActions.toggleRepoLimitErrorModal({ + ...basePayload, + open: true, + }), + ); + } + + yield put(gitArtifactActions.commitError({ ...basePayload, error })); + } else { + log.error(e); + captureException(e); + } } } diff --git a/app/client/src/git/sagas/connectSaga.ts b/app/client/src/git/sagas/connectSaga.ts index 16d4ba1cbe0e..b1bfa286e778 100644 --- a/app/client/src/git/sagas/connectSaga.ts +++ b/app/client/src/git/sagas/connectSaga.ts @@ -15,6 +15,8 @@ import { validateResponse } from "sagas/ErrorSagas"; import { fetchPageAction } from "actions/pageActions"; import history from "utils/history"; import { addBranchParam } from "constants/routes"; +import log from "loglevel"; +import { captureException } from "@sentry/react"; export default function* connectSaga( action: GitArtifactPayloadAction, @@ -52,23 +54,28 @@ export default function* connectSaga( // ! case for updating lastDeployedAt in application manually? } } - } catch (error) { - if ( - GitErrorCodes.REPO_LIMIT_REACHED === response?.responseMeta?.error?.code - ) { + } catch (e) { + if (response && response.responseMeta.error) { + const { error } = response.responseMeta; + + if (GitErrorCodes.REPO_LIMIT_REACHED === error.code) { + yield put( + gitArtifactActions.toggleRepoLimitErrorModal({ + ...basePayload, + open: true, + }), + ); + } + yield put( - gitArtifactActions.toggleRepoLimitErrorModal({ + gitArtifactActions.connectError({ ...basePayload, - open: true, + error, }), ); + } else { + log.error(e); + captureException(e); } - - yield put( - gitArtifactActions.connectError({ - ...basePayload, - error: error as string, - }), - ); } } diff --git a/app/client/src/git/sagas/createBranchSaga.ts b/app/client/src/git/sagas/createBranchSaga.ts index 37ce2de1afaf..99604bd86602 100644 --- a/app/client/src/git/sagas/createBranchSaga.ts +++ b/app/client/src/git/sagas/createBranchSaga.ts @@ -10,6 +10,8 @@ import type { GitArtifactPayloadAction } from "../store/types"; // internal dependencies import { validateResponse } from "sagas/ErrorSagas"; +import { captureException } from "@sentry/react"; +import log from "loglevel"; export default function* createBranchSaga( action: GitArtifactPayloadAction, @@ -35,14 +37,26 @@ export default function* createBranchSaga( }), ); - // ! case to switch to the new branch + yield put( + gitArtifactActions.checkoutBranchInit({ + ...basePayload, + branchName: action.payload.branchName, + }), + ); + } + } catch (e) { + if (response && response.responseMeta.error) { + const { error } = response.responseMeta; + + yield put( + gitArtifactActions.createBranchError({ + ...basePayload, + error, + }), + ); + } else { + log.error(e); + captureException(e); } - } catch (error) { - yield put( - gitArtifactActions.createBranchError({ - ...basePayload, - error: error as string, - }), - ); } } diff --git a/app/client/src/git/sagas/deleteBranchSaga.ts b/app/client/src/git/sagas/deleteBranchSaga.ts index 7b138685e6a9..4f6bdde2f7fc 100644 --- a/app/client/src/git/sagas/deleteBranchSaga.ts +++ b/app/client/src/git/sagas/deleteBranchSaga.ts @@ -10,6 +10,8 @@ import { call, put } from "redux-saga/effects"; // internal dependencies import { validateResponse } from "sagas/ErrorSagas"; +import log from "loglevel"; +import { captureException } from "@sentry/react"; export default function* deleteBranchSaga( action: GitArtifactPayloadAction, @@ -35,12 +37,19 @@ export default function* deleteBranchSaga( }), ); } - } catch (error) { - yield put( - gitArtifactActions.deleteBranchError({ - ...basePayload, - error: error as string, - }), - ); + } catch (e) { + if (response && response.responseMeta.error) { + const { error } = response.responseMeta; + + yield put( + gitArtifactActions.deleteBranchError({ + ...basePayload, + error, + }), + ); + } else { + log.error(e); + captureException(e); + } } } diff --git a/app/client/src/git/sagas/fetchBranchesSaga.ts b/app/client/src/git/sagas/fetchBranchesSaga.ts index 5909b62e0c45..465310e01a4f 100644 --- a/app/client/src/git/sagas/fetchBranchesSaga.ts +++ b/app/client/src/git/sagas/fetchBranchesSaga.ts @@ -8,6 +8,8 @@ import { gitArtifactActions } from "git/store/gitArtifactSlice"; import type { GitArtifactPayloadAction } from "../store/types"; import { call, put } from "redux-saga/effects"; import { validateResponse } from "sagas/ErrorSagas"; +import log from "loglevel"; +import { captureException } from "@sentry/react"; export default function* fetchBranchesSaga( action: GitArtifactPayloadAction, @@ -32,12 +34,19 @@ export default function* fetchBranchesSaga( }), ); } - } catch (error) { - yield put( - gitArtifactActions.fetchBranchesError({ - ...basePayload, - error: error as string, - }), - ); + } catch (e) { + if (response && response.responseMeta.error) { + const { error } = response.responseMeta; + + yield put( + gitArtifactActions.fetchBranchesError({ + ...basePayload, + error, + }), + ); + } else { + log.error(e); + captureException(e); + } } } diff --git a/app/client/src/git/sagas/fetchGitMetadataSaga.ts b/app/client/src/git/sagas/fetchGitMetadataSaga.ts index 9f694ff10f36..a91122b83682 100644 --- a/app/client/src/git/sagas/fetchGitMetadataSaga.ts +++ b/app/client/src/git/sagas/fetchGitMetadataSaga.ts @@ -1,7 +1,9 @@ +import { captureException } from "@sentry/react"; import fetchGitMetadataRequest from "git/requests/fetchGitMetadataRequest"; import type { FetchGitMetadataResponse } from "git/requests/fetchGitMetadataRequest.types"; import { gitArtifactActions } from "git/store/gitArtifactSlice"; import type { GitArtifactPayloadAction } from "git/store/types"; +import log from "loglevel"; import { call, put } from "redux-saga/effects"; import { validateResponse } from "sagas/ErrorSagas"; @@ -24,12 +26,19 @@ export default function* fetchGitMetadataSaga( }), ); } - } catch (error) { - yield put( - gitArtifactActions.fetchGitMetadataError({ - ...basePayload, - error: error as string, - }), - ); + } catch (e) { + if (response && response.responseMeta.error) { + const { error } = response.responseMeta; + + yield put( + gitArtifactActions.fetchGitMetadataError({ + ...basePayload, + error, + }), + ); + } else { + log.error(e); + captureException(e); + } } } diff --git a/app/client/src/git/sagas/fetchGlobalProfileSaga.ts b/app/client/src/git/sagas/fetchGlobalProfileSaga.ts index 0443703ad0d5..71e7ca1a9c29 100644 --- a/app/client/src/git/sagas/fetchGlobalProfileSaga.ts +++ b/app/client/src/git/sagas/fetchGlobalProfileSaga.ts @@ -5,6 +5,8 @@ import { gitConfigActions } from "../store/gitConfigSlice"; // internal dependencies import { validateResponse } from "sagas/ErrorSagas"; +import log from "loglevel"; +import { captureException } from "@sentry/react"; export default function* fetchGlobalProfileSaga() { let response: FetchGlobalProfileResponse | undefined; @@ -21,11 +23,18 @@ export default function* fetchGlobalProfileSaga() { }), ); } - } catch (error) { - yield put( - gitConfigActions.fetchGlobalProfileError({ - error: error as string, - }), - ); + } catch (e) { + if (response && response.responseMeta.error) { + const { error } = response.responseMeta; + + yield put( + gitConfigActions.fetchGlobalProfileError({ + error, + }), + ); + } else { + log.error(e); + captureException(e); + } } } diff --git a/app/client/src/git/sagas/fetchLocalProfileSaga.ts b/app/client/src/git/sagas/fetchLocalProfileSaga.ts index a284b7e21d57..c568129beab9 100644 --- a/app/client/src/git/sagas/fetchLocalProfileSaga.ts +++ b/app/client/src/git/sagas/fetchLocalProfileSaga.ts @@ -4,6 +4,8 @@ import { gitArtifactActions } from "git/store/gitArtifactSlice"; import type { GitArtifactPayloadAction } from "../store/types"; import { call, put } from "redux-saga/effects"; import { validateResponse } from "sagas/ErrorSagas"; +import log from "loglevel"; +import { captureException } from "@sentry/react"; export default function* fetchLocalProfileSaga( action: GitArtifactPayloadAction, @@ -24,12 +26,16 @@ export default function* fetchLocalProfileSaga( }), ); } - } catch (error) { - yield put( - gitArtifactActions.fetchLocalProfileError({ - ...basePayload, - error: error as string, - }), - ); + } catch (e) { + if (response && response.responseMeta.error) { + const { error } = response.responseMeta; + + yield put( + gitArtifactActions.fetchLocalProfileError({ ...basePayload, error }), + ); + } else { + log.error(e); + captureException(e); + } } } diff --git a/app/client/src/git/sagas/fetchMergeStatusSaga.ts b/app/client/src/git/sagas/fetchMergeStatusSaga.ts index ebe98d10feb5..684233de206d 100644 --- a/app/client/src/git/sagas/fetchMergeStatusSaga.ts +++ b/app/client/src/git/sagas/fetchMergeStatusSaga.ts @@ -1,3 +1,4 @@ +import { captureException } from "@sentry/react"; import fetchMergeStatusRequest from "git/requests/fetchMergeStatusRequest"; import type { FetchMergeStatusRequestParams, @@ -6,6 +7,7 @@ import type { import type { FetchMergeStatusInitPayload } from "git/store/actions/fetchMergeStatusActions"; import { gitArtifactActions } from "git/store/gitArtifactSlice"; import type { GitArtifactPayloadAction } from "git/store/types"; +import log from "loglevel"; import { call, put } from "redux-saga/effects"; import { validateResponse } from "sagas/ErrorSagas"; @@ -33,12 +35,19 @@ export default function* fetchMergeStatusSaga( }), ); } - } catch (error) { - yield put( - gitArtifactActions.fetchMergeStatusError({ - ...basePayload, - error: error as string, - }), - ); + } catch (e) { + if (response && response.responseMeta.error) { + const { error } = response.responseMeta; + + yield put( + gitArtifactActions.fetchMergeStatusError({ + ...basePayload, + error, + }), + ); + } else { + log.error(e); + captureException(e); + } } } diff --git a/app/client/src/git/sagas/fetchProtectedBranchesSaga.ts b/app/client/src/git/sagas/fetchProtectedBranchesSaga.ts index c0c5d70e7314..9c81123ea26f 100644 --- a/app/client/src/git/sagas/fetchProtectedBranchesSaga.ts +++ b/app/client/src/git/sagas/fetchProtectedBranchesSaga.ts @@ -1,7 +1,9 @@ +import { captureException } from "@sentry/react"; import fetchProtectedBranchesRequest from "git/requests/fetchProtectedBranchesRequest"; import type { FetchProtectedBranchesResponse } from "git/requests/fetchProtectedBranchesRequest.types"; import { gitArtifactActions } from "git/store/gitArtifactSlice"; import type { GitArtifactPayloadAction } from "git/store/types"; +import log from "loglevel"; import { call, put } from "redux-saga/effects"; import { validateResponse } from "sagas/ErrorSagas"; @@ -25,12 +27,19 @@ export default function* fetchProtectedBranchesSaga( }), ); } - } catch (error) { - yield put( - gitArtifactActions.fetchProtectedBranchesError({ - ...basePayload, - error: error as string, - }), - ); + } catch (e) { + if (response && response.responseMeta.error) { + const { error } = response.responseMeta; + + yield put( + gitArtifactActions.fetchProtectedBranchesError({ + ...basePayload, + error, + }), + ); + } else { + log.error(e); + captureException(e); + } } } diff --git a/app/client/src/git/sagas/fetchStatusSaga.ts b/app/client/src/git/sagas/fetchStatusSaga.ts index b0bf5d97e4da..4c714a22c0da 100644 --- a/app/client/src/git/sagas/fetchStatusSaga.ts +++ b/app/client/src/git/sagas/fetchStatusSaga.ts @@ -1,8 +1,10 @@ +import { captureException } from "@sentry/react"; import fetchStatusRequest from "git/requests/fetchStatusRequest"; import type { FetchStatusResponse } from "git/requests/fetchStatusRequest.types"; import type { FetchStatusInitPayload } from "git/store/actions/fetchStatusActions"; import { gitArtifactActions } from "git/store/gitArtifactSlice"; import type { GitArtifactPayloadAction } from "git/store/types"; +import log from "loglevel"; import { call, put } from "redux-saga/effects"; import { validateResponse } from "sagas/ErrorSagas"; @@ -25,15 +27,22 @@ export default function* fetchStatusSaga( }), ); } - } catch (error) { - yield put( - gitArtifactActions.fetchStatusError({ - ...basePayload, - error: error as string, - }), - ); + } catch (e) { + if (response && response.responseMeta.error) { + const { error } = response.responseMeta; - // ! case: BETTER ERROR HANDLING + yield put( + gitArtifactActions.fetchStatusError({ + ...basePayload, + error, + }), + ); + } else { + log.error(e); + captureException(e); + } + + // ! case: better error handling than passing strings // if ((error as Error)?.message?.includes("Auth fail")) { // payload.error = new Error(createMessage(ERROR_GIT_AUTH_FAIL)); // } else if ((error as Error)?.message?.includes("Invalid remote: origin")) { diff --git a/app/client/src/git/sagas/pullSaga.ts b/app/client/src/git/sagas/pullSaga.ts index a5d68032d626..eafb4a5c098b 100644 --- a/app/client/src/git/sagas/pullSaga.ts +++ b/app/client/src/git/sagas/pullSaga.ts @@ -11,6 +11,8 @@ import { validateResponse } from "sagas/ErrorSagas"; import { getCurrentBasePageId } from "selectors/editorSelectors"; import { initEditorAction } from "actions/initActions"; import { APP_MODE } from "entities/App"; +import log from "loglevel"; +import { captureException } from "@sentry/react"; export default function* pullSaga( action: GitArtifactPayloadAction, @@ -41,16 +43,18 @@ export default function* pullSaga( ); } } catch (e) { - // !case: handle this with error - // if (triggeredFromBottomBar) { - // yield put(setIsGitErrorPopupVisible({ isVisible: true })); - // } - - yield put( - gitArtifactActions.pullError({ - ...basePayload, - error: e as string, - }), - ); + if (response && response.responseMeta.error) { + const { error } = response.responseMeta; + + // !case: handle this with error + // if (triggeredFromBottomBar) { + // yield put(setIsGitErrorPopupVisible({ isVisible: true })); + // } + + yield put(gitArtifactActions.pullError({ ...basePayload, error })); + } else { + log.error(e); + captureException(e); + } } } diff --git a/app/client/src/git/sagas/triggerAutocommitSaga.ts b/app/client/src/git/sagas/triggerAutocommitSaga.ts index 12c766fe8f10..c69452acf94b 100644 --- a/app/client/src/git/sagas/triggerAutocommitSaga.ts +++ b/app/client/src/git/sagas/triggerAutocommitSaga.ts @@ -28,6 +28,8 @@ import { } from "redux-saga/effects"; import type { Task } from "redux-saga"; import { validateResponse } from "sagas/ErrorSagas"; +import log from "loglevel"; +import { captureException } from "@sentry/react"; const AUTOCOMMIT_POLL_DELAY = 1000; const AUTOCOMMIT_WHITELISTED_STATES = [ @@ -66,25 +68,30 @@ function* pollAutocommitProgressSaga(params: PollAutocommitProgressParams) { if (triggerResponse && isValidResponse) { yield put(gitArtifactActions.triggerAutocommitSuccess(basePayload)); } - } catch (error) { - yield put( - gitArtifactActions.triggerAutocommitError({ - ...basePayload, - error: error as string, - }), - ); + } catch (e) { + if (triggerResponse && triggerResponse.responseMeta.error) { + const { error } = triggerResponse.responseMeta; + + yield put( + gitArtifactActions.triggerAutocommitError({ ...basePayload, error }), + ); + } else { + log.error(e); + captureException(e); + } } + let progressResponse: FetchAutocommitProgressResponse | null = null; + try { if (isAutocommitHappening(triggerResponse?.data)) { yield put(gitArtifactActions.pollAutocommitProgressStart(basePayload)); while (true) { - yield put(gitArtifactActions.fetchAutocommitProgressInit(basePayload)); - const progressResponse: FetchAutocommitProgressResponse = yield call( - fetchAutocommitProgressRequest, - baseArtifactId, + progressResponse = yield put( + gitArtifactActions.fetchAutocommitProgressInit(basePayload), ); + yield call(fetchAutocommitProgressRequest, baseArtifactId); const isValidResponse: boolean = yield validateResponse(progressResponse); @@ -101,14 +108,22 @@ function* pollAutocommitProgressSaga(params: PollAutocommitProgressParams) { } else { yield put(gitArtifactActions.pollAutocommitProgressStop(basePayload)); } - } catch (error) { + } catch (e) { yield put(gitArtifactActions.pollAutocommitProgressStop(basePayload)); - yield put( - gitArtifactActions.fetchAutocommitProgressError({ - ...basePayload, - error: error as string, - }), - ); + + if (progressResponse && progressResponse.responseMeta.error) { + const { error } = progressResponse.responseMeta; + + yield put( + gitArtifactActions.fetchAutocommitProgressError({ + ...basePayload, + error, + }), + ); + } else { + log.error(e); + captureException(e); + } } } diff --git a/app/client/src/git/sagas/updateGlobalProfileSaga.ts b/app/client/src/git/sagas/updateGlobalProfileSaga.ts index 967d6228a0a0..2ce98fe47fb4 100644 --- a/app/client/src/git/sagas/updateGlobalProfileSaga.ts +++ b/app/client/src/git/sagas/updateGlobalProfileSaga.ts @@ -10,6 +10,8 @@ import { gitConfigActions } from "../store/gitConfigSlice"; // internal dependencies import { validateResponse } from "sagas/ErrorSagas"; +import log from "loglevel"; +import { captureException } from "@sentry/react"; export default function* updateGlobalProfileSaga( action: PayloadAction, @@ -30,9 +32,14 @@ export default function* updateGlobalProfileSaga( yield put(gitConfigActions.updateGlobalProfileSuccess()); yield put(gitConfigActions.fetchGlobalProfileInit()); } - } catch (error) { - yield put( - gitConfigActions.updateGlobalProfileError({ error: error as string }), - ); + } catch (e) { + if (response && response.responseMeta.error) { + const { error } = response.responseMeta; + + yield put(gitConfigActions.updateGlobalProfileError({ error })); + } else { + log.error(e); + captureException(e); + } } } diff --git a/app/client/src/git/sagas/updateLocalProfileSaga.ts b/app/client/src/git/sagas/updateLocalProfileSaga.ts index d2a9c0243a15..74579562b058 100644 --- a/app/client/src/git/sagas/updateLocalProfileSaga.ts +++ b/app/client/src/git/sagas/updateLocalProfileSaga.ts @@ -8,6 +8,8 @@ import { gitArtifactActions } from "../store/gitArtifactSlice"; import type { GitArtifactPayloadAction } from "../store/types"; import { call, put } from "redux-saga/effects"; import { validateResponse } from "sagas/ErrorSagas"; +import log from "loglevel"; +import { captureException } from "@sentry/react"; export default function* updateLocalProfileSaga( action: GitArtifactPayloadAction, @@ -31,12 +33,16 @@ export default function* updateLocalProfileSaga( yield put(gitArtifactActions.updateLocalProfileSuccess(basePayload)); yield put(gitArtifactActions.fetchLocalProfileInit(basePayload)); } - } catch (error) { - yield put( - gitArtifactActions.updateLocalProfileError({ - ...basePayload, - error: error as string, - }), - ); + } catch (e) { + if (response && response.responseMeta.error) { + const { error } = response.responseMeta; + + yield put( + gitArtifactActions.updateLocalProfileError({ ...basePayload, error }), + ); + } else { + log.error(e); + captureException(e); + } } } diff --git a/app/client/src/git/store/types.ts b/app/client/src/git/store/types.ts index c15d52dc5107..f023e916ea2e 100644 --- a/app/client/src/git/store/types.ts +++ b/app/client/src/git/store/types.ts @@ -13,42 +13,48 @@ import type { FetchStatusResponseData } from "git/requests/fetchStatusRequest.ty import type { FetchMergeStatusResponseData } from "git/requests/fetchMergeStatusRequest.types"; import type { FetchGitMetadataResponseData } from "git/requests/fetchGitMetadataRequest.types"; import type { FetchProtectedBranchesResponseData } from "git/requests/fetchProtectedBranchesRequest.types"; +import type { ApiResponseError } from "api/types"; export type GitSSHKey = Record; -export interface AsyncState { +export interface GitApiError extends ApiResponseError { + errorType?: string; + referenceDoc?: string; + title?: string; +} +interface GitAsyncState { value: T | null; loading: boolean; - error: string | null; + error: GitApiError | null; } -interface AsyncStateWithoutValue { +interface GitAsyncStateWithoutValue { loading: boolean; - error: string | null; + error: GitApiError | null; } export interface GitSingleArtifactAPIResponsesReduxState { - metadata: AsyncState; - connect: AsyncStateWithoutValue; - status: AsyncState; - commit: AsyncStateWithoutValue; - pull: AsyncStateWithoutValue; - discard: AsyncStateWithoutValue; - mergeStatus: AsyncState; - merge: AsyncStateWithoutValue; - branches: AsyncState; - checkoutBranch: AsyncStateWithoutValue; - createBranch: AsyncStateWithoutValue; - deleteBranch: AsyncStateWithoutValue; - localProfile: AsyncState; - updateLocalProfile: AsyncStateWithoutValue; - disconnect: AsyncStateWithoutValue; - protectedBranches: AsyncState; - updateProtectedBranches: AsyncStateWithoutValue; - autocommitProgress: AsyncStateWithoutValue; - toggleAutocommit: AsyncStateWithoutValue; - triggerAutocommit: AsyncStateWithoutValue; - sshKey: AsyncState; - generateSSHKey: AsyncStateWithoutValue; + metadata: GitAsyncState; + connect: GitAsyncStateWithoutValue; + status: GitAsyncState; + commit: GitAsyncStateWithoutValue; + pull: GitAsyncStateWithoutValue; + discard: GitAsyncStateWithoutValue; + mergeStatus: GitAsyncState; + merge: GitAsyncStateWithoutValue; + branches: GitAsyncState; + checkoutBranch: GitAsyncStateWithoutValue; + createBranch: GitAsyncStateWithoutValue; + deleteBranch: GitAsyncStateWithoutValue; + localProfile: GitAsyncState; + updateLocalProfile: GitAsyncStateWithoutValue; + disconnect: GitAsyncStateWithoutValue; + protectedBranches: GitAsyncState; + updateProtectedBranches: GitAsyncStateWithoutValue; + autocommitProgress: GitAsyncStateWithoutValue; + toggleAutocommit: GitAsyncStateWithoutValue; + triggerAutocommit: GitAsyncStateWithoutValue; + sshKey: GitAsyncState; + generateSSHKey: GitAsyncStateWithoutValue; } export interface GitSingleArtifactUIReduxState { @@ -86,8 +92,8 @@ export interface GitArtifactReduxState { } export interface GitConfigReduxState { - globalProfile: AsyncState; - updateGlobalProfile: AsyncStateWithoutValue; + globalProfile: GitAsyncState; + updateGlobalProfile: GitAsyncStateWithoutValue; } export interface GitRootState { @@ -103,7 +109,7 @@ export interface GitArtifactBasePayload { } export interface GitAsyncErrorPayload { - error: string; + error: GitApiError; } export interface GitAsyncSuccessPayload { From 245cb9ba19c33b70db8c0381ad45e668e04d6181 Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Fri, 13 Dec 2024 16:55:29 +0800 Subject: [PATCH 044/143] chore: minor changes in error handling --- ...iledWarning.tsx => DiscardFailedError.tsx} | 6 ++-- .../GitOpsModal/TabDeploy/DumbTabDeploy.tsx | 14 +++----- ...hFailedWarning.tsx => PushFailedError.tsx} | 6 ++-- .../GitOpsModal/TabDeploy/UpstreamWarning.tsx | 33 ------------------- .../GitOpsModal/TabMerge/DumbTabMerge.tsx | 7 ++-- 5 files changed, 13 insertions(+), 53 deletions(-) rename app/client/src/git/components/GitOpsModal/TabDeploy/{DiscardFailedWarning.tsx => DiscardFailedError.tsx} (81%) rename app/client/src/git/components/GitOpsModal/TabDeploy/{PushFailedWarning.tsx => PushFailedError.tsx} (85%) delete mode 100644 app/client/src/git/components/GitOpsModal/TabDeploy/UpstreamWarning.tsx diff --git a/app/client/src/git/components/GitOpsModal/TabDeploy/DiscardFailedWarning.tsx b/app/client/src/git/components/GitOpsModal/TabDeploy/DiscardFailedError.tsx similarity index 81% rename from app/client/src/git/components/GitOpsModal/TabDeploy/DiscardFailedWarning.tsx rename to app/client/src/git/components/GitOpsModal/TabDeploy/DiscardFailedError.tsx index d5397c625b32..740193af9038 100644 --- a/app/client/src/git/components/GitOpsModal/TabDeploy/DiscardFailedWarning.tsx +++ b/app/client/src/git/components/GitOpsModal/TabDeploy/DiscardFailedError.tsx @@ -2,18 +2,18 @@ import React from "react"; import styled from "styled-components"; import { Callout } from "@appsmith/ads"; import type { CalloutProps } from "@appsmith/ads"; +import type { GitApiError } from "git/store/types"; const Container = styled.div` margin: 8px 0 16px; `; -export default function DiscardFailedWarning({ +export default function DiscardFailedError({ closeHandler, error, }: { closeHandler: () => void; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - error: any; + error: GitApiError; }) { const calloutOptions: CalloutProps = { isClosable: true, diff --git a/app/client/src/git/components/GitOpsModal/TabDeploy/DumbTabDeploy.tsx b/app/client/src/git/components/GitOpsModal/TabDeploy/DumbTabDeploy.tsx index 44c809b2d5fd..ea518facdf88 100644 --- a/app/client/src/git/components/GitOpsModal/TabDeploy/DumbTabDeploy.tsx +++ b/app/client/src/git/components/GitOpsModal/TabDeploy/DumbTabDeploy.tsx @@ -34,12 +34,11 @@ import { isEllipsisActive } from "utils/helpers"; import AnalyticsUtil from "ee/utils/AnalyticsUtil"; import GIT_ERROR_CODES from "constants/GitErrorCodes"; import DiscardChangesWarning from "./DiscardChangesWarning"; -import PushFailedWarning from "./PushFailedWarning"; -import DiscardFailedWarning from "./DiscardFailedWarning"; +import PushFailedError from "./PushFailedError"; +import DiscardFailedError from "./DiscardFailedError"; import GitStatus from "git/components/GitStatus"; import GitConflictError from "git/components/GitConflictError"; import SubmitWrapper from "./SubmitWrapper"; -import UpstreamWarning from "./UpstreamWarning"; import noop from "lodash/noop"; import type { GitApiError } from "git/store/types"; @@ -314,14 +313,9 @@ function DumbTabDeploy({ value={commitMessageDisplay} /> - {/* // ! case: should be removed from here */} - {/* {isFetchStatusLoading && ( - - )} */} - {pullRequired && !isConflicting && } {isConflicting && } {commitError && ( - @@ -347,7 +341,7 @@ function DumbTabDeploy({
{discardError && ( - diff --git a/app/client/src/git/components/GitOpsModal/TabDeploy/PushFailedWarning.tsx b/app/client/src/git/components/GitOpsModal/TabDeploy/PushFailedError.tsx similarity index 85% rename from app/client/src/git/components/GitOpsModal/TabDeploy/PushFailedWarning.tsx rename to app/client/src/git/components/GitOpsModal/TabDeploy/PushFailedError.tsx index 69297913ad99..9fa5a8049e74 100644 --- a/app/client/src/git/components/GitOpsModal/TabDeploy/PushFailedWarning.tsx +++ b/app/client/src/git/components/GitOpsModal/TabDeploy/PushFailedError.tsx @@ -8,15 +8,15 @@ const Container = styled.div` margin: 8px 0 16px; `; -export interface PushFailedWarningProps { +export interface PushFailedErrorProps { closeHandler: () => void; error: GitApiError; } -export default function PushFailedWarning({ +export default function PushFailedError({ closeHandler, error, -}: PushFailedWarningProps) { +}: PushFailedErrorProps) { return ( diff --git a/app/client/src/git/components/GitOpsModal/TabDeploy/UpstreamWarning.tsx b/app/client/src/git/components/GitOpsModal/TabDeploy/UpstreamWarning.tsx deleted file mode 100644 index 61d5e1244316..000000000000 --- a/app/client/src/git/components/GitOpsModal/TabDeploy/UpstreamWarning.tsx +++ /dev/null @@ -1,33 +0,0 @@ -import React from "react"; - -import { Callout } from "@appsmith/ads"; -import AnalyticsUtil from "ee/utils/AnalyticsUtil"; -import { - createMessage, - GIT_UPSTREAM_CHANGES, - READ_DOCUMENTATION, -} from "ee/constants/messages"; - -export default function UpstreamWarning() { - return ( - { - AnalyticsUtil.logEvent("GS_GIT_DOCUMENTATION_LINK_CLICK", { - source: "UPSTREAM_CHANGES_LINK_ON_GIT_DEPLOY_MODAL", - }); - }, - // ! case: should be a constant - to: "https://docs.appsmith.com/advanced-concepts/version-control-with-git", - target: "_blank", - }, - ]} - style={{ marginBottom: 12 }} - > - {createMessage(GIT_UPSTREAM_CHANGES)} - - ); -} diff --git a/app/client/src/git/components/GitOpsModal/TabMerge/DumbTabMerge.tsx b/app/client/src/git/components/GitOpsModal/TabMerge/DumbTabMerge.tsx index ecaa99775405..c682fb13b492 100644 --- a/app/client/src/git/components/GitOpsModal/TabMerge/DumbTabMerge.tsx +++ b/app/client/src/git/components/GitOpsModal/TabMerge/DumbTabMerge.tsx @@ -34,6 +34,7 @@ import { noop } from "lodash"; import type { FetchBranchesResponseData } from "git/requests/fetchBranchesRequest.types"; import type { FetchProtectedBranchesResponseData } from "git/requests/fetchProtectedBranchesRequest.types"; import type { FetchMergeStatusResponseData } from "git/requests/fetchMergeStatusRequest.types"; +import type { GitApiError } from "git/store/types"; const Container = styled.div` min-height: 360px; @@ -74,9 +75,7 @@ interface DumbTabMergeProps { isMergeLoading: boolean; isStatusClean: boolean; merge: (sourceBranch: string, destinationBranch: string) => void; - // ! case: should add proper type - // eslint-disable-next-line @typescript-eslint/no-explicit-any - mergeError: any; + mergeError: GitApiError | null; mergeStatus: FetchMergeStatusResponseData | null; protectedBranches: FetchProtectedBranchesResponseData | null; } @@ -125,7 +124,7 @@ export default function DumbTabMerge({ status = MergeStatusState.NOT_MERGEABLE; } else if (mergeError) { status = MergeStatusState.ERROR; - message = mergeError.error.message; + message = mergeError.message; } // should check after added error code for conflicting From cc35140b810ab0b6a9fa9ff2c7026ee698e8a7d3 Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Fri, 13 Dec 2024 17:09:30 +0800 Subject: [PATCH 045/143] chore: review fixes --- .../git/artifactHelpers/application/statusTransformer.ts | 2 +- .../components/GitConflictError/DumbGitConflictError.tsx | 2 +- .../GitConflictErrorModal/DumbGitConflictErrorModal.tsx | 6 +++--- .../src/git/components/GitConflictErrorModal/index.tsx | 2 +- .../components/GitOpsModal/TabDeploy/DumbTabDeploy.tsx | 2 +- .../components/GitOpsModal/TabDeploy/SubmitWrapper.tsx | 5 ++++- app/client/src/git/components/GitStatus/DumbGitStatus.tsx | 8 ++++++-- .../Editor/gitSync/components/DiscardChangesWarning.tsx | 7 ++++--- 8 files changed, 21 insertions(+), 13 deletions(-) diff --git a/app/client/src/git/artifactHelpers/application/statusTransformer.ts b/app/client/src/git/artifactHelpers/application/statusTransformer.ts index 8d5193373a6b..1923d186c4a1 100644 --- a/app/client/src/git/artifactHelpers/application/statusTransformer.ts +++ b/app/client/src/git/artifactHelpers/application/statusTransformer.ts @@ -111,7 +111,7 @@ function statusPageTransformer(status: FetchStatusResponseData) { } if (jsObjectDefs.length > 0) { - const subject = jsObjectDefs.length === 1 ? "query" : "queries"; + const subject = jsObjectDefs.length === 1 ? "jsObject" : "jsObjects"; children.push(createTreeNodeGroup(jsObjectDefs, subject)); } diff --git a/app/client/src/git/components/GitConflictError/DumbGitConflictError.tsx b/app/client/src/git/components/GitConflictError/DumbGitConflictError.tsx index 0813971f04d5..220d051f9107 100644 --- a/app/client/src/git/components/GitConflictError/DumbGitConflictError.tsx +++ b/app/client/src/git/components/GitConflictError/DumbGitConflictError.tsx @@ -36,7 +36,7 @@ export default function DumbGitConflictError({ repoUrl, }: DumbGitConflictErrorProps) { const handleClickOnOpenRepo = useCallback(() => { - window.open(repoUrl, "_blank"); + window.open(repoUrl, "_blank", "noopener,noreferrer"); }, [repoUrl]); const calloutLinks = useMemo( diff --git a/app/client/src/git/components/GitConflictErrorModal/DumbGitConflictErrorModal.tsx b/app/client/src/git/components/GitConflictErrorModal/DumbGitConflictErrorModal.tsx index e30768f3316b..83d983d9866a 100644 --- a/app/client/src/git/components/GitConflictErrorModal/DumbGitConflictErrorModal.tsx +++ b/app/client/src/git/components/GitConflictErrorModal/DumbGitConflictErrorModal.tsx @@ -39,12 +39,12 @@ const StyledGitErrorPopup = styled.div` `; interface DumbGitConflictErrorModalProps { - isConfictErrorModalOpen?: boolean; + isConflictErrorModalOpen?: boolean; toggleConflictErrorModal?: (open: boolean) => void; } function DumbGitConflictErrorModal({ - isConfictErrorModalOpen = false, + isConflictErrorModalOpen = false, toggleConflictErrorModal = noop, }: DumbGitConflictErrorModalProps) { const handleClose = useCallback(() => { @@ -55,7 +55,7 @@ function DumbGitConflictErrorModal({ ); diff --git a/app/client/src/git/components/GitOpsModal/TabDeploy/DumbTabDeploy.tsx b/app/client/src/git/components/GitOpsModal/TabDeploy/DumbTabDeploy.tsx index ea518facdf88..ee58659d9be5 100644 --- a/app/client/src/git/components/GitOpsModal/TabDeploy/DumbTabDeploy.tsx +++ b/app/client/src/git/components/GitOpsModal/TabDeploy/DumbTabDeploy.tsx @@ -62,7 +62,7 @@ const CommitLabelText = styled(Text)` const CommitLabelBranchText = styled(Text)` overflow: hidden; - textoverflow: ellipsis; + text-overflow: ellipsis; whitespace: nowrap; `; diff --git a/app/client/src/git/components/GitOpsModal/TabDeploy/SubmitWrapper.tsx b/app/client/src/git/components/GitOpsModal/TabDeploy/SubmitWrapper.tsx index 93e98dbdb36e..3e11cf40e0e4 100644 --- a/app/client/src/git/components/GitOpsModal/TabDeploy/SubmitWrapper.tsx +++ b/app/client/src/git/components/GitOpsModal/TabDeploy/SubmitWrapper.tsx @@ -17,7 +17,10 @@ export default function SubmitWrapper({ ? e.metaKey && e.key === "Enter" : e.ctrlKey && e.key === "Enter"; - if (triggerSubmit) onSubmit(); + if (triggerSubmit) { + e.preventDefault(); + onSubmit(); + } }, [onSubmit], ); diff --git a/app/client/src/git/components/GitStatus/DumbGitStatus.tsx b/app/client/src/git/components/GitStatus/DumbGitStatus.tsx index 370f8fe47c03..eab2719f8ab5 100644 --- a/app/client/src/git/components/GitStatus/DumbGitStatus.tsx +++ b/app/client/src/git/components/GitStatus/DumbGitStatus.tsx @@ -4,7 +4,11 @@ import type { StatusTreeStruct } from "./StatusTree"; import StatusTree from "./StatusTree"; import { Text } from "@appsmith/ads"; import { createMessage } from "@appsmith/ads-old"; -import { CHANGES_SINCE_LAST_DEPLOYMENT } from "ee/constants/messages"; +import { + CHANGES_SINCE_LAST_DEPLOYMENT, + FETCH_GIT_STATUS, +} from "ee/constants/messages"; +import StatusLoader from "pages/Editor/gitSync/components/StatusLoader"; const noopStatusTransformer = () => null; @@ -28,7 +32,7 @@ export default function DumbGitStatus({ }, [isFetchStatusLoading, status, statusTransformer]); if (isFetchStatusLoading) { - return
Loading...
; + return ; } if (!status || status.isClean || !statusTree) { diff --git a/app/client/src/pages/Editor/gitSync/components/DiscardChangesWarning.tsx b/app/client/src/pages/Editor/gitSync/components/DiscardChangesWarning.tsx index 730a419655db..c940996def18 100644 --- a/app/client/src/pages/Editor/gitSync/components/DiscardChangesWarning.tsx +++ b/app/client/src/pages/Editor/gitSync/components/DiscardChangesWarning.tsx @@ -12,9 +12,10 @@ const Container = styled.div` `; export default function DiscardChangesWarning({ - onCloseDiscardChangesWarning, // TODO: Fix this the next time the file is edited - // eslint-disable-next-line @typescript-eslint/no-explicit-any -}: any) { + onCloseDiscardChangesWarning, +}: { + onCloseDiscardChangesWarning: () => void; +}) { const discardDocUrl = "https://docs.appsmith.com/advanced-concepts/version-control-with-git/commit-and-push"; From 8dc482f3bfe418f4d646c83be42352dab46b3cab Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Fri, 13 Dec 2024 17:21:40 +0800 Subject: [PATCH 046/143] fix: review comments --- .../git/components/GitOpsModal/TabDeploy/DumbTabDeploy.tsx | 4 ++-- .../git/components/GitOpsModal/TabDeploy/PushFailedError.tsx | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/client/src/git/components/GitOpsModal/TabDeploy/DumbTabDeploy.tsx b/app/client/src/git/components/GitOpsModal/TabDeploy/DumbTabDeploy.tsx index ee58659d9be5..87cfe05540c5 100644 --- a/app/client/src/git/components/GitOpsModal/TabDeploy/DumbTabDeploy.tsx +++ b/app/client/src/git/components/GitOpsModal/TabDeploy/DumbTabDeploy.tsx @@ -271,14 +271,14 @@ function DumbTabDeploy({ content={currentBranch} isDisabled={ !isEllipsisActive( - document.getElementById("git-branch-name-commmit-tab"), + document.getElementById("git-branch-name-commit-tab"), ) } >  {currentBranch} diff --git a/app/client/src/git/components/GitOpsModal/TabDeploy/PushFailedError.tsx b/app/client/src/git/components/GitOpsModal/TabDeploy/PushFailedError.tsx index 9fa5a8049e74..25fb748928cd 100644 --- a/app/client/src/git/components/GitOpsModal/TabDeploy/PushFailedError.tsx +++ b/app/client/src/git/components/GitOpsModal/TabDeploy/PushFailedError.tsx @@ -18,7 +18,7 @@ export default function PushFailedError({ error, }: PushFailedErrorProps) { return ( - + <> {error.errorType} From 801b06b734fec2423efbfa66b52a8561a879fed9 Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Fri, 13 Dec 2024 18:33:14 +0800 Subject: [PATCH 047/143] chore: minor fixes for build failures --- .../hooks/useGitContextValue.ts | 4 ++++ .../GitDefaultBranch/DumbGitDefaultBranch.tsx | 16 ++++++++-------- .../selectors/gitSingleArtifactSelectors.ts | 6 ++++++ 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/app/client/src/git/components/GitContextProvider/hooks/useGitContextValue.ts b/app/client/src/git/components/GitContextProvider/hooks/useGitContextValue.ts index f39b27a40722..ad529704dc4c 100644 --- a/app/client/src/git/components/GitContextProvider/hooks/useGitContextValue.ts +++ b/app/client/src/git/components/GitContextProvider/hooks/useGitContextValue.ts @@ -35,6 +35,8 @@ export interface GitContextValue UseGitSettingsReturnValue, UseGitBranchesReturnValue, UseGitPermissionsReturnValue { + artifactType: keyof typeof GitArtifactType; + baseArtifactId: string; artifact: ApplicationPayload | null; statusTransformer: ( status: FetchStatusResponseData, @@ -65,6 +67,8 @@ export default function useGitContextValue({ }); return { + artifactType, + baseArtifactId, statusTransformer, artifact, ...useGitMetadataReturnValue, diff --git a/app/client/src/git/components/GitDefaultBranch/DumbGitDefaultBranch.tsx b/app/client/src/git/components/GitDefaultBranch/DumbGitDefaultBranch.tsx index ea336115d2d8..3acc26b0e5b7 100644 --- a/app/client/src/git/components/GitDefaultBranch/DumbGitDefaultBranch.tsx +++ b/app/client/src/git/components/GitDefaultBranch/DumbGitDefaultBranch.tsx @@ -1,19 +1,19 @@ import { - APPSMITH_ENTERPRISE, + // APPSMITH_ENTERPRISE, DEFAULT_BRANCH, DEFAULT_BRANCH_DESC, UPDATE, createMessage, } from "ee/constants/messages"; // import { updateGitDefaultBranch } from "actions/gitSyncActions"; -import { Button, Link, Option, Select, Text } from "@appsmith/ads"; +import { Button, Option, Select, Text } from "@appsmith/ads"; import React, { useEffect, useMemo, useState } from "react"; // import { useDispatch, useSelector } from "react-redux"; // import { getGitBranches } from "selectors/gitSyncSelectors"; import styled from "styled-components"; // import { useFeatureFlag } from "utils/hooks/useFeatureFlag"; // import { FEATURE_FLAG } from "ee/entities/FeatureFlag"; -import { useAppsmithEnterpriseLink } from "./hooks"; +// import { useAppsmithEnterpriseLink } from "./hooks"; import AnalyticsUtil from "ee/utils/AnalyticsUtil"; import type { FetchBranchesResponseData } from "git/requests/fetchBranchesRequest.types"; @@ -61,9 +61,9 @@ function DumbGitDefaultBranch({ return defaultBranch?.branchName; }, [branches]); - const enterprisePricingLink = useAppsmithEnterpriseLink( - "git_branch_protection", - ); + // const enterprisePricingLink = useAppsmithEnterpriseLink( + // "git_branch_protection", + // ); useEffect( function selectedValueOnInitEffect() { @@ -103,14 +103,14 @@ function DumbGitDefaultBranch({ {!isGitProtectedFeatureLicensed && ( To change your default branch, try{" "} - {createMessage(APPSMITH_ENTERPRISE)} - + */} )} diff --git a/app/client/src/git/store/selectors/gitSingleArtifactSelectors.ts b/app/client/src/git/store/selectors/gitSingleArtifactSelectors.ts index 03a36c5b3776..86cd5216af76 100644 --- a/app/client/src/git/store/selectors/gitSingleArtifactSelectors.ts +++ b/app/client/src/git/store/selectors/gitSingleArtifactSelectors.ts @@ -138,3 +138,9 @@ export const selectSettingsModalTab = ( state: GitRootState, artifactDef: GitArtifactDef, ) => selectSingleArtifact(state, artifactDef)?.ui.settingsModalTab; + +// default branch +export const selectDefaultBranch = ( + state: GitRootState, + artifactDef: GitArtifactDef, +) => selectGitMetadata(state, artifactDef)?.value?.defaultBranchName; From ec461fde26da90af2f365fb36f49e3758c14cb96 Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Fri, 13 Dec 2024 23:07:15 +0800 Subject: [PATCH 048/143] chore: review fixes --- .../application/statusTransformer.ts | 2 +- .../ConflictErrorView.tsx} | 6 ++-- .../index.tsx | 6 ++-- .../ConflictErrorModalView.tsx} | 13 ++++---- .../index.tsx | 6 ++-- .../hooks/useGitContextValue.ts | 2 +- app/client/src/git/components/GitModals.tsx | 8 ++--- .../OpsModalView.tsx} | 8 ++--- .../TabDeploy/DeployPreview.tsx | 0 .../TabDeploy/DiscardChangesWarning.tsx | 0 .../TabDeploy/DiscardFailedError.tsx | 0 .../TabDeploy/PushFailedError.tsx | 0 .../TabDeploy/SubmitWrapper.tsx | 0 .../TabDeploy/TabDeployView.tsx} | 16 +++++----- .../TabDeploy/index.tsx | 4 +-- .../TabMerge/MergeStatus.tsx | 0 .../TabMerge/MergeSuccessIndicator.tsx | 0 .../TabMerge/TabMergeView.tsx} | 10 +++---- .../TabMerge/index.tsx | 4 +-- .../{GitOpsModal => OpsModal}/index.tsx | 6 ++-- .../BranchButton/BranchList.tsx | 0 .../BranchButton/index.tsx | 0 .../ConnectButton.test.tsx | 0 .../ConnectButton.tsx | 0 .../QuickActionButton.test.tsx | 0 .../QuickActionButton.tsx | 0 .../QuickActionsView.test.tsx} | 30 +++++++++---------- .../QuickActionsView.tsx} | 8 ++--- .../helpers/getPullButtonStatus.test.ts | 0 .../helpers/getPullButtonStatus.ts | 0 .../hooks/useStatusChangeCount.ts | 0 .../index.tsx | 8 ++--- .../StatusChangesView.tsx} | 6 ++-- .../StatusLoader.tsx | 0 .../StatusTree.tsx | 0 .../{GitStatus => StatusChanges}/index.tsx | 8 ++--- .../src/git/components/connect/GitTest.tsx | 7 ----- app/client/src/git/components/index.tsx | 2 ++ .../gitSync/components/DeployPreview.tsx | 1 + 39 files changed, 79 insertions(+), 82 deletions(-) rename app/client/src/git/components/{GitConflictError/DumbGitConflictError.tsx => ConflictError/ConflictErrorView.tsx} (92%) rename app/client/src/git/components/{GitConflictError => ConflictError}/index.tsx (68%) rename app/client/src/git/components/{GitConflictErrorModal/DumbGitConflictErrorModal.tsx => ConflictErrorModal/ConflictErrorModalView.tsx} (88%) rename app/client/src/git/components/{GitConflictErrorModal => ConflictErrorModal}/index.tsx (66%) rename app/client/src/git/components/{GitOpsModal/DumbGitOpsModal.tsx => OpsModal/OpsModalView.tsx} (95%) rename app/client/src/git/components/{GitOpsModal => OpsModal}/TabDeploy/DeployPreview.tsx (100%) rename app/client/src/git/components/{GitOpsModal => OpsModal}/TabDeploy/DiscardChangesWarning.tsx (100%) rename app/client/src/git/components/{GitOpsModal => OpsModal}/TabDeploy/DiscardFailedError.tsx (100%) rename app/client/src/git/components/{GitOpsModal => OpsModal}/TabDeploy/PushFailedError.tsx (100%) rename app/client/src/git/components/{GitOpsModal => OpsModal}/TabDeploy/SubmitWrapper.tsx (100%) rename app/client/src/git/components/{GitOpsModal/TabDeploy/DumbTabDeploy.tsx => OpsModal/TabDeploy/TabDeployView.tsx} (97%) rename app/client/src/git/components/{GitOpsModal => OpsModal}/TabDeploy/index.tsx (95%) rename app/client/src/git/components/{GitOpsModal => OpsModal}/TabMerge/MergeStatus.tsx (100%) rename app/client/src/git/components/{GitOpsModal => OpsModal}/TabMerge/MergeSuccessIndicator.tsx (100%) rename app/client/src/git/components/{GitOpsModal/TabMerge/DumbTabMerge.tsx => OpsModal/TabMerge/TabMergeView.tsx} (97%) rename app/client/src/git/components/{GitOpsModal => OpsModal}/TabMerge/index.tsx (94%) rename app/client/src/git/components/{GitOpsModal => OpsModal}/index.tsx (82%) rename app/client/src/git/components/{GitQuickActions => QuickActions}/BranchButton/BranchList.tsx (100%) rename app/client/src/git/components/{GitQuickActions => QuickActions}/BranchButton/index.tsx (100%) rename app/client/src/git/components/{GitQuickActions => QuickActions}/ConnectButton.test.tsx (100%) rename app/client/src/git/components/{GitQuickActions => QuickActions}/ConnectButton.tsx (100%) rename app/client/src/git/components/{GitQuickActions => QuickActions}/QuickActionButton.test.tsx (100%) rename app/client/src/git/components/{GitQuickActions => QuickActions}/QuickActionButton.tsx (100%) rename app/client/src/git/components/{GitQuickActions/DumbGitQuickActions.test.tsx => QuickActions/QuickActionsView.test.tsx} (92%) rename app/client/src/git/components/{GitQuickActions/DumbGitQuickActions.tsx => QuickActions/QuickActionsView.tsx} (97%) rename app/client/src/git/components/{GitQuickActions => QuickActions}/helpers/getPullButtonStatus.test.ts (100%) rename app/client/src/git/components/{GitQuickActions => QuickActions}/helpers/getPullButtonStatus.ts (100%) rename app/client/src/git/components/{GitQuickActions => QuickActions}/hooks/useStatusChangeCount.ts (100%) rename app/client/src/git/components/{GitQuickActions => QuickActions}/index.tsx (90%) rename app/client/src/git/components/{GitStatus/DumbGitStatus.tsx => StatusChanges/StatusChangesView.tsx} (93%) rename app/client/src/git/components/{GitStatus => StatusChanges}/StatusLoader.tsx (100%) rename app/client/src/git/components/{GitStatus => StatusChanges}/StatusTree.tsx (100%) rename app/client/src/git/components/{GitStatus => StatusChanges}/index.tsx (69%) delete mode 100644 app/client/src/git/components/connect/GitTest.tsx create mode 100644 app/client/src/git/components/index.tsx diff --git a/app/client/src/git/artifactHelpers/application/statusTransformer.ts b/app/client/src/git/artifactHelpers/application/statusTransformer.ts index 1923d186c4a1..9ac95d9c424e 100644 --- a/app/client/src/git/artifactHelpers/application/statusTransformer.ts +++ b/app/client/src/git/artifactHelpers/application/statusTransformer.ts @@ -1,6 +1,6 @@ import type { FetchStatusResponseData } from "git/requests/fetchStatusRequest.types"; import { objectKeys } from "@appsmith/utils"; -import type { StatusTreeStruct } from "git/components/GitStatus/StatusTree"; +import type { StatusTreeStruct } from "git/components/StatusChanges/StatusTree"; const ICON_LOOKUP = { query: "query", diff --git a/app/client/src/git/components/GitConflictError/DumbGitConflictError.tsx b/app/client/src/git/components/ConflictError/ConflictErrorView.tsx similarity index 92% rename from app/client/src/git/components/GitConflictError/DumbGitConflictError.tsx rename to app/client/src/git/components/ConflictError/ConflictErrorView.tsx index 220d051f9107..5a62f6fa04ba 100644 --- a/app/client/src/git/components/GitConflictError/DumbGitConflictError.tsx +++ b/app/client/src/git/components/ConflictError/ConflictErrorView.tsx @@ -26,15 +26,15 @@ const ConflictInfoContainer = styled.div` margin-bottom: ${(props) => props.theme.spaces[7]}px; `; -interface DumbGitConflictErrorProps { +interface ConflictErrorViewProps { learnMoreUrl: string; repoUrl: string; } -export default function DumbGitConflictError({ +export default function ConflictErrorView({ learnMoreUrl, repoUrl, -}: DumbGitConflictErrorProps) { +}: ConflictErrorViewProps) { const handleClickOnOpenRepo = useCallback(() => { window.open(repoUrl, "_blank", "noopener,noreferrer"); }, [repoUrl]); diff --git a/app/client/src/git/components/GitConflictError/index.tsx b/app/client/src/git/components/ConflictError/index.tsx similarity index 68% rename from app/client/src/git/components/GitConflictError/index.tsx rename to app/client/src/git/components/ConflictError/index.tsx index c1da1aa6f6a0..c5d49533f8ed 100644 --- a/app/client/src/git/components/GitConflictError/index.tsx +++ b/app/client/src/git/components/ConflictError/index.tsx @@ -1,9 +1,9 @@ import React from "react"; import { useGitContext } from "../GitContextProvider"; -import DumbGitConflictError from "./DumbGitConflictError"; +import GitConflictErrorView from "./ConflictErrorView"; -export default function GitConflictError() { +export default function ConflictError() { const { gitMetadata } = useGitContext(); // ! case: learnMoreUrl comes from pullError @@ -11,5 +11,5 @@ export default function GitConflictError() { "https://docs.appsmith.com/advanced-concepts/version-control-with-git"; const repoUrl = gitMetadata?.browserSupportedRemoteUrl || ""; - return ; + return ; } diff --git a/app/client/src/git/components/GitConflictErrorModal/DumbGitConflictErrorModal.tsx b/app/client/src/git/components/ConflictErrorModal/ConflictErrorModalView.tsx similarity index 88% rename from app/client/src/git/components/GitConflictErrorModal/DumbGitConflictErrorModal.tsx rename to app/client/src/git/components/ConflictErrorModal/ConflictErrorModalView.tsx index 83d983d9866a..d59ff023af40 100644 --- a/app/client/src/git/components/GitConflictErrorModal/DumbGitConflictErrorModal.tsx +++ b/app/client/src/git/components/ConflictErrorModal/ConflictErrorModalView.tsx @@ -8,7 +8,7 @@ import { import { Button } from "@appsmith/ads"; import noop from "lodash/noop"; -import GitConflictError from "../GitConflictError"; +import ConflictError from "../ConflictError"; const StyledGitErrorPopup = styled.div` & { @@ -38,15 +38,15 @@ const StyledGitErrorPopup = styled.div` } `; -interface DumbGitConflictErrorModalProps { +interface ConflictErrorModalViewProps { isConflictErrorModalOpen?: boolean; toggleConflictErrorModal?: (open: boolean) => void; } -function DumbGitConflictErrorModal({ +function ConflictErrorModalView({ isConflictErrorModalOpen = false, toggleConflictErrorModal = noop, -}: DumbGitConflictErrorModalProps) { +}: ConflictErrorModalViewProps) { const handleClose = useCallback(() => { toggleConflictErrorModal(false); }, [toggleConflictErrorModal]); @@ -63,6 +63,7 @@ function DumbGitConflictErrorModal({
- +
@@ -89,4 +90,4 @@ function DumbGitConflictErrorModal({ ); } -export default DumbGitConflictErrorModal; +export default ConflictErrorModalView; diff --git a/app/client/src/git/components/GitConflictErrorModal/index.tsx b/app/client/src/git/components/ConflictErrorModal/index.tsx similarity index 66% rename from app/client/src/git/components/GitConflictErrorModal/index.tsx rename to app/client/src/git/components/ConflictErrorModal/index.tsx index ac0ce4e837f7..0de96380c6d1 100644 --- a/app/client/src/git/components/GitConflictErrorModal/index.tsx +++ b/app/client/src/git/components/ConflictErrorModal/index.tsx @@ -1,12 +1,12 @@ import React from "react"; -import DumbGitConflictErrorModal from "./DumbGitConflictErrorModal"; +import ConflictErrorModalView from "./ConflictErrorModalView"; import { useGitContext } from "../GitContextProvider"; -export default function GitConflictErrorModal() { +export default function ConflictErrorModal() { const { conflictErrorModalOpen, toggleConflictErrorModal } = useGitContext(); return ( - diff --git a/app/client/src/git/components/GitContextProvider/hooks/useGitContextValue.ts b/app/client/src/git/components/GitContextProvider/hooks/useGitContextValue.ts index bbfbf87215cb..4a11ca17a73e 100644 --- a/app/client/src/git/components/GitContextProvider/hooks/useGitContextValue.ts +++ b/app/client/src/git/components/GitContextProvider/hooks/useGitContextValue.ts @@ -14,7 +14,7 @@ import useGitMetadata from "./useGitMetadata"; // internal dependencies import type { ApplicationPayload } from "entities/Application"; import type { FetchStatusResponseData } from "git/requests/fetchStatusRequest.types"; -import type { StatusTreeStruct } from "git/components/GitStatus/StatusTree"; +import type { StatusTreeStruct } from "git/components/StatusChanges/StatusTree"; export interface UseGitContextValueParams { artifactType: keyof typeof GitArtifactType; diff --git a/app/client/src/git/components/GitModals.tsx b/app/client/src/git/components/GitModals.tsx index 52b2097eee16..443943ba736d 100644 --- a/app/client/src/git/components/GitModals.tsx +++ b/app/client/src/git/components/GitModals.tsx @@ -1,12 +1,12 @@ import React from "react"; -import GitOpsModal from "./GitOpsModal"; -import GitConflictErrorModal from "./GitConflictErrorModal"; +import ConflictErrorModal from "./ConflictErrorModal"; +import OpsModal from "./OpsModal"; export default function GitModals() { return ( <> - - + + ); } diff --git a/app/client/src/git/components/GitOpsModal/DumbGitOpsModal.tsx b/app/client/src/git/components/OpsModal/OpsModalView.tsx similarity index 95% rename from app/client/src/git/components/GitOpsModal/DumbGitOpsModal.tsx rename to app/client/src/git/components/OpsModal/OpsModalView.tsx index 0c7e28762b67..54acf3f32b38 100644 --- a/app/client/src/git/components/GitOpsModal/DumbGitOpsModal.tsx +++ b/app/client/src/git/components/OpsModal/OpsModalView.tsx @@ -26,7 +26,7 @@ const StyledModalContent = styled(ModalContent)` } `; -interface DumbGitOpsModalProps { +interface OpsModalViewProps { fetchStatus: () => void; isOpsModalOpen: boolean; isProtectedMode: boolean; @@ -35,14 +35,14 @@ interface DumbGitOpsModalProps { toggleOpsModal: (open: boolean, tab?: keyof typeof GitOpsTab) => void; } -function DumbGitOpsModal({ +function OpsModalView({ fetchStatus = noop, isOpsModalOpen = false, isProtectedMode = false, opsModalTab = GitOpsTab.Deploy, repoName = null, toggleOpsModal = noop, -}: DumbGitOpsModalProps) { +}: OpsModalViewProps) { useEffect( function fetchStatusOnMountEffect() { if (isOpsModalOpen) { @@ -102,4 +102,4 @@ function DumbGitOpsModal({ ); } -export default DumbGitOpsModal; +export default OpsModalView; diff --git a/app/client/src/git/components/GitOpsModal/TabDeploy/DeployPreview.tsx b/app/client/src/git/components/OpsModal/TabDeploy/DeployPreview.tsx similarity index 100% rename from app/client/src/git/components/GitOpsModal/TabDeploy/DeployPreview.tsx rename to app/client/src/git/components/OpsModal/TabDeploy/DeployPreview.tsx diff --git a/app/client/src/git/components/GitOpsModal/TabDeploy/DiscardChangesWarning.tsx b/app/client/src/git/components/OpsModal/TabDeploy/DiscardChangesWarning.tsx similarity index 100% rename from app/client/src/git/components/GitOpsModal/TabDeploy/DiscardChangesWarning.tsx rename to app/client/src/git/components/OpsModal/TabDeploy/DiscardChangesWarning.tsx diff --git a/app/client/src/git/components/GitOpsModal/TabDeploy/DiscardFailedError.tsx b/app/client/src/git/components/OpsModal/TabDeploy/DiscardFailedError.tsx similarity index 100% rename from app/client/src/git/components/GitOpsModal/TabDeploy/DiscardFailedError.tsx rename to app/client/src/git/components/OpsModal/TabDeploy/DiscardFailedError.tsx diff --git a/app/client/src/git/components/GitOpsModal/TabDeploy/PushFailedError.tsx b/app/client/src/git/components/OpsModal/TabDeploy/PushFailedError.tsx similarity index 100% rename from app/client/src/git/components/GitOpsModal/TabDeploy/PushFailedError.tsx rename to app/client/src/git/components/OpsModal/TabDeploy/PushFailedError.tsx diff --git a/app/client/src/git/components/GitOpsModal/TabDeploy/SubmitWrapper.tsx b/app/client/src/git/components/OpsModal/TabDeploy/SubmitWrapper.tsx similarity index 100% rename from app/client/src/git/components/GitOpsModal/TabDeploy/SubmitWrapper.tsx rename to app/client/src/git/components/OpsModal/TabDeploy/SubmitWrapper.tsx diff --git a/app/client/src/git/components/GitOpsModal/TabDeploy/DumbTabDeploy.tsx b/app/client/src/git/components/OpsModal/TabDeploy/TabDeployView.tsx similarity index 97% rename from app/client/src/git/components/GitOpsModal/TabDeploy/DumbTabDeploy.tsx rename to app/client/src/git/components/OpsModal/TabDeploy/TabDeployView.tsx index 87cfe05540c5..d22c93f79b97 100644 --- a/app/client/src/git/components/GitOpsModal/TabDeploy/DumbTabDeploy.tsx +++ b/app/client/src/git/components/OpsModal/TabDeploy/TabDeployView.tsx @@ -36,8 +36,8 @@ import GIT_ERROR_CODES from "constants/GitErrorCodes"; import DiscardChangesWarning from "./DiscardChangesWarning"; import PushFailedError from "./PushFailedError"; import DiscardFailedError from "./DiscardFailedError"; -import GitStatus from "git/components/GitStatus"; -import GitConflictError from "git/components/GitConflictError"; +import StatusChanges from "git/components/StatusChanges"; +import ConflictError from "git/components/ConflictError"; import SubmitWrapper from "./SubmitWrapper"; import noop from "lodash/noop"; import type { GitApiError } from "git/store/types"; @@ -69,7 +69,7 @@ const CommitLabelBranchText = styled(Text)` const FIRST_COMMIT = "First Commit"; const NO_CHANGES_TO_COMMIT = "No changes to commit"; -interface DumbTabDeployProps { +interface TabDeployViewProps { clearCommitError: () => void; clearDiscardError: () => void; commit: (commitMessage: string) => void; @@ -89,7 +89,7 @@ interface DumbTabDeployProps { statusIsClean: boolean; } -function DumbTabDeploy({ +function TabDeployView({ clearCommitError = noop, clearDiscardError = noop, commit = noop, @@ -107,7 +107,7 @@ function DumbTabDeploy({ remoteUrl = null, statusBehindCount = 0, statusIsClean = false, -}: DumbTabDeployProps) { +}: TabDeployViewProps) { const hasChangesToCommit = !statusIsClean; const commitInputRef = useRef(null); const [commitMessage, setCommitMessage] = useState( @@ -297,7 +297,7 @@ function DumbTabDeploy({ style={{ minHeight: 360 }} >
- + - {isConflicting && } + {isConflicting && } {commitError && ( void; currentBranch: string | null; @@ -80,7 +80,7 @@ interface DumbTabMergeProps { protectedBranches: FetchProtectedBranchesResponseData | null; } -export default function DumbTabMerge({ +export default function TabMergeView({ branches = null, clearMergeStatus = noop, currentBranch = null, @@ -95,7 +95,7 @@ export default function DumbTabMerge({ mergeError = null, mergeStatus = null, protectedBranches = null, -}: DumbTabMergeProps) { +}: TabMergeViewProps) { const [showMergeSuccessIndicator, setShowMergeSuccessIndicator] = useState(false); const [selectedBranchOption, setSelectedBranchOption] = @@ -293,7 +293,7 @@ export default function DumbTabMerge({
- {isConflicting ? : null} + {isConflicting ? : null} {showMergeSuccessIndicator ? : null} {isMergeLoading ? ( diff --git a/app/client/src/git/components/GitOpsModal/TabMerge/index.tsx b/app/client/src/git/components/OpsModal/TabMerge/index.tsx similarity index 94% rename from app/client/src/git/components/GitOpsModal/TabMerge/index.tsx rename to app/client/src/git/components/OpsModal/TabMerge/index.tsx index 483662570aa9..204cf25093f3 100644 --- a/app/client/src/git/components/GitOpsModal/TabMerge/index.tsx +++ b/app/client/src/git/components/OpsModal/TabMerge/index.tsx @@ -1,5 +1,5 @@ import React from "react"; -import DumbTabMerge from "./DumbTabMerge"; +import TabMergeView from "./TabMergeView"; import { useGitContext } from "git/components/GitContextProvider"; export default function TabMerge() { @@ -23,7 +23,7 @@ export default function TabMerge() { const isStatusClean = status?.isClean ?? false; return ( - () => (
Statusbar
)); -describe("DumbGitQuickActions Component", () => { +describe("QuickActionsView Component", () => { const defaultProps = { discard: jest.fn(), isAutocommitEnabled: false, @@ -47,7 +47,7 @@ describe("DumbGitQuickActions Component", () => { it("should render ConnectButton when isGitConnected is false", () => { render( - + , ); expect(screen.getByTestId("connect-button")).toBeInTheDocument(); @@ -61,7 +61,7 @@ describe("DumbGitQuickActions Component", () => { const { container } = render( - + , ); @@ -89,7 +89,7 @@ describe("DumbGitQuickActions Component", () => { const { container } = render( - + , ); @@ -107,7 +107,7 @@ describe("DumbGitQuickActions Component", () => { const { container } = render( - + , ); const commitButton = container.querySelectorAll( @@ -139,7 +139,7 @@ describe("DumbGitQuickActions Component", () => { const { container } = render( - + , ); const pullButton = container.querySelectorAll( @@ -160,7 +160,7 @@ describe("DumbGitQuickActions Component", () => { const { container } = render( - + , ); const mergeButton = container.querySelectorAll( @@ -185,7 +185,7 @@ describe("DumbGitQuickActions Component", () => { const { container } = render( - + , ); const settingsButton = container.querySelectorAll( @@ -211,7 +211,7 @@ describe("DumbGitQuickActions Component", () => { const { container } = render( - + , ); const commitButton = container.querySelectorAll( @@ -230,7 +230,7 @@ describe("DumbGitQuickActions Component", () => { const { container } = render( - + , ); @@ -252,7 +252,7 @@ describe("DumbGitQuickActions Component", () => { render( - + , ); const countElement = screen.getByTestId("t--bottom-bar-count"); @@ -270,7 +270,7 @@ describe("DumbGitQuickActions Component", () => { render( - + , ); expect(screen.queryByTestId("t--bottom-bar-count")).not.toBeInTheDocument(); @@ -293,7 +293,7 @@ describe("DumbGitQuickActions Component", () => { const { container } = render( - + , ); const pullButton = container.querySelectorAll( @@ -313,7 +313,7 @@ describe("DumbGitQuickActions Component", () => { render( - + , ); const countElement = screen.getByTestId("t--bottom-bar-count"); diff --git a/app/client/src/git/components/GitQuickActions/DumbGitQuickActions.tsx b/app/client/src/git/components/QuickActions/QuickActionsView.tsx similarity index 97% rename from app/client/src/git/components/GitQuickActions/DumbGitQuickActions.tsx rename to app/client/src/git/components/QuickActions/QuickActionsView.tsx index 3dc3459670ad..eedb67bf3787 100644 --- a/app/client/src/git/components/GitQuickActions/DumbGitQuickActions.tsx +++ b/app/client/src/git/components/QuickActions/QuickActionsView.tsx @@ -23,7 +23,7 @@ const Container = styled.div` align-items: center; `; -interface DumbGitQuickActionsProps { +interface QuickActionsViewProps { discard: () => void; isAutocommitEnabled: boolean; isAutocommitPolling: boolean; @@ -46,7 +46,7 @@ interface DumbGitQuickActionsProps { ) => void; } -function DumbGitQuickActions({ +function QuickActionsView({ discard = noop, isAutocommitEnabled = false, isAutocommitPolling = false, @@ -64,7 +64,7 @@ function DumbGitQuickActions({ toggleConnectModal = noop, toggleOpsModal = noop, toggleSettingsModal = noop, -}: DumbGitQuickActionsProps) { +}: QuickActionsViewProps) { const { isDisabled: isPullDisabled, message: pullTooltipMessage } = getPullBtnStatus({ isStatusClean, @@ -177,4 +177,4 @@ function DumbGitQuickActions({ ); } -export default DumbGitQuickActions; +export default QuickActionsView; diff --git a/app/client/src/git/components/GitQuickActions/helpers/getPullButtonStatus.test.ts b/app/client/src/git/components/QuickActions/helpers/getPullButtonStatus.test.ts similarity index 100% rename from app/client/src/git/components/GitQuickActions/helpers/getPullButtonStatus.test.ts rename to app/client/src/git/components/QuickActions/helpers/getPullButtonStatus.test.ts diff --git a/app/client/src/git/components/GitQuickActions/helpers/getPullButtonStatus.ts b/app/client/src/git/components/QuickActions/helpers/getPullButtonStatus.ts similarity index 100% rename from app/client/src/git/components/GitQuickActions/helpers/getPullButtonStatus.ts rename to app/client/src/git/components/QuickActions/helpers/getPullButtonStatus.ts diff --git a/app/client/src/git/components/GitQuickActions/hooks/useStatusChangeCount.ts b/app/client/src/git/components/QuickActions/hooks/useStatusChangeCount.ts similarity index 100% rename from app/client/src/git/components/GitQuickActions/hooks/useStatusChangeCount.ts rename to app/client/src/git/components/QuickActions/hooks/useStatusChangeCount.ts diff --git a/app/client/src/git/components/GitQuickActions/index.tsx b/app/client/src/git/components/QuickActions/index.tsx similarity index 90% rename from app/client/src/git/components/GitQuickActions/index.tsx rename to app/client/src/git/components/QuickActions/index.tsx index d3d1acbd1a49..4e6d8a7a9985 100644 --- a/app/client/src/git/components/GitQuickActions/index.tsx +++ b/app/client/src/git/components/QuickActions/index.tsx @@ -1,9 +1,9 @@ import React from "react"; -import DumbGitQuickActions from "./DumbGitQuickActions"; +import QuickActionsView from "./QuickActionsView"; import { useGitContext } from "../GitContextProvider"; import useStatusChangeCount from "./hooks/useStatusChangeCount"; -function GitQuickActions() { +function QuickActions() { const { autocommitEnabled, autocommitPolling, @@ -28,7 +28,7 @@ function GitQuickActions() { const statusChangeCount = useStatusChangeCount(status); return ( - null; -interface DumbGitStatusProps { +interface StatusChangesViewProps { status: FetchStatusResponseData | null; statusTransformer: ( status: FetchStatusResponseData, @@ -20,11 +20,11 @@ interface DumbGitStatusProps { isFetchStatusLoading: boolean; } -export default function DumbGitStatus({ +export default function StatusChangesView({ isFetchStatusLoading = false, status = null, statusTransformer = noopStatusTransformer, -}: DumbGitStatusProps) { +}: StatusChangesViewProps) { const statusTree = useMemo(() => { if (!status || isFetchStatusLoading) return null; diff --git a/app/client/src/git/components/GitStatus/StatusLoader.tsx b/app/client/src/git/components/StatusChanges/StatusLoader.tsx similarity index 100% rename from app/client/src/git/components/GitStatus/StatusLoader.tsx rename to app/client/src/git/components/StatusChanges/StatusLoader.tsx diff --git a/app/client/src/git/components/GitStatus/StatusTree.tsx b/app/client/src/git/components/StatusChanges/StatusTree.tsx similarity index 100% rename from app/client/src/git/components/GitStatus/StatusTree.tsx rename to app/client/src/git/components/StatusChanges/StatusTree.tsx diff --git a/app/client/src/git/components/GitStatus/index.tsx b/app/client/src/git/components/StatusChanges/index.tsx similarity index 69% rename from app/client/src/git/components/GitStatus/index.tsx rename to app/client/src/git/components/StatusChanges/index.tsx index a45796ad9a11..05b8e280189b 100644 --- a/app/client/src/git/components/GitStatus/index.tsx +++ b/app/client/src/git/components/StatusChanges/index.tsx @@ -1,12 +1,12 @@ import React from "react"; import { useGitContext } from "../GitContextProvider"; -import DumbGitStatus from "./DumbGitStatus"; +import StatusChangesView from "./StatusChangesView"; -function GitStatus() { +function StatusChanges() { const { fetchStatusLoading, status, statusTransformer } = useGitContext(); return ( - GitTest; -} - -export default GitTest; diff --git a/app/client/src/git/components/index.tsx b/app/client/src/git/components/index.tsx new file mode 100644 index 000000000000..ec1d504d030a --- /dev/null +++ b/app/client/src/git/components/index.tsx @@ -0,0 +1,2 @@ +export { default as GitModals } from "./GitModals"; +export { default as GitQuickActions } from "./QuickActions"; diff --git a/app/client/src/pages/Editor/gitSync/components/DeployPreview.tsx b/app/client/src/pages/Editor/gitSync/components/DeployPreview.tsx index 9ead5d9d65c9..68c5d609429b 100644 --- a/app/client/src/pages/Editor/gitSync/components/DeployPreview.tsx +++ b/app/client/src/pages/Editor/gitSync/components/DeployPreview.tsx @@ -58,6 +58,7 @@ export default function DeployPreview(props: { showSuccess: boolean }) { : ""; return lastDeployedAt ? ( + // ! case: can use flex?
{props.showSuccess ? ( From a569b2296395512bd2ab82b95935df5379654485 Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Fri, 13 Dec 2024 23:58:26 +0800 Subject: [PATCH 049/143] chore: shifting fixes from ee to ee --- .../src/ee/git/hooks/useGitDefaultBranch.ts | 3 + app/client/src/ee/git/sagas/index.ts | 14 ++++ app/client/src/ee/git/store/actions/index.ts | 3 + app/client/src/ee/git/store/types.ts | 3 + .../src/entities/Engine/AppEditorEngine.ts | 81 +++++++++++-------- .../GitDefaultBranch/DumbGitDefaultBranch.tsx | 58 ++++++------- .../git/components/GitDefaultBranch/index.tsx | 23 +++++- .../src/git/hooks/useAppsmithEnterpriseUrl.ts | 23 ++++++ .../src/git/hooks/useGitDefaultBranch.ts | 28 +++++++ .../src/git/hooks/useGitFeatureFlags.ts | 12 +++ app/client/src/git/sagas/index.ts | 10 +++ app/client/src/git/store/gitArtifactSlice.ts | 5 +- .../selectors/gitSingleArtifactSelectors.ts | 2 +- app/client/src/git/store/types.ts | 14 +++- 14 files changed, 211 insertions(+), 68 deletions(-) create mode 100644 app/client/src/ee/git/hooks/useGitDefaultBranch.ts create mode 100644 app/client/src/ee/git/sagas/index.ts create mode 100644 app/client/src/ee/git/store/actions/index.ts create mode 100644 app/client/src/ee/git/store/types.ts create mode 100644 app/client/src/git/hooks/useAppsmithEnterpriseUrl.ts create mode 100644 app/client/src/git/hooks/useGitDefaultBranch.ts create mode 100644 app/client/src/git/hooks/useGitFeatureFlags.ts diff --git a/app/client/src/ee/git/hooks/useGitDefaultBranch.ts b/app/client/src/ee/git/hooks/useGitDefaultBranch.ts new file mode 100644 index 000000000000..9048d38e1dbd --- /dev/null +++ b/app/client/src/ee/git/hooks/useGitDefaultBranch.ts @@ -0,0 +1,3 @@ +export default function useGitDefaultBranchEE() { + return {}; +} diff --git a/app/client/src/ee/git/sagas/index.ts b/app/client/src/ee/git/sagas/index.ts new file mode 100644 index 000000000000..c6e962bdcace --- /dev/null +++ b/app/client/src/ee/git/sagas/index.ts @@ -0,0 +1,14 @@ +import type { PayloadAction } from "@reduxjs/toolkit"; + +// ! case: can we rethink the types +export const gitRequestBlockingActionsEE: Record< + string, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (action: PayloadAction) => Generator +> = {}; + +export const gitRequestNonBlockingActionsEE: Record< + string, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (action: PayloadAction) => Generator +> = {}; diff --git a/app/client/src/ee/git/store/actions/index.ts b/app/client/src/ee/git/store/actions/index.ts new file mode 100644 index 000000000000..e697f353cd27 --- /dev/null +++ b/app/client/src/ee/git/store/actions/index.ts @@ -0,0 +1,3 @@ +const gitArtifactCaseReducersEE = {}; + +export default gitArtifactCaseReducersEE; diff --git a/app/client/src/ee/git/store/types.ts b/app/client/src/ee/git/store/types.ts new file mode 100644 index 000000000000..77fa321f9154 --- /dev/null +++ b/app/client/src/ee/git/store/types.ts @@ -0,0 +1,3 @@ +export interface GitSingleArtifactAPIResponsesReduxStateEE {} + +export interface GitSingleArtifactUIReduxStateEE {} diff --git a/app/client/src/entities/Engine/AppEditorEngine.ts b/app/client/src/entities/Engine/AppEditorEngine.ts index d2ff14faf778..393d5ce7c206 100644 --- a/app/client/src/entities/Engine/AppEditorEngine.ts +++ b/app/client/src/entities/Engine/AppEditorEngine.ts @@ -1,14 +1,14 @@ import { fetchMockDatasources } from "actions/datasourceActions"; -import { - fetchGitProtectedBranchesInit, - fetchGitStatusInit, - remoteUrlInputValue, - resetPullMergeStatus, - fetchBranchesInit, - triggerAutocommitInitAction, - getGitMetadataInitAction, -} from "actions/gitSyncActions"; -import { restoreRecentEntitiesRequest } from "actions/globalSearchActions"; +// import { +// fetchGitProtectedBranchesInit, +// fetchGitStatusInit, +// remoteUrlInputValue, +// resetPullMergeStatus, +// fetchBranchesInit, +// triggerAutocommitInitAction, +// getGitMetadataInitAction, +// } from "actions/gitSyncActions"; +// import { restoreRecentEntitiesRequest } from "actions/globalSearchActions"; import { resetEditorSuccess } from "actions/initActions"; import { fetchAllPageEntityCompletion, @@ -24,9 +24,9 @@ import { ReduxActionErrorTypes, ReduxActionTypes, } from "ee/constants/ReduxActionConstants"; -import { addBranchParam } from "constants/routes"; +// import { addBranchParam } from "constants/routes"; import type { APP_MODE } from "entities/App"; -import { call, fork, put, select, spawn } from "redux-saga/effects"; +import { call, put, select, spawn } from "redux-saga/effects"; import type { EditConsolidatedApi } from "sagas/InitSagas"; import { failFastApiCalls, @@ -38,7 +38,7 @@ import { isGitPersistBranchEnabledSelector, } from "selectors/gitSyncSelectors"; import AnalyticsUtil from "ee/utils/AnalyticsUtil"; -import history from "utils/history"; +// import history from "utils/history"; import type { AppEnginePayload } from "."; import AppEngine, { ActionsNotFoundError, @@ -74,6 +74,8 @@ import { endSpan, startNestedSpan } from "UITelemetry/generateTraces"; import { getCurrentUser } from "selectors/usersSelectors"; import type { User } from "constants/userConstants"; import log from "loglevel"; +import { gitArtifactActions } from "git/store/gitArtifactSlice"; +import { GitArtifactType } from "git/constants/enums"; export default class AppEditorEngine extends AppEngine { constructor(mode: APP_MODE) { @@ -364,34 +366,45 @@ export default class AppEditorEngine extends AppEngine { public *loadGit(applicationId: string, rootSpan: Span) { const loadGitSpan = startNestedSpan("AppEditorEngine.loadGit", rootSpan); - - const branchInStore: string = yield select(getCurrentGitBranch); + const currentApplication: ApplicationPayload = yield select( + getCurrentApplication, + ); yield put( - restoreRecentEntitiesRequest({ - applicationId, - branch: branchInStore, + gitArtifactActions.initGitForEditor({ + artifactType: GitArtifactType.Application, + baseArtifactId: currentApplication.baseId, + artifact: currentApplication, }), ); - // init of temporary remote url from old application - yield put(remoteUrlInputValue({ tempRemoteUrl: "" })); - // add branch query to path and fetch status - if (branchInStore) { - history.replace(addBranchParam(branchInStore)); - yield fork(this.loadGitInBackground); - } + // const branchInStore: string = yield select(getCurrentGitBranch); + + // yield put( + // restoreRecentEntitiesRequest({ + // applicationId, + // branch: branchInStore, + // }), + // ); + // // init of temporary remote url from old application + // yield put(remoteUrlInputValue({ tempRemoteUrl: "" })); + // // add branch query to path and fetch status + + // if (branchInStore) { + // history.replace(addBranchParam(branchInStore)); + // yield fork(this.loadGitInBackground); + // } endSpan(loadGitSpan); } - private *loadGitInBackground() { - yield put(fetchBranchesInit()); - yield put(fetchGitProtectedBranchesInit()); - yield put(fetchGitProtectedBranchesInit()); - yield put(getGitMetadataInitAction()); - yield put(triggerAutocommitInitAction()); - yield put(fetchGitStatusInit({ compareRemote: true })); - yield put(resetPullMergeStatus()); - } + // private *loadGitInBackground() { + // yield put(fetchBranchesInit()); + // yield put(fetchGitProtectedBranchesInit()); + // yield put(fetchGitProtectedBranchesInit()); + // yield put(getGitMetadataInitAction()); + // yield put(triggerAutocommitInitAction()); + // yield put(fetchGitStatusInit({ compareRemote: true })); + // yield put(resetPullMergeStatus()); + // } } diff --git a/app/client/src/git/components/GitDefaultBranch/DumbGitDefaultBranch.tsx b/app/client/src/git/components/GitDefaultBranch/DumbGitDefaultBranch.tsx index 3acc26b0e5b7..63d9f194b814 100644 --- a/app/client/src/git/components/GitDefaultBranch/DumbGitDefaultBranch.tsx +++ b/app/client/src/git/components/GitDefaultBranch/DumbGitDefaultBranch.tsx @@ -1,21 +1,17 @@ import { - // APPSMITH_ENTERPRISE, + APPSMITH_ENTERPRISE, DEFAULT_BRANCH, DEFAULT_BRANCH_DESC, UPDATE, createMessage, } from "ee/constants/messages"; -// import { updateGitDefaultBranch } from "actions/gitSyncActions"; -import { Button, Option, Select, Text } from "@appsmith/ads"; -import React, { useEffect, useMemo, useState } from "react"; -// import { useDispatch, useSelector } from "react-redux"; -// import { getGitBranches } from "selectors/gitSyncSelectors"; +import { Button, Link, Option, Select, Text } from "@appsmith/ads"; +import React, { useCallback, useEffect, useMemo, useState } from "react"; import styled from "styled-components"; -// import { useFeatureFlag } from "utils/hooks/useFeatureFlag"; -// import { FEATURE_FLAG } from "ee/entities/FeatureFlag"; -// import { useAppsmithEnterpriseLink } from "./hooks"; import AnalyticsUtil from "ee/utils/AnalyticsUtil"; import type { FetchBranchesResponseData } from "git/requests/fetchBranchesRequest.types"; +import noop from "lodash/noop"; +import { useAppsmithEnterpriseUrl } from "git/hooks/useAppsmithEnterpriseUrl"; const Container = styled.div` padding-top: 8px; @@ -47,11 +43,13 @@ const StyledSelect = styled(Select)` interface DumbGitDefaultBranchProps { branches: FetchBranchesResponseData | null; isGitProtectedFeatureLicensed: boolean; + updateDefaultBranch?: (branchName: string) => void; } function DumbGitDefaultBranch({ branches = null, isGitProtectedFeatureLicensed = false, + updateDefaultBranch = noop, }: DumbGitDefaultBranchProps) { const [selectedValue, setSelectedValue] = useState(); @@ -61,9 +59,17 @@ function DumbGitDefaultBranch({ return defaultBranch?.branchName; }, [branches]); - // const enterprisePricingLink = useAppsmithEnterpriseLink( - // "git_branch_protection", - // ); + const enterprisePricingUrl = useAppsmithEnterpriseUrl( + "git_branch_protection", + ); + + const filteredBranches = useMemo( + () => branches?.filter((branch) => !branch.branchName.includes("origin/")), + [branches], + ); + + const isUpdateDisabled = + !selectedValue || selectedValue === currentDefaultBranch; useEffect( function selectedValueOnInitEffect() { @@ -74,22 +80,20 @@ function DumbGitDefaultBranch({ [branches], ); - const filteredBranches = branches?.filter( - (branch) => !branch.branchName.includes("origin/"), + const handleGetPopupContainer = useCallback( + (triggerNode) => triggerNode.parentNode, + [], ); - const handleUpdate = () => { + const handleUpdate = useCallback(() => { if (selectedValue) { AnalyticsUtil.logEvent("GS_DEFAULT_BRANCH_UPDATE", { old_branch: currentDefaultBranch, new_branch: selectedValue, }); - // dispatch(updateGitDefaultBranch({ branchName: selectedValue })); + updateDefaultBranch(selectedValue); } - }; - - const updateIsDisabled = - !selectedValue || selectedValue === currentDefaultBranch; + }, [currentDefaultBranch, selectedValue, updateDefaultBranch]); return ( @@ -103,14 +107,14 @@ function DumbGitDefaultBranch({ {!isGitProtectedFeatureLicensed && ( To change your default branch, try{" "} - {/* {createMessage(APPSMITH_ENTERPRISE)} - */} + )} @@ -118,9 +122,9 @@ function DumbGitDefaultBranch({ triggerNode.parentNode} + getPopupContainer={handleGetPopupContainer} isDisabled={!isGitProtectedFeatureLicensed} - onChange={(v) => setSelectedValue(v)} + onChange={setSelectedValue} value={selectedValue} > {filteredBranches?.map((b) => ( @@ -131,7 +135,7 @@ function DumbGitDefaultBranch({
; +const Container = styled.div` + padding-top: 16px; + padding-bottom: 16px; +`; + +const HeadContainer = styled.div` + margin-bottom: 16px; +`; + +const BodyContainer = styled.div` + display: flex; +`; + +const SectionTitle = styled(Text)` + font-weight: 600; + margin-bottom: 4px; +`; + +const SectionDesc = styled(Text)` + margin-bottom: 4px; +`; + +const StyledSelect = styled(Select)` + width: 300px; + margin-right: 12px; +`; + +const StyledLink = styled(Link)` + display: inline-flex; +`; + +interface ProtectedBranchesViewProps { + branches: FetchBranchesResponseData | null; + defaultBranch: string | null; + isProtectedBranchesLicensed: boolean; + isUpdateProtectedBranchesLoading: boolean; + protectedBranches: FetchProtectedBranchesResponseData | null; + updateProtectedBranches?: (branches: string[]) => void; +} + +function ProtectedBranchesView({ + branches = null, + defaultBranch = null, + isProtectedBranchesLicensed = false, + isUpdateProtectedBranchesLoading = false, + protectedBranches = null, + updateProtectedBranches = noop, +}: ProtectedBranchesViewProps) { + const [selectedValues, setSelectedValues] = useState([]); + + const filteredBranches = useMemo(() => { + const returnVal: string[] = []; + + for (const branch of branches ?? []) { + if (branch.branchName === defaultBranch) { + returnVal.unshift(branch.branchName); + } else if (branch.branchName.includes(GIT_REMOTE_BRANCH_PREFIX)) { + const localBranchName = branch.branchName.replace( + GIT_REMOTE_BRANCH_PREFIX, + "", + ); + + if (!returnVal.includes(localBranchName)) { + returnVal.push( + branch.branchName.replace(GIT_REMOTE_BRANCH_PREFIX, ""), + ); + } + } else { + returnVal.push(branch.branchName); + } + } + + return returnVal; + }, [branches, defaultBranch]); + + const isUpdateDisabled = useMemo(() => { + const areDifferent = xor(protectedBranches, selectedValues).length > 0; + + return !areDifferent; + }, [protectedBranches, selectedValues]); + + const enterprisePricingUrl = useAppsmithEnterpriseUrl( + "git_branch_protection", + ); + + useEffect( + function setValueOnInit() { + setSelectedValues(protectedBranches ?? []); + }, + [protectedBranches], + ); + + const sendAnalyticsEvent = useCallback(() => { + const eventData = { + branches_added: [] as string[], + branches_removed: [] as string[], + protected_branches: selectedValues, + }; + + for (const val of selectedValues) { + if (!protectedBranches?.includes(val)) { + eventData.branches_added.push(val); + } + } + + for (const val of protectedBranches ?? []) { + if (!selectedValues.includes(val)) { + eventData.branches_removed.push(val); + } + } + + AnalyticsUtil.logEvent("GS_PROTECTED_BRANCHES_UPDATE", eventData); + }, [protectedBranches, selectedValues]); + + const handleUpdate = useCallback(() => { + sendAnalyticsEvent(); + updateProtectedBranches(selectedValues ?? []); + }, [selectedValues, sendAnalyticsEvent, updateProtectedBranches]); + + const handleGetPopupContainer = useCallback( + (triggerNode) => triggerNode.parentNode, + [], + ); + + return ( + + + + {createMessage(BRANCH_PROTECTION)} + + + {createMessage(BRANCH_PROTECTION_DESC)}{" "} + + {createMessage(LEARN_MORE)} + + + {!isProtectedBranchesLicensed && ( + + To protect multiple branches, try{" "} + + {createMessage(APPSMITH_ENTERPRISE)} + + + )} + + + + {filteredBranches.map((branchName) => ( + + ))} + + + + + ); } export default ProtectedBranchesView; diff --git a/app/client/src/git/components/ProtectedBranches/index.tsx b/app/client/src/git/components/ProtectedBranches/index.tsx index f8f4f2b12706..8f1381ca67c9 100644 --- a/app/client/src/git/components/ProtectedBranches/index.tsx +++ b/app/client/src/git/components/ProtectedBranches/index.tsx @@ -1,7 +1,30 @@ import React from "react"; +import ProtectedBranchesView from "./ProtectedBranchesView"; +import { useGitContext } from "../GitContextProvider"; +import useDefaultBranch from "git/hooks/useDefaultBranch"; +import useProtectedBranches from "git/hooks/useProtectedBranches"; +import useGitFeatureFlags from "git/hooks/useGitFeatureFlags"; function ProtectedBranches() { - return
ProtectedBranches
; + const { branches } = useGitContext(); + const { defaultBranch } = useDefaultBranch(); + const { + isUpdateProtectedBranchesLoading, + protectedBranches, + updateProtectedBranches, + } = useProtectedBranches(); + const { license_git_branch_protection_enabled } = useGitFeatureFlags(); + + return ( + + ); } export default ProtectedBranches; diff --git a/app/client/src/git/components/QuickActions/index.tsx b/app/client/src/git/components/QuickActions/index.tsx index 4e6d8a7a9985..ef5c644fbee6 100644 --- a/app/client/src/git/components/QuickActions/index.tsx +++ b/app/client/src/git/components/QuickActions/index.tsx @@ -2,6 +2,7 @@ import React from "react"; import QuickActionsView from "./QuickActionsView"; import { useGitContext } from "../GitContextProvider"; import useStatusChangeCount from "./hooks/useStatusChangeCount"; +import useProtectedBranches from "git/hooks/useProtectedBranches"; function QuickActions() { const { @@ -11,7 +12,6 @@ function QuickActions() { discardLoading, fetchStatusLoading, gitConnected, - protectedMode, pull, pullError, pullLoading, @@ -20,6 +20,7 @@ function QuickActions() { toggleOpsModal, toggleSettingsModal, } = useGitContext(); + const { isProtectedMode } = useProtectedBranches(); const connectPermitted = true; const isPullFailing = !!pullError; @@ -36,7 +37,7 @@ function QuickActions() { isDiscardLoading={discardLoading} isFetchStatusLoading={fetchStatusLoading} isGitConnected={gitConnected} - isProtectedMode={protectedMode} + isProtectedMode={isProtectedMode} isPullFailing={isPullFailing} isPullLoading={pullLoading} isStatusClean={isStatusClean} diff --git a/app/client/src/git/constants/misc.ts b/app/client/src/git/constants/misc.ts index 41621dc726c8..e78ac729c738 100644 --- a/app/client/src/git/constants/misc.ts +++ b/app/client/src/git/constants/misc.ts @@ -1 +1,3 @@ +export const GIT_REMOTE_BRANCH_PREFIX = "origin/"; + export const GIT_BRANCH_QUERY_KEY = "branch"; diff --git a/app/client/src/git/hooks/useDefaultBranch.ts b/app/client/src/git/hooks/useDefaultBranch.ts new file mode 100644 index 000000000000..f9a145229f5a --- /dev/null +++ b/app/client/src/git/hooks/useDefaultBranch.ts @@ -0,0 +1,22 @@ +import useDefaultBranchEE from "ee/git/hooks/useDefaultBranch"; +import { useGitContext } from "git/components/GitContextProvider"; +import { selectDefaultBranch } from "git/store/selectors/gitSingleArtifactSelectors"; +import type { GitRootState } from "git/store/types"; +import { useSelector } from "react-redux"; + +function useDefaultBranch() { + const { artifactDef } = useGitContext(); + + const defaultBranch = useSelector((state: GitRootState) => + selectDefaultBranch(state, artifactDef), + ); + + const useDefaultBranchEEValues = useDefaultBranchEE(); + + return { + defaultBranch, + ...useDefaultBranchEEValues, + }; +} + +export default useDefaultBranch; diff --git a/app/client/src/git/hooks/useGitDefaultBranch.ts b/app/client/src/git/hooks/useGitDefaultBranch.ts deleted file mode 100644 index 3ebce3d49ce2..000000000000 --- a/app/client/src/git/hooks/useGitDefaultBranch.ts +++ /dev/null @@ -1,28 +0,0 @@ -import useGitDefaultBranchEE from "ee/git/hooks/useGitDefaultBranch"; -import { useGitContext } from "git/components/GitContextProvider"; -import { selectDefaultBranch } from "git/store/selectors/gitSingleArtifactSelectors"; -import type { GitRootState } from "git/store/types"; -import { useMemo } from "react"; -import { useSelector } from "react-redux"; - -function useGitDefaultBranch() { - const { artifactType, baseArtifactId } = useGitContext(); - - const artifactDef = useMemo( - () => ({ artifactType, baseArtifactId }), - [artifactType, baseArtifactId], - ); - - const defaultBranch = useSelector((state: GitRootState) => - selectDefaultBranch(state, artifactDef), - ); - - const useGitDefaultBranchEEValues = useGitDefaultBranchEE(); - - return { - defaultBranch: defaultBranch ?? null, - ...useGitDefaultBranchEEValues, - }; -} - -export default useGitDefaultBranch; diff --git a/app/client/src/git/hooks/useProtectedBranches.ts b/app/client/src/git/hooks/useProtectedBranches.ts new file mode 100644 index 000000000000..3d26df24066e --- /dev/null +++ b/app/client/src/git/hooks/useProtectedBranches.ts @@ -0,0 +1,53 @@ +import { useGitContext } from "git/components/GitContextProvider"; +import { gitArtifactActions } from "git/store/gitArtifactSlice"; +import { + selectFetchProtectedBranchesState, + selectProtectedMode, + selectUpdateProtectedBranchesState, +} from "git/store/selectors/gitSingleArtifactSelectors"; +import type { GitRootState } from "git/store/types"; +import { useDispatch, useSelector } from "react-redux"; + +function useProtectedBranches() { + const { artifactDef } = useGitContext(); + + const dispatch = useDispatch(); + + const fetchProtectedBranchesState = useSelector((state: GitRootState) => + selectFetchProtectedBranchesState(state, artifactDef), + ); + + const fetchProtectedBranches = () => { + dispatch(gitArtifactActions.fetchProtectedBranchesInit(artifactDef)); + }; + + const updateProtectedBranchesState = useSelector((state: GitRootState) => + selectUpdateProtectedBranchesState(state, artifactDef), + ); + + const updateProtectedBranches = (branches: string[]) => { + dispatch( + gitArtifactActions.updateProtectedBranchesInit({ + ...artifactDef, + branchNames: branches, + }), + ); + }; + + const isProtectedMode = useSelector((state: GitRootState) => + selectProtectedMode(state, artifactDef), + ); + + return { + protectedBranches: fetchProtectedBranchesState.value, + isFetchProtectedBranchesLoading: fetchProtectedBranchesState.loading, + fetchProtectedBranchesError: fetchProtectedBranchesState.error, + fetchProtectedBranches, + isUpdateProtectedBranchesLoading: updateProtectedBranchesState.loading, + updateProtectedBranchesError: updateProtectedBranchesState.error, + updateProtectedBranches, + isProtectedMode, + }; +} + +export default useProtectedBranches; diff --git a/app/client/src/git/requests/updateProtectedBranchesRequest.types.ts b/app/client/src/git/requests/updateProtectedBranchesRequest.types.ts index fff7073624e4..c59faa8f249e 100644 --- a/app/client/src/git/requests/updateProtectedBranchesRequest.types.ts +++ b/app/client/src/git/requests/updateProtectedBranchesRequest.types.ts @@ -1,5 +1,10 @@ +import type { ApiResponse } from "api/types"; + export interface UpdateProtectedBranchesRequestParams { branchNames: string[]; } -export type UpdateProtectedBranchesResponse = string[]; +export type UpdateProtectedBranchesResponseData = string[]; + +export type UpdateProtectedBranchesResponse = + ApiResponse; diff --git a/app/client/src/git/sagas/index.ts b/app/client/src/git/sagas/index.ts index a09a6aa409de..e5c62c3a3384 100644 --- a/app/client/src/git/sagas/index.ts +++ b/app/client/src/git/sagas/index.ts @@ -28,6 +28,7 @@ import { gitRequestBlockingActionsEE, gitRequestNonBlockingActionsEE, } from "ee/git/sagas"; +import updateProtectedBranchesSaga from "./updateProtectedBranchesSaga"; const gitRequestBlockingActions: Record< string, @@ -55,6 +56,12 @@ const gitRequestBlockingActions: Record< [gitConfigActions.fetchGlobalProfileInit.type]: fetchGlobalProfileSaga, [gitConfigActions.updateGlobalProfileInit.type]: updateGlobalProfileSaga, + // settings + [gitArtifactActions.fetchProtectedBranchesInit.type]: + fetchProtectedBranchesSaga, + [gitArtifactActions.updateProtectedBranchesInit.type]: + updateProtectedBranchesSaga, + // autocommit [gitArtifactActions.triggerAutocommitInit.type]: triggerAutocommitSaga, @@ -70,10 +77,6 @@ const gitRequestNonBlockingActions: Record< // init [gitArtifactActions.initGitForEditor.type]: initGitForEditorSaga, - // settings - [gitArtifactActions.fetchProtectedBranchesInit.type]: - fetchProtectedBranchesSaga, - // EE ...gitRequestNonBlockingActionsEE, }; diff --git a/app/client/src/git/sagas/updateProtectedBranchesSaga.ts b/app/client/src/git/sagas/updateProtectedBranchesSaga.ts new file mode 100644 index 000000000000..3f7bd121270e --- /dev/null +++ b/app/client/src/git/sagas/updateProtectedBranchesSaga.ts @@ -0,0 +1,52 @@ +import { captureException } from "@sentry/react"; +import updateProtectedBranchesRequest from "git/requests/updateProtectedBranchesRequest"; +import type { + UpdateProtectedBranchesRequestParams, + UpdateProtectedBranchesResponse, +} from "git/requests/updateProtectedBranchesRequest.types"; +import type { UpdateProtectedBranchesInitPayload } from "git/store/actions/updateProtectedBranchesActions"; +import { gitArtifactActions } from "git/store/gitArtifactSlice"; +import type { GitArtifactPayloadAction } from "git/store/types"; +import log from "loglevel"; +import { call, put } from "redux-saga/effects"; +import { validateResponse } from "sagas/ErrorSagas"; + +export default function* updateProtectedBranchesSaga( + action: GitArtifactPayloadAction, +) { + const { artifactType, baseArtifactId } = action.payload; + const artifactDef = { artifactType, baseArtifactId }; + let response: UpdateProtectedBranchesResponse | undefined; + + try { + const params: UpdateProtectedBranchesRequestParams = { + branchNames: action.payload.branchNames, + }; + + response = yield call( + updateProtectedBranchesRequest, + baseArtifactId, + params, + ); + const isValidResponse: boolean = yield validateResponse(response); + + if (response && isValidResponse) { + yield put(gitArtifactActions.updateProtectedBranchesSuccess(artifactDef)); + yield put(gitArtifactActions.fetchProtectedBranchesInit(artifactDef)); + } + } catch (e) { + if (response && response.responseMeta.error) { + const { error } = response.responseMeta; + + yield put( + gitArtifactActions.updateProtectedBranchesError({ + ...artifactDef, + error, + }), + ); + } else { + log.error(e); + captureException(e); + } + } +} diff --git a/app/client/src/git/store/actions/updateProtectedBranchesActions.ts b/app/client/src/git/store/actions/updateProtectedBranchesActions.ts index 8a90e5889d8d..6e45bf0dcca5 100644 --- a/app/client/src/git/store/actions/updateProtectedBranchesActions.ts +++ b/app/client/src/git/store/actions/updateProtectedBranchesActions.ts @@ -1,14 +1,17 @@ +import type { UpdateProtectedBranchesRequestParams } from "git/requests/updateProtectedBranchesRequest.types"; import { createSingleArtifactAction } from "../helpers/createSingleArtifactAction"; import type { GitArtifactErrorPayloadAction } from "../types"; -export const updateProtectedBranchesInitAction = createSingleArtifactAction( - (state) => { +export interface UpdateProtectedBranchesInitPayload + extends UpdateProtectedBranchesRequestParams {} + +export const updateProtectedBranchesInitAction = + createSingleArtifactAction((state) => { state.apiResponses.updateProtectedBranches.loading = true; state.apiResponses.updateProtectedBranches.error = null; return state; - }, -); + }); export const updateProtectedBranchesSuccessAction = createSingleArtifactAction( (state) => { diff --git a/app/client/src/git/store/selectors/gitSingleArtifactSelectors.ts b/app/client/src/git/store/selectors/gitSingleArtifactSelectors.ts index 88098b71400c..09f3c767d3b5 100644 --- a/app/client/src/git/store/selectors/gitSingleArtifactSelectors.ts +++ b/app/client/src/git/store/selectors/gitSingleArtifactSelectors.ts @@ -6,7 +6,7 @@ export interface GitArtifactDef { baseArtifactId: string; } -export const selectSingleArtifact = ( +export const selectGitArtifact = ( state: GitRootState, artifactDef: GitArtifactDef, ) => { @@ -19,7 +19,7 @@ export const selectSingleArtifact = ( export const selectGitMetadata = ( state: GitRootState, artifactDef: GitArtifactDef, -) => selectSingleArtifact(state, artifactDef)?.apiResponses.metadata; +) => selectGitArtifact(state, artifactDef)?.apiResponses.metadata; export const selectGitConnected = ( state: GitRootState, @@ -30,43 +30,43 @@ export const selectGitConnected = ( export const selectCommit = ( state: GitRootState, artifactDef: GitArtifactDef, -) => selectSingleArtifact(state, artifactDef)?.apiResponses?.commit; +) => selectGitArtifact(state, artifactDef)?.apiResponses?.commit; export const selectDiscard = ( state: GitRootState, artifactDef: GitArtifactDef, -) => selectSingleArtifact(state, artifactDef)?.apiResponses?.discard; +) => selectGitArtifact(state, artifactDef)?.apiResponses?.discard; export const selectStatus = ( state: GitRootState, artifactDef: GitArtifactDef, -) => selectSingleArtifact(state, artifactDef)?.apiResponses?.status; +) => selectGitArtifact(state, artifactDef)?.apiResponses?.status; export const selectMerge = (state: GitRootState, artifactDef: GitArtifactDef) => - selectSingleArtifact(state, artifactDef)?.apiResponses?.merge; + selectGitArtifact(state, artifactDef)?.apiResponses?.merge; export const selectMergeStatus = ( state: GitRootState, artifactDef: GitArtifactDef, -) => selectSingleArtifact(state, artifactDef)?.apiResponses?.mergeStatus; +) => selectGitArtifact(state, artifactDef)?.apiResponses?.mergeStatus; export const selectPull = (state: GitRootState, artifactDef: GitArtifactDef) => - selectSingleArtifact(state, artifactDef)?.apiResponses?.pull; + selectGitArtifact(state, artifactDef)?.apiResponses?.pull; export const selectOpsModalOpen = ( state: GitRootState, artifactDef: GitArtifactDef, -) => selectSingleArtifact(state, artifactDef)?.ui.opsModalOpen; +) => selectGitArtifact(state, artifactDef)?.ui.opsModalOpen; export const selectOpsModalTab = ( state: GitRootState, artifactDef: GitArtifactDef, -) => selectSingleArtifact(state, artifactDef)?.ui.opsModalTab; +) => selectGitArtifact(state, artifactDef)?.ui.opsModalTab; export const selectConflictErrorModalOpen = ( state: GitRootState, artifactDef: GitArtifactDef, -) => selectSingleArtifact(state, artifactDef)?.ui.conflictErrorModalOpen; +) => selectGitArtifact(state, artifactDef)?.ui.conflictErrorModalOpen; // git branches @@ -82,22 +82,22 @@ export const selectCurrentBranch = ( export const selectBranches = ( state: GitRootState, artifactDef: GitArtifactDef, -) => selectSingleArtifact(state, artifactDef)?.apiResponses?.branches; +) => selectGitArtifact(state, artifactDef)?.apiResponses?.branches; export const selectCreateBranch = ( state: GitRootState, artifactDef: GitArtifactDef, -) => selectSingleArtifact(state, artifactDef)?.apiResponses?.createBranch; +) => selectGitArtifact(state, artifactDef)?.apiResponses?.createBranch; export const selectDeleteBranch = ( state: GitRootState, artifactDef: GitArtifactDef, -) => selectSingleArtifact(state, artifactDef)?.apiResponses?.deleteBranch; +) => selectGitArtifact(state, artifactDef)?.apiResponses?.deleteBranch; export const selectCheckoutBranch = ( state: GitRootState, artifactDef: GitArtifactDef, -) => selectSingleArtifact(state, artifactDef)?.apiResponses.checkoutBranch; +) => selectGitArtifact(state, artifactDef)?.apiResponses.checkoutBranch; // settings export const selectAutocommitEnabled = ( @@ -112,35 +112,44 @@ export const selectAutocommitEnabled = ( export const selectAutocommitPolling = ( state: GitRootState, artifactDef: GitArtifactDef, -) => selectSingleArtifact(state, artifactDef)?.ui.autocommitPolling; +) => selectGitArtifact(state, artifactDef)?.ui.autocommitPolling; -export const selectProtectedBranches = ( +export const selectFetchProtectedBranchesState = ( state: GitRootState, artifactDef: GitArtifactDef, -) => selectSingleArtifact(state, artifactDef)?.apiResponses.protectedBranches; +) => selectGitArtifact(state, artifactDef)?.apiResponses.protectedBranches; + +export const selectUpdateProtectedBranchesState = ( + state: GitRootState, + artifactDef: GitArtifactDef, +) => + selectGitArtifact(state, artifactDef)?.apiResponses.updateProtectedBranches; export const selectProtectedMode = ( state: GitRootState, artifactDef: GitArtifactDef, ) => { const currentBranch = selectCurrentBranch(state, artifactDef); - const protectedBranches = selectProtectedBranches(state, artifactDef).value; + const protectedBranches = selectFetchProtectedBranchesState( + state, + artifactDef, + ).value; - return protectedBranches?.includes(currentBranch ?? ""); + return protectedBranches?.includes(currentBranch ?? "") ?? false; }; export const selectSettingsModalOpen = ( state: GitRootState, artifactDef: GitArtifactDef, -) => selectSingleArtifact(state, artifactDef)?.ui.settingsModalOpen; +) => selectGitArtifact(state, artifactDef)?.ui.settingsModalOpen; export const selectSettingsModalTab = ( state: GitRootState, artifactDef: GitArtifactDef, -) => selectSingleArtifact(state, artifactDef)?.ui.settingsModalTab; +) => selectGitArtifact(state, artifactDef)?.ui.settingsModalTab; // default branch export const selectDefaultBranch = ( state: GitRootState, artifactDef: GitArtifactDef, -) => selectGitMetadata(state, artifactDef)?.value?.defaultBranchName; +) => selectGitMetadata(state, artifactDef)?.value?.defaultBranchName ?? null; From fe620bd0cdcebd2825617f3c46173e5bda75c668 Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Sat, 14 Dec 2024 04:37:25 +0800 Subject: [PATCH 056/143] chore: adding local profile --- .../src/git/components/DangerZone/index.tsx | 7 + .../hooks/useGitContextValue.ts | 10 +- .../LocalProfile/LocalProfileView.tsx | 325 ++++++++++++++++++ .../src/git/components/LocalProfile/index.tsx | 23 ++ .../src/git/components/QuickActions/index.tsx | 5 +- .../SettingsModal/SettingsModalView.tsx | 11 +- .../SettingsModal/TabGeneral/index.tsx | 26 +- .../git/components/SettingsModal/index.tsx | 13 +- .../hooks/useGitPermissions.ts | 45 +-- app/client/src/git/hooks/useGlobalProfile.ts | 37 ++ app/client/src/git/hooks/useLocalProfile.ts | 44 +++ app/client/src/git/sagas/index.ts | 4 +- .../actions/updateGlobalProfileActions.ts | 9 +- .../git/store/selectors/gitConfigSelectors.ts | 9 + .../selectors/gitSingleArtifactSelectors.ts | 29 +- 15 files changed, 549 insertions(+), 48 deletions(-) create mode 100644 app/client/src/git/components/DangerZone/index.tsx create mode 100644 app/client/src/git/components/LocalProfile/LocalProfileView.tsx create mode 100644 app/client/src/git/components/LocalProfile/index.tsx rename app/client/src/git/{components/GitContextProvider => }/hooks/useGitPermissions.ts (58%) create mode 100644 app/client/src/git/hooks/useGlobalProfile.ts create mode 100644 app/client/src/git/hooks/useLocalProfile.ts create mode 100644 app/client/src/git/store/selectors/gitConfigSelectors.ts diff --git a/app/client/src/git/components/DangerZone/index.tsx b/app/client/src/git/components/DangerZone/index.tsx new file mode 100644 index 000000000000..00a8640adea5 --- /dev/null +++ b/app/client/src/git/components/DangerZone/index.tsx @@ -0,0 +1,7 @@ +import React from "react"; + +function DangerZone() { + return
DangerZone
; +} + +export default DangerZone; diff --git a/app/client/src/git/components/GitContextProvider/hooks/useGitContextValue.ts b/app/client/src/git/components/GitContextProvider/hooks/useGitContextValue.ts index b556160f7cb8..56c0ad4b7fb3 100644 --- a/app/client/src/git/components/GitContextProvider/hooks/useGitContextValue.ts +++ b/app/client/src/git/components/GitContextProvider/hooks/useGitContextValue.ts @@ -14,8 +14,6 @@ import useGitMetadata from "./useGitMetadata"; // internal dependencies import type { ApplicationPayload } from "entities/Application"; import type { FetchStatusResponseData } from "git/requests/fetchStatusRequest.types"; -import useGitPermissions from "./useGitPermissions"; -import type { UseGitPermissionsReturnValue } from "./useGitPermissions"; import type { StatusTreeStruct } from "git/components/StatusChanges/StatusTree"; export interface UseGitContextValueParams { @@ -32,8 +30,7 @@ export interface GitContextValue UseGitConnectReturnValue, UseGitOpsReturnValue, UseGitSettingsReturnValue, - UseGitBranchesReturnValue, - UseGitPermissionsReturnValue { + UseGitBranchesReturnValue { artifactType: keyof typeof GitArtifactType; baseArtifactId: string; artifactDef: { @@ -64,10 +61,6 @@ export default function useGitContextValue({ }); const useGitBranchesReturnValue = useGitBranches(artifactDef); const useGitSettingsReturnValue = useGitSettings(artifactDef); - const useGitPermissionsReturnValue = useGitPermissions({ - ...artifactDef, - artifact, - }); return { artifactType, @@ -80,6 +73,5 @@ export default function useGitContextValue({ ...useGitBranchesReturnValue, ...useGitConnectReturnValue, ...useGitSettingsReturnValue, - ...useGitPermissionsReturnValue, }; } diff --git a/app/client/src/git/components/LocalProfile/LocalProfileView.tsx b/app/client/src/git/components/LocalProfile/LocalProfileView.tsx new file mode 100644 index 000000000000..e918da7fc4d4 --- /dev/null +++ b/app/client/src/git/components/LocalProfile/LocalProfileView.tsx @@ -0,0 +1,325 @@ +import React, { useCallback, useEffect, useMemo } from "react"; +import { + AUTHOR_EMAIL_ONLY, + AUTHOR_EMAIL_CANNOT_BE_EMPTY, + AUTHOR_NAME_ONLY, + AUTHOR_NAME_CANNOT_BE_EMPTY, + FORM_VALIDATION_INVALID_EMAIL, + GIT_USER_SETTINGS_TITLE, + UPDATE, + USE_DEFAULT_CONFIGURATION, + createMessage, +} from "ee/constants/messages"; +import styled, { keyframes } from "styled-components"; +import { Button, Input, Switch, Text } from "@appsmith/ads"; +import type { SubmitHandler } from "react-hook-form"; +import { Controller, useForm } from "react-hook-form"; +import { noop, omit } from "lodash"; +import type { FetchLocalProfileResponseData } from "git/requests/fetchLocalProfileRequest.types"; +import type { FetchGlobalProfileResponseData } from "git/requests/fetchGlobalProfileRequest.types"; + +const Container = styled.div` + padding-top: 8px; + padding-bottom: 8px; +`; + +const HeadContainer = styled.div` + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 36px; +`; + +const BodyContainer = styled.div` + display: flex; + align-items: flex-end; +`; + +const InputContainer = styled.div` + margin-right: 12px; + width: 240px; +`; + +const SectionTitle = styled(Text)` + font-weight: 600; +`; + +const loadingKeyframe = keyframes` + 100% { + transform: translateX(100%); + } +`; + +const DummyLabel = styled.div` + height: 17px; + width: 100px; + margin-bottom: 8px; + border-radius: 4px; + background-color: var(--ads-color-black-100); + position: relative; + + overflow: hidden; + + &::after { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + transform: translateX(-100%); + background-image: linear-gradient( + 90deg, + rgba(255, 255, 255, 0) 0, + rgba(255, 255, 255, 0.5) 20%, + rgba(255, 255, 255, 0.8) 60%, + rgba(255, 255, 255, 0) + ); + animation: ${loadingKeyframe} 5s infinite; + content: ""; + } +`; + +const DummyInput = styled.div` + height: 36px; + border-radius: 4px; + background-color: linear-gradient( + 90deg, + var(--ads-color-black-200) 0%, + rgba(240, 240, 240, 0) 100% + ); + background-color: var(--ads-color-black-100); + position: relative; + + overflow: hidden; + + &::after { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + transform: translateX(-100%); + background-image: linear-gradient( + 90deg, + rgba(255, 255, 255, 0) 0, + rgba(255, 255, 255, 0.5) 20%, + rgba(255, 255, 255, 0.8) 60%, + rgba(255, 255, 255, 0) + ); + animation: ${loadingKeyframe} 5s infinite; + content: ""; + } +`; + +const DummyField = () => { + return ( +
+ + +
+ ); +}; + +interface AuthorInfo { + authorName: string; + authorEmail: string; + useGlobalProfile: boolean; +} + +interface LocalProfileProps { + fetchGlobalProfile?: () => void; + fetchLocalProfile?: () => void; + globalProfile: FetchGlobalProfileResponseData | null; + isFetchGlobalProfileLoading: boolean; + isFetchLocalProfileLoading: boolean; + localProfile: FetchLocalProfileResponseData | null; + updateLocalProfile: (data: AuthorInfo) => void; +} + +function LocalProfileView({ + fetchGlobalProfile = noop, + fetchLocalProfile = noop, + globalProfile = null, + isFetchGlobalProfileLoading = false, + isFetchLocalProfileLoading = false, + localProfile = null, + updateLocalProfile = noop, +}: LocalProfileProps) { + const { + control, + formState: { errors }, + handleSubmit, + register, + setValue, + watch, + } = useForm(); + + const useGlobalProfile = watch("useGlobalProfile"); + const authorName = watch("authorName"); + const authorEmail = watch("authorEmail"); + + const isLoading = isFetchGlobalProfileLoading || isFetchLocalProfileLoading; + + useEffect( + function fetchProfilesOnInitEffect() { + fetchGlobalProfile(); + fetchLocalProfile(); + }, + [fetchGlobalProfile, fetchLocalProfile], + ); + + useEffect( + function setDefaultProfileOnInitEffect() { + if (!isLoading) { + setValue("useGlobalProfile", !!localProfile?.useGlobalProfile); + } + }, + [isLoading, setValue], + ); + + useEffect( + function setValuesOnDefaultProfileChangeEffect() { + if (!isLoading) { + if (!useGlobalProfile && localProfile) { + setValue("authorName", localProfile.authorName); + setValue("authorEmail", localProfile.authorEmail); + } else if (globalProfile) { + setValue("authorName", globalProfile.authorName); + setValue("authorEmail", globalProfile.authorEmail); + } + } + }, + [isLoading, useGlobalProfile], + ); + + const onSubmit: SubmitHandler = (data) => { + if (data.useGlobalProfile && localProfile) { + data.authorName = localProfile.authorName; + data.authorEmail = localProfile.authorEmail; + } + + updateLocalProfile(data); + }; + + const isSubmitAllowed = useMemo(() => { + if (!isLoading) { + if (useGlobalProfile) { + return ( + authorName !== globalProfile?.authorName || + authorEmail !== globalProfile?.authorEmail || + useGlobalProfile !== localProfile?.useGlobalProfile + ); + } else { + return ( + authorName !== localProfile?.authorName || + authorEmail !== localProfile?.authorEmail || + useGlobalProfile !== localProfile?.useGlobalProfile + ); + } + } else { + return false; + } + }, [ + isLoading, + localProfile, + globalProfile, + useGlobalProfile, + authorName, + authorEmail, + ]); + + const handleInputChange = useCallback( + (key: "authorName" | "authorEmail") => (value: string) => { + setValue(key, value); + }, + [setValue], + ); + + const renderDefaultProfileSwitch = useCallback( + ({ field }) => { + return ( + + {createMessage(USE_DEFAULT_CONFIGURATION)} + + ); + }, + [isLoading], + ); + + return ( + +
+ + + {createMessage(GIT_USER_SETTINGS_TITLE)} + +
+ +
+
+ + + {!isLoading ? ( + + ) : ( + + )} + + + {!isLoading ? ( + + ) : ( + + )} + + + +
+
+ ); +} + +export default LocalProfileView; diff --git a/app/client/src/git/components/LocalProfile/index.tsx b/app/client/src/git/components/LocalProfile/index.tsx new file mode 100644 index 000000000000..1525abb4fb08 --- /dev/null +++ b/app/client/src/git/components/LocalProfile/index.tsx @@ -0,0 +1,23 @@ +import React from "react"; +import LocalProfileView from "./LocalProfileView"; +import useLocalProfile from "git/hooks/useLocalProfile"; +import useGlobalProfile from "git/hooks/useGlobalProfile"; + +function LocalProfile() { + const { isFetchLocalProfileLoading, localProfile, updateLocalProfile } = + useLocalProfile(); + + const { globalProfile, isFetchGlobalProfileLoading } = useGlobalProfile(); + + return ( + + ); +} + +export default LocalProfile; diff --git a/app/client/src/git/components/QuickActions/index.tsx b/app/client/src/git/components/QuickActions/index.tsx index ef5c644fbee6..e101a4e4e776 100644 --- a/app/client/src/git/components/QuickActions/index.tsx +++ b/app/client/src/git/components/QuickActions/index.tsx @@ -3,6 +3,7 @@ import QuickActionsView from "./QuickActionsView"; import { useGitContext } from "../GitContextProvider"; import useStatusChangeCount from "./hooks/useStatusChangeCount"; import useProtectedBranches from "git/hooks/useProtectedBranches"; +import useGitPermissions from "git/hooks/useGitPermissions"; function QuickActions() { const { @@ -21,8 +22,8 @@ function QuickActions() { toggleSettingsModal, } = useGitContext(); const { isProtectedMode } = useProtectedBranches(); + const { isConnectPermitted } = useGitPermissions(); - const connectPermitted = true; const isPullFailing = !!pullError; const isStatusClean = status?.isClean ?? false; const statusBehindCount = status?.behindCount ?? 0; @@ -33,7 +34,7 @@ function QuickActions() { discard={discard} isAutocommitEnabled={autocommitEnabled} isAutocommitPolling={autocommitPolling} - isConnectPermitted={connectPermitted} + isConnectPermitted={isConnectPermitted} isDiscardLoading={discardLoading} isFetchStatusLoading={fetchStatusLoading} isGitConnected={gitConnected} diff --git a/app/client/src/git/components/SettingsModal/SettingsModalView.tsx b/app/client/src/git/components/SettingsModal/SettingsModalView.tsx index 41427b82d7db..84693bcc90a3 100644 --- a/app/client/src/git/components/SettingsModal/SettingsModalView.tsx +++ b/app/client/src/git/components/SettingsModal/SettingsModalView.tsx @@ -34,6 +34,8 @@ const StyledModalContent = styled(ModalContent)` `; interface SettingsModalViewProps { + isConnectPermitted: boolean; + isManageAutocommitPermitted: boolean; isManageDefaultBranchPermitted: boolean; isManageProtectedBranchesPermitted: boolean; isSettingsModalOpen: boolean; @@ -45,6 +47,8 @@ interface SettingsModalViewProps { } function SettingsModalView({ + isConnectPermitted = false, + isManageAutocommitPermitted = false, isManageDefaultBranchPermitted = false, isManageProtectedBranchesPermitted = false, isSettingsModalOpen = false, @@ -84,7 +88,12 @@ function SettingsModalView({ - {settingsModalTab === GitSettingsTab.General && } + {settingsModalTab === GitSettingsTab.General && ( + + )} {settingsModalTab === GitSettingsTab.Branch && ( TabGeneral; +const Container = styled.div` + overflow: auto; +`; + +interface TabGeneralProps { + isConnectPermitted: boolean; + isManageAutocommitPermitted: boolean; +} + +function TabGeneral({ + isConnectPermitted = false, + isManageAutocommitPermitted = false, +}: TabGeneralProps) { + const showDangerZone = isConnectPermitted || isManageAutocommitPermitted; + + return ( + + + {showDangerZone && } + + ); } export default TabGeneral; diff --git a/app/client/src/git/components/SettingsModal/index.tsx b/app/client/src/git/components/SettingsModal/index.tsx index faf97373539e..179817869959 100644 --- a/app/client/src/git/components/SettingsModal/index.tsx +++ b/app/client/src/git/components/SettingsModal/index.tsx @@ -1,18 +1,23 @@ import React from "react"; import SettingsModalView from "./SettingsModalView"; import { useGitContext } from "../GitContextProvider"; +import useGitPermissions from "git/hooks/useGitPermissions"; function SettingsModal() { + const { settingsModalOpen, settingsModalTab, toggleSettingsModal } = + useGitContext(); + const { + isConnectPermitted, + isManageAutocommitPermitted, isManageDefaultBranchPermitted, isManageProtectedBranchesPermitted, - settingsModalOpen, - settingsModalTab, - toggleSettingsModal, - } = useGitContext(); + } = useGitPermissions(); return ( { if (artifact) { if (artifactType === GitArtifactType.Application) { return hasConnectToGitPermission(artifact.userPermissions); } } + + return false; }, [artifact, artifactType]); const isManageDefaultBranchPermitted = useMemo(() => { @@ -37,6 +28,8 @@ export default function useGitPermissions({ return hasManageDefaultBranchPermission(artifact.userPermissions); } } + + return false; }, [artifact, artifactType]); const isManageProtectedBranchesPermitted = useMemo(() => { @@ -45,12 +38,24 @@ export default function useGitPermissions({ return hasManageProtectedBranchesPermission(artifact.userPermissions); } } + + return false; + }, [artifact, artifactType]); + + const isManageAutocommitPermitted = useMemo(() => { + if (artifact) { + if (artifactType === GitArtifactType.Application) { + return hasManageAutoCommitPermission(artifact.userPermissions); + } + } + + return false; }, [artifact, artifactType]); return { - isConnectPermitted: isConnectPermitted ?? false, - isManageDefaultBranchPermitted: isManageDefaultBranchPermitted ?? false, - isManageProtectedBranchesPermitted: - isManageProtectedBranchesPermitted ?? false, + isConnectPermitted, + isManageDefaultBranchPermitted, + isManageProtectedBranchesPermitted, + isManageAutocommitPermitted, }; } diff --git a/app/client/src/git/hooks/useGlobalProfile.ts b/app/client/src/git/hooks/useGlobalProfile.ts new file mode 100644 index 000000000000..2e05a18ae3d4 --- /dev/null +++ b/app/client/src/git/hooks/useGlobalProfile.ts @@ -0,0 +1,37 @@ +// useGlobaProfile same as useLocalProfile but it uses global state + +import type { UpdateGlobalProfileRequestParams } from "git/requests/updateGlobalProfileRequest.types"; +import { gitConfigActions } from "git/store/gitConfigSlice"; +import { selectFetchGlobalProfileState } from "git/store/selectors/gitConfigSelectors"; + +import type { GitRootState } from "git/store/types"; +import { useDispatch, useSelector } from "react-redux"; + +export default function useGlobalProfile() { + const dispatch = useDispatch(); + const fetchGlobalProfileState = useSelector((state: GitRootState) => + selectFetchGlobalProfileState(state), + ); + + const fetchGlobalProfile = () => { + dispatch(gitConfigActions.fetchGlobalProfileInit()); + }; + + const updateGlobalProfileState = useSelector((state: GitRootState) => + selectFetchGlobalProfileState(state), + ); + + const updateGlobalProfile = (params: UpdateGlobalProfileRequestParams) => { + dispatch(gitConfigActions.updateGlobalProfileInit(params)); + }; + + return { + globalProfile: fetchGlobalProfileState?.value ?? null, + isFetchGlobalProfileLoading: fetchGlobalProfileState?.loading ?? false, + fetchGlobalProfileError: fetchGlobalProfileState?.error ?? null, + fetchGlobalProfile, + isUpdateGlobalProfileLoading: updateGlobalProfileState?.loading ?? false, + updateGlobalProfileError: updateGlobalProfileState?.error ?? null, + updateGlobalProfile, + }; +} diff --git a/app/client/src/git/hooks/useLocalProfile.ts b/app/client/src/git/hooks/useLocalProfile.ts new file mode 100644 index 000000000000..e3cc32fa8d04 --- /dev/null +++ b/app/client/src/git/hooks/useLocalProfile.ts @@ -0,0 +1,44 @@ +import { useGitContext } from "git/components/GitContextProvider"; +import type { UpdateLocalProfileRequestParams } from "git/requests/updateLocalProfileRequest.types"; +import { gitArtifactActions } from "git/store/gitArtifactSlice"; +import { selectFetchGlobalProfileState } from "git/store/selectors/gitConfigSelectors"; +import { selectFetchLocalProfileState } from "git/store/selectors/gitSingleArtifactSelectors"; +import type { GitRootState } from "git/store/types"; +import { useDispatch, useSelector } from "react-redux"; + +export default function useLocalProfile() { + const { artifactDef } = useGitContext(); + + const dispatch = useDispatch(); + + const fetchLocalProfileState = useSelector((state: GitRootState) => + selectFetchLocalProfileState(state, artifactDef), + ); + + const fetchLocalProfile = () => { + dispatch(gitArtifactActions.fetchLocalProfileInit(artifactDef)); + }; + + const updateLocalProfileState = useSelector((state: GitRootState) => + selectFetchGlobalProfileState(state), + ); + + const updateLocalProfile = (params: UpdateLocalProfileRequestParams) => { + dispatch( + gitArtifactActions.updateLocalProfileInit({ + ...artifactDef, + ...params, + }), + ); + }; + + return { + localProfile: fetchLocalProfileState?.value ?? null, + isFetchLocalProfileLoading: fetchLocalProfileState?.loading ?? false, + fetchLocalProfileError: fetchLocalProfileState?.error ?? null, + fetchLocalProfile, + isUpdateLocalProfileLoading: updateLocalProfileState?.loading ?? false, + updateLocalProfileError: updateLocalProfileState?.error ?? null, + updateLocalProfile, + }; +} diff --git a/app/client/src/git/sagas/index.ts b/app/client/src/git/sagas/index.ts index e5c62c3a3384..d0ac2c5c89e5 100644 --- a/app/client/src/git/sagas/index.ts +++ b/app/client/src/git/sagas/index.ts @@ -50,13 +50,13 @@ const gitRequestBlockingActions: Record< // branches [gitArtifactActions.fetchBranchesInit.type]: fetchBranchesSaga, - // settings + // user profiles [gitArtifactActions.fetchLocalProfileInit.type]: fetchLocalProfileSaga, [gitArtifactActions.updateLocalProfileInit.type]: updateLocalProfileSaga, [gitConfigActions.fetchGlobalProfileInit.type]: fetchGlobalProfileSaga, [gitConfigActions.updateGlobalProfileInit.type]: updateGlobalProfileSaga, - // settings + // protected branches [gitArtifactActions.fetchProtectedBranchesInit.type]: fetchProtectedBranchesSaga, [gitArtifactActions.updateProtectedBranchesInit.type]: diff --git a/app/client/src/git/store/actions/updateGlobalProfileActions.ts b/app/client/src/git/store/actions/updateGlobalProfileActions.ts index 58dcd8570367..b4d25b0b57d7 100644 --- a/app/client/src/git/store/actions/updateGlobalProfileActions.ts +++ b/app/client/src/git/store/actions/updateGlobalProfileActions.ts @@ -5,7 +5,14 @@ import type { PayloadAction } from "@reduxjs/toolkit"; export interface UpdateGlobalProfileInitPayload extends UpdateGlobalProfileRequestParams {} -export const updateGlobalProfileInitAction = (state: GitConfigReduxState) => { +type UpdateGlobalProfileInitAction = ( + state: GitConfigReduxState, + action: PayloadAction, +) => GitConfigReduxState; + +export const updateGlobalProfileInitAction: UpdateGlobalProfileInitAction = ( + state, +) => { state.updateGlobalProfile.loading = true; state.updateGlobalProfile.error = null; diff --git a/app/client/src/git/store/selectors/gitConfigSelectors.ts b/app/client/src/git/store/selectors/gitConfigSelectors.ts new file mode 100644 index 000000000000..9cdfd4799ed4 --- /dev/null +++ b/app/client/src/git/store/selectors/gitConfigSelectors.ts @@ -0,0 +1,9 @@ +import type { GitRootState } from "../types"; + +export const selectGitConfig = (state: GitRootState) => { + return state.git.config; +}; + +// global profile +export const selectFetchGlobalProfileState = (state: GitRootState) => + selectGitConfig(state).globalProfile; diff --git a/app/client/src/git/store/selectors/gitSingleArtifactSelectors.ts b/app/client/src/git/store/selectors/gitSingleArtifactSelectors.ts index 09f3c767d3b5..3682da48fa34 100644 --- a/app/client/src/git/store/selectors/gitSingleArtifactSelectors.ts +++ b/app/client/src/git/store/selectors/gitSingleArtifactSelectors.ts @@ -99,7 +99,20 @@ export const selectCheckoutBranch = ( artifactDef: GitArtifactDef, ) => selectGitArtifact(state, artifactDef)?.apiResponses.checkoutBranch; -// settings +// SETTINGS + +// local profile +export const selectFetchLocalProfileState = ( + state: GitRootState, + artifactDef: GitArtifactDef, +) => selectGitArtifact(state, artifactDef)?.apiResponses.localProfile ?? null; + +export const selectUpdateLocalProfileState = ( + state: GitRootState, + artifactDef: GitArtifactDef, +) => selectGitArtifact(state, artifactDef)?.apiResponses.updateLocalProfile; + +// autocommit export const selectAutocommitEnabled = ( state: GitRootState, artifactDef: GitArtifactDef, @@ -114,6 +127,13 @@ export const selectAutocommitPolling = ( artifactDef: GitArtifactDef, ) => selectGitArtifact(state, artifactDef)?.ui.autocommitPolling; +// default branch +export const selectDefaultBranch = ( + state: GitRootState, + artifactDef: GitArtifactDef, +) => selectGitMetadata(state, artifactDef)?.value?.defaultBranchName ?? null; + +// protected branches export const selectFetchProtectedBranchesState = ( state: GitRootState, artifactDef: GitArtifactDef, @@ -138,6 +158,7 @@ export const selectProtectedMode = ( return protectedBranches?.includes(currentBranch ?? "") ?? false; }; +// settings modal export const selectSettingsModalOpen = ( state: GitRootState, artifactDef: GitArtifactDef, @@ -147,9 +168,3 @@ export const selectSettingsModalTab = ( state: GitRootState, artifactDef: GitArtifactDef, ) => selectGitArtifact(state, artifactDef)?.ui.settingsModalTab; - -// default branch -export const selectDefaultBranch = ( - state: GitRootState, - artifactDef: GitArtifactDef, -) => selectGitMetadata(state, artifactDef)?.value?.defaultBranchName ?? null; From d8dca7fa4c2a2ebe201f6fbdd332659aa4602645 Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Sat, 14 Dec 2024 04:53:40 +0800 Subject: [PATCH 057/143] fix: issue with localprofile --- .../LocalProfile/LocalProfileView.tsx | 6 ++--- .../src/git/components/LocalProfile/index.tsx | 13 +++++++--- app/client/src/git/hooks/useGlobalProfile.ts | 14 +++++++---- app/client/src/git/hooks/useLocalProfile.ts | 24 +++++++++++-------- 4 files changed, 36 insertions(+), 21 deletions(-) diff --git a/app/client/src/git/components/LocalProfile/LocalProfileView.tsx b/app/client/src/git/components/LocalProfile/LocalProfileView.tsx index e918da7fc4d4..af504bab61d7 100644 --- a/app/client/src/git/components/LocalProfile/LocalProfileView.tsx +++ b/app/client/src/git/components/LocalProfile/LocalProfileView.tsx @@ -27,7 +27,7 @@ const HeadContainer = styled.div` display: flex; align-items: center; justify-content: space-between; - margin-bottom: 36px; + margin-bottom: 12px; `; const BodyContainer = styled.div` @@ -127,8 +127,8 @@ interface AuthorInfo { } interface LocalProfileProps { - fetchGlobalProfile?: () => void; - fetchLocalProfile?: () => void; + fetchGlobalProfile: () => void; + fetchLocalProfile: () => void; globalProfile: FetchGlobalProfileResponseData | null; isFetchGlobalProfileLoading: boolean; isFetchLocalProfileLoading: boolean; diff --git a/app/client/src/git/components/LocalProfile/index.tsx b/app/client/src/git/components/LocalProfile/index.tsx index 1525abb4fb08..221a01ef5969 100644 --- a/app/client/src/git/components/LocalProfile/index.tsx +++ b/app/client/src/git/components/LocalProfile/index.tsx @@ -4,13 +4,20 @@ import useLocalProfile from "git/hooks/useLocalProfile"; import useGlobalProfile from "git/hooks/useGlobalProfile"; function LocalProfile() { - const { isFetchLocalProfileLoading, localProfile, updateLocalProfile } = - useLocalProfile(); + const { + fetchLocalProfile, + isFetchLocalProfileLoading, + localProfile, + updateLocalProfile, + } = useLocalProfile(); - const { globalProfile, isFetchGlobalProfileLoading } = useGlobalProfile(); + const { fetchGlobalProfile, globalProfile, isFetchGlobalProfileLoading } = + useGlobalProfile(); return ( { + const fetchGlobalProfile = useCallback(() => { dispatch(gitConfigActions.fetchGlobalProfileInit()); - }; + }, [dispatch]); const updateGlobalProfileState = useSelector((state: GitRootState) => selectFetchGlobalProfileState(state), ); - const updateGlobalProfile = (params: UpdateGlobalProfileRequestParams) => { - dispatch(gitConfigActions.updateGlobalProfileInit(params)); - }; + const updateGlobalProfile = useCallback( + (params: UpdateGlobalProfileRequestParams) => { + dispatch(gitConfigActions.updateGlobalProfileInit(params)); + }, + [dispatch], + ); return { globalProfile: fetchGlobalProfileState?.value ?? null, diff --git a/app/client/src/git/hooks/useLocalProfile.ts b/app/client/src/git/hooks/useLocalProfile.ts index e3cc32fa8d04..ccac5bbcb875 100644 --- a/app/client/src/git/hooks/useLocalProfile.ts +++ b/app/client/src/git/hooks/useLocalProfile.ts @@ -4,6 +4,7 @@ import { gitArtifactActions } from "git/store/gitArtifactSlice"; import { selectFetchGlobalProfileState } from "git/store/selectors/gitConfigSelectors"; import { selectFetchLocalProfileState } from "git/store/selectors/gitSingleArtifactSelectors"; import type { GitRootState } from "git/store/types"; +import { useCallback } from "react"; import { useDispatch, useSelector } from "react-redux"; export default function useLocalProfile() { @@ -15,22 +16,25 @@ export default function useLocalProfile() { selectFetchLocalProfileState(state, artifactDef), ); - const fetchLocalProfile = () => { + const fetchLocalProfile = useCallback(() => { dispatch(gitArtifactActions.fetchLocalProfileInit(artifactDef)); - }; + }, [artifactDef, dispatch]); const updateLocalProfileState = useSelector((state: GitRootState) => selectFetchGlobalProfileState(state), ); - const updateLocalProfile = (params: UpdateLocalProfileRequestParams) => { - dispatch( - gitArtifactActions.updateLocalProfileInit({ - ...artifactDef, - ...params, - }), - ); - }; + const updateLocalProfile = useCallback( + (params: UpdateLocalProfileRequestParams) => { + dispatch( + gitArtifactActions.updateLocalProfileInit({ + ...artifactDef, + ...params, + }), + ); + }, + [artifactDef, dispatch], + ); return { localProfile: fetchLocalProfileState?.value ?? null, From e23819b2f21920aa436b16960da4fd00bc287b2c Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Sat, 14 Dec 2024 08:10:37 +0800 Subject: [PATCH 058/143] chore: adding general tab --- .../git/components/ConflictError/index.tsx | 6 +- .../components/DangerZone/DangerZoneView.tsx | 160 ++++++++++++++++++ .../src/git/components/DangerZone/index.tsx | 31 +++- .../DefaultBranch/DefaultBranchView.tsx | 9 +- .../hooks/useGitContextValue.ts | 12 +- .../hooks/useGitMetadata.ts | 45 ----- .../hooks/useGitSettings.ts | 78 --------- .../components/OpsModal/TabDeploy/index.tsx | 5 +- .../src/git/components/OpsModal/index.tsx | 14 +- .../src/git/components/QuickActions/index.tsx | 16 +- .../git/components/SettingsModal/index.tsx | 8 +- app/client/src/git/hooks/useAutocommit.ts | 58 +++++++ app/client/src/git/hooks/useDisconnect.ts | 54 ++++++ app/client/src/git/hooks/useMetadata.ts | 26 +++ app/client/src/git/hooks/useSettings.ts | 42 +++++ ...dataRequest.ts => fetchMetadataRequest.ts} | 6 +- ...types.ts => fetchMetadataRequest.types.ts} | 5 +- ...itMetadataSaga.ts => fetchMetadataSaga.ts} | 16 +- app/client/src/git/sagas/index.ts | 4 +- app/client/src/git/sagas/initGitSaga.ts | 4 +- ...dataActions.ts => fetchMetadataActions.ts} | 20 +-- .../src/git/store/actions/initGitActions.ts | 4 +- app/client/src/git/store/actions/uiActions.ts | 102 +++++++---- app/client/src/git/store/gitArtifactSlice.ts | 28 ++- .../helpers/gitSingleArtifactInitialState.ts | 8 +- .../selectors/gitSingleArtifactSelectors.ts | 38 ++++- app/client/src/git/store/types.ts | 12 +- 27 files changed, 567 insertions(+), 244 deletions(-) create mode 100644 app/client/src/git/components/DangerZone/DangerZoneView.tsx delete mode 100644 app/client/src/git/components/GitContextProvider/hooks/useGitSettings.ts create mode 100644 app/client/src/git/hooks/useAutocommit.ts create mode 100644 app/client/src/git/hooks/useDisconnect.ts create mode 100644 app/client/src/git/hooks/useMetadata.ts create mode 100644 app/client/src/git/hooks/useSettings.ts rename app/client/src/git/requests/{fetchGitMetadataRequest.ts => fetchMetadataRequest.ts} (54%) rename app/client/src/git/requests/{fetchGitMetadataRequest.types.ts => fetchMetadataRequest.types.ts} (74%) rename app/client/src/git/sagas/{fetchGitMetadataSaga.ts => fetchMetadataSaga.ts} (65%) rename app/client/src/git/store/actions/{fetchGitMetadataActions.ts => fetchMetadataActions.ts} (54%) diff --git a/app/client/src/git/components/ConflictError/index.tsx b/app/client/src/git/components/ConflictError/index.tsx index c5d49533f8ed..babe539e3eb5 100644 --- a/app/client/src/git/components/ConflictError/index.tsx +++ b/app/client/src/git/components/ConflictError/index.tsx @@ -1,15 +1,15 @@ import React from "react"; -import { useGitContext } from "../GitContextProvider"; import GitConflictErrorView from "./ConflictErrorView"; +import useMetadata from "git/hooks/useMetadata"; export default function ConflictError() { - const { gitMetadata } = useGitContext(); + const { metadata } = useMetadata(); // ! case: learnMoreUrl comes from pullError const learnMoreUrl = "https://docs.appsmith.com/advanced-concepts/version-control-with-git"; - const repoUrl = gitMetadata?.browserSupportedRemoteUrl || ""; + const repoUrl = metadata?.browserSupportedRemoteUrl || ""; return ; } diff --git a/app/client/src/git/components/DangerZone/DangerZoneView.tsx b/app/client/src/git/components/DangerZone/DangerZoneView.tsx new file mode 100644 index 000000000000..19d564bcf39d --- /dev/null +++ b/app/client/src/git/components/DangerZone/DangerZoneView.tsx @@ -0,0 +1,160 @@ +import { + AUTOCOMMIT, + AUTOCOMMIT_DISABLE, + AUTOCOMMIT_ENABLE, + AUTOCOMMIT_MESSAGE, + DANGER_ZONE, + DISCONNECT_GIT, + DISCONNECT_GIT_MESSAGE, + createMessage, +} from "ee/constants/messages"; +import { Button, Divider, Text } from "@appsmith/ads"; +import React, { useCallback } from "react"; +import styled from "styled-components"; +import AnalyticsUtil from "ee/utils/AnalyticsUtil"; +import noop from "lodash/noop"; +import type { GitSettingsTab } from "git/constants/enums"; + +const Container = styled.div` + padding-top: 16px; + padding-bottom: 16px; +`; + +const HeadContainer = styled.div` + margin-bottom: 16px; +`; + +const ZoneContainer = styled.div` + border: solid 0.4px var(--ads-v2-color-red-600); + padding: 12px; + border-radius: 4px; +`; + +const BodyContainer = styled.div` + display: flex; + align-items: center; +`; + +const BodyInnerContainer = styled.div` + flex: 1; + margin-right: 32px; +`; + +const SectionTitle = styled(Text)` + font-weight: 600; +`; + +const StyledDivider = styled(Divider)` + display: block; + margin-top: 16px; + margin-bottom: 16px; +`; + +interface DangerZoneViewProps { + closeDisconnectModal: () => void; + isConnectPermitted: boolean; + isManageAutocommitPermitted: boolean; + isToggleAutocommitLoading: boolean; + isAutocommitEnabled: boolean; + isMetadataLoading: boolean; + openDisconnectModal: () => void; + toggleAutocommit: () => void; + toggleDisableAutocommitModal: (open: boolean) => void; + toggleSettingsModal: ( + open: boolean, + tab?: keyof typeof GitSettingsTab, + ) => void; +} + +function DangerZoneView({ + isAutocommitEnabled = false, + isConnectPermitted = false, + isManageAutocommitPermitted = false, + isMetadataLoading = false, + isToggleAutocommitLoading = false, + openDisconnectModal = noop, + toggleAutocommit = noop, + toggleDisableAutocommitModal = noop, + toggleSettingsModal = noop, +}: DangerZoneViewProps) { + const handleDisconnect = useCallback(() => { + AnalyticsUtil.logEvent("GS_DISCONNECT_GIT_CLICK", { + source: "GIT_CONNECTION_MODAL", + }); + toggleSettingsModal(false); + openDisconnectModal(); + }, [openDisconnectModal, toggleSettingsModal]); + + const handleToggleAutocommit = useCallback(() => { + if (isAutocommitEnabled) { + toggleSettingsModal(false); + toggleDisableAutocommitModal(true); + } else { + toggleAutocommit(); + AnalyticsUtil.logEvent("GS_AUTO_COMMIT_ENABLED"); + } + }, [ + isAutocommitEnabled, + toggleAutocommit, + toggleDisableAutocommitModal, + toggleSettingsModal, + ]); + + const showAutoCommit = isManageAutocommitPermitted; + const showDisconnect = isConnectPermitted; + const showDivider = showAutoCommit && showDisconnect; + + return ( + + + + {createMessage(DANGER_ZONE)} + + + + {showAutoCommit && ( + + + + {createMessage(AUTOCOMMIT)} + + {createMessage(AUTOCOMMIT_MESSAGE)} + + + + )} + {showDivider && } + {showDisconnect && ( + + + + {createMessage(DISCONNECT_GIT)} + + {createMessage(DISCONNECT_GIT_MESSAGE)} + + + + )} + + + ); +} + +export default DangerZoneView; diff --git a/app/client/src/git/components/DangerZone/index.tsx b/app/client/src/git/components/DangerZone/index.tsx index 00a8640adea5..6fec7113a017 100644 --- a/app/client/src/git/components/DangerZone/index.tsx +++ b/app/client/src/git/components/DangerZone/index.tsx @@ -1,7 +1,36 @@ +import useAutocommit from "git/hooks/useAutocommit"; +import useDisconnect from "git/hooks/useDisconnect"; +import useGitPermissions from "git/hooks/useGitPermissions"; +import useSettings from "git/hooks/useSettings"; import React from "react"; +import DangerZoneView from "./DangerZoneView"; function DangerZone() { - return
DangerZone
; + const { closeDisconnectModal, openDisconnectModal } = useDisconnect(); + const { isConnectPermitted, isManageAutocommitPermitted } = + useGitPermissions(); + const { + isAutocommitEnabled, + isToggleAutocommitLoading, + toggleAutocommit, + toggleAutocommitDisableModal, + } = useAutocommit(); + const { toggleSettingsModal } = useSettings(); + + return ( + + ); } export default DangerZone; diff --git a/app/client/src/git/components/DefaultBranch/DefaultBranchView.tsx b/app/client/src/git/components/DefaultBranch/DefaultBranchView.tsx index d2152076f3e8..692c9403cf5f 100644 --- a/app/client/src/git/components/DefaultBranch/DefaultBranchView.tsx +++ b/app/client/src/git/components/DefaultBranch/DefaultBranchView.tsx @@ -40,6 +40,10 @@ const StyledSelect = styled(Select)` margin-right: 12px; `; +const StyledLink = styled(Link)` + display: inline-flex; +`; + interface DefaultBranchViewProps { branches: FetchBranchesResponseData | null; isGitProtectedFeatureLicensed: boolean; @@ -107,14 +111,13 @@ function DefaultBranchView({ {!isGitProtectedFeatureLicensed && ( To change your default branch, try{" "} - {createMessage(APPSMITH_ENTERPRISE)} - + )} diff --git a/app/client/src/git/components/GitContextProvider/hooks/useGitContextValue.ts b/app/client/src/git/components/GitContextProvider/hooks/useGitContextValue.ts index 56c0ad4b7fb3..9b62bc1ba4cf 100644 --- a/app/client/src/git/components/GitContextProvider/hooks/useGitContextValue.ts +++ b/app/client/src/git/components/GitContextProvider/hooks/useGitContextValue.ts @@ -1,15 +1,11 @@ import type { GitArtifactType } from "git/constants/enums"; import type { UseGitConnectReturnValue } from "./useGitConnect"; import type { UseGitOpsReturnValue } from "./useGitOps"; -import type { UseGitSettingsReturnValue } from "./useGitSettings"; import type { UseGitBranchesReturnValue } from "./useGitBranches"; import useGitConnect from "./useGitConnect"; import useGitOps from "./useGitOps"; import useGitBranches from "./useGitBranches"; -import useGitSettings from "./useGitSettings"; import { useMemo } from "react"; -import type { UseGitMetadataReturnValue } from "./useGitMetadata"; -import useGitMetadata from "./useGitMetadata"; // internal dependencies import type { ApplicationPayload } from "entities/Application"; @@ -26,10 +22,8 @@ export interface UseGitContextValueParams { } export interface GitContextValue - extends UseGitMetadataReturnValue, - UseGitConnectReturnValue, + extends UseGitConnectReturnValue, UseGitOpsReturnValue, - UseGitSettingsReturnValue, UseGitBranchesReturnValue { artifactType: keyof typeof GitArtifactType; baseArtifactId: string; @@ -53,14 +47,12 @@ export default function useGitContextValue({ () => ({ artifactType, baseArtifactId }), [artifactType, baseArtifactId], ); - const useGitMetadataReturnValue = useGitMetadata(artifactDef); const useGitConnectReturnValue = useGitConnect(artifactDef); const useGitOpsReturnValue = useGitOps({ ...artifactDef, artifactId: artifact?.id ?? null, }); const useGitBranchesReturnValue = useGitBranches(artifactDef); - const useGitSettingsReturnValue = useGitSettings(artifactDef); return { artifactType, @@ -68,10 +60,8 @@ export default function useGitContextValue({ artifactDef, statusTransformer, artifact, - ...useGitMetadataReturnValue, ...useGitOpsReturnValue, ...useGitBranchesReturnValue, ...useGitConnectReturnValue, - ...useGitSettingsReturnValue, }; } diff --git a/app/client/src/git/components/GitContextProvider/hooks/useGitMetadata.ts b/app/client/src/git/components/GitContextProvider/hooks/useGitMetadata.ts index aabc125c8382..e69de29bb2d1 100644 --- a/app/client/src/git/components/GitContextProvider/hooks/useGitMetadata.ts +++ b/app/client/src/git/components/GitContextProvider/hooks/useGitMetadata.ts @@ -1,45 +0,0 @@ -import type { GitArtifactType } from "git/constants/enums"; -import type { FetchGitMetadataResponseData } from "git/requests/fetchGitMetadataRequest.types"; -import { - selectGitConnected, - selectGitMetadata, -} from "git/store/selectors/gitSingleArtifactSelectors"; -import type { GitApiError, GitRootState } from "git/store/types"; -import { useMemo } from "react"; -import { useSelector } from "react-redux"; - -interface UseGitMetadataParams { - artifactType: keyof typeof GitArtifactType; - baseArtifactId: string; -} - -export interface UseGitMetadataReturnValue { - gitMetadata: FetchGitMetadataResponseData | null; - fetchGitMetadataLoading: boolean; - fetchGitMetadataError: GitApiError | null; - gitConnected: boolean; -} - -export default function useGitMetadata({ - artifactType, - baseArtifactId, -}: UseGitMetadataParams): UseGitMetadataReturnValue { - const basePayload = useMemo( - () => ({ artifactType, baseArtifactId }), - [artifactType, baseArtifactId], - ); - - const gitMetadataState = useSelector((state: GitRootState) => - selectGitMetadata(state, basePayload), - ); - const gitConnected = useSelector((state: GitRootState) => - selectGitConnected(state, basePayload), - ); - - return { - gitMetadata: gitMetadataState.value, - fetchGitMetadataLoading: gitMetadataState.loading ?? false, - fetchGitMetadataError: gitMetadataState.error, - gitConnected: gitConnected ?? false, - }; -} diff --git a/app/client/src/git/components/GitContextProvider/hooks/useGitSettings.ts b/app/client/src/git/components/GitContextProvider/hooks/useGitSettings.ts deleted file mode 100644 index 2f54d90dfdec..000000000000 --- a/app/client/src/git/components/GitContextProvider/hooks/useGitSettings.ts +++ /dev/null @@ -1,78 +0,0 @@ -import { GitSettingsTab, type GitArtifactType } from "git/constants/enums"; -import { gitArtifactActions } from "git/store/gitArtifactSlice"; -import { - selectAutocommitEnabled, - selectAutocommitPolling, - selectSettingsModalOpen, - selectSettingsModalTab, -} from "git/store/selectors/gitSingleArtifactSelectors"; -import type { GitRootState } from "git/store/types"; -import { useMemo } from "react"; -import { useDispatch, useSelector } from "react-redux"; - -interface UseGitSettingsParams { - artifactType: keyof typeof GitArtifactType; - baseArtifactId: string; -} - -export interface UseGitSettingsReturnValue { - autocommitEnabled: boolean; - autocommitPolling: boolean; - settingsModalOpen: boolean; - settingsModalTab: keyof typeof GitSettingsTab; - toggleSettingsModal: ( - open: boolean, - tab?: keyof typeof GitSettingsTab, - ) => void; -} - -export default function useGitSettings({ - artifactType, - baseArtifactId, -}: UseGitSettingsParams): UseGitSettingsReturnValue { - const dispatch = useDispatch(); - const basePayload = useMemo( - () => ({ artifactType, baseArtifactId }), - [artifactType, baseArtifactId], - ); - - // autocommit - const autocommitEnabled = useSelector((state: GitRootState) => - selectAutocommitEnabled(state, basePayload), - ); - - const autocommitPolling = useSelector((state: GitRootState) => - selectAutocommitPolling(state, basePayload), - ); - - // ui - const settingsModalOpen = useSelector((state: GitRootState) => - selectSettingsModalOpen(state, basePayload), - ); - - const settingsModalTab = useSelector((state: GitRootState) => - selectSettingsModalTab(state, basePayload), - ); - - const toggleSettingsModal = ( - open: boolean, - tab: keyof typeof GitSettingsTab = GitSettingsTab.General, - ) => { - dispatch( - gitArtifactActions.toggleSettingsModal({ - ...basePayload, - open, - tab, - }), - ); - }; - - return { - autocommitEnabled: autocommitEnabled ?? false, - autocommitPolling: autocommitPolling ?? false, - - settingsModalOpen: settingsModalOpen ?? false, - settingsModalTab: settingsModalTab ?? GitSettingsTab.General, - toggleSettingsModal, - }; -} diff --git a/app/client/src/git/components/OpsModal/TabDeploy/index.tsx b/app/client/src/git/components/OpsModal/TabDeploy/index.tsx index e363f571f4fe..53d1a8f4c6af 100644 --- a/app/client/src/git/components/OpsModal/TabDeploy/index.tsx +++ b/app/client/src/git/components/OpsModal/TabDeploy/index.tsx @@ -1,6 +1,7 @@ import React from "react"; import TabDeployView from "./TabDeployView"; import { useGitContext } from "git/components/GitContextProvider"; +import useMetadata from "git/hooks/useMetadata"; export default function TabDeploy() { const { @@ -15,18 +16,18 @@ export default function TabDeploy() { discardError, discardLoading, fetchStatusLoading, - gitMetadata, pull, pullError, pullLoading, status, } = useGitContext(); + const { metadata } = useMetadata(); const lastDeployedAt = artifact?.lastDeployedAt ?? null; const isPullFailing = !!pullError; const statusIsClean = status?.isClean ?? false; const statusBehindCount = status?.behindCount ?? 0; - const remoteUrl = gitMetadata?.remoteUrl ?? ""; + const remoteUrl = metadata?.remoteUrl ?? null; return ( diff --git a/app/client/src/git/hooks/useAutocommit.ts b/app/client/src/git/hooks/useAutocommit.ts new file mode 100644 index 000000000000..b342b7442b29 --- /dev/null +++ b/app/client/src/git/hooks/useAutocommit.ts @@ -0,0 +1,58 @@ +import { useGitContext } from "git/components/GitContextProvider"; +import { gitArtifactActions } from "git/store/gitArtifactSlice"; +import { + selectAutocommitDisableModalOpen, + selectAutocommitEnabled, + selectAutocommitPolling, + selectToggleAutocommitState, +} from "git/store/selectors/gitSingleArtifactSelectors"; +import type { GitRootState } from "git/store/types"; +import { useCallback } from "react"; +import { useDispatch, useSelector } from "react-redux"; + +export default function useAutocommit() { + const { artifactDef } = useGitContext(); + const dispatch = useDispatch(); + + const toggleAutocommitState = useSelector((state: GitRootState) => + selectToggleAutocommitState(state, artifactDef), + ); + + const toggleAutocommit = useCallback(() => { + dispatch(gitArtifactActions.toggleAutocommitInit(artifactDef)); + }, [artifactDef, dispatch]); + + const isAutocommitDisableModalOpen = useSelector((state: GitRootState) => + selectAutocommitDisableModalOpen(state, artifactDef), + ); + + const toggleAutocommitDisableModal = useCallback( + (open: boolean) => { + dispatch( + gitArtifactActions.toggleAutocommitDisableModal({ + ...artifactDef, + open, + }), + ); + }, + [artifactDef, dispatch], + ); + + const isAutocommitEnabled = useSelector((state: GitRootState) => + selectAutocommitEnabled(state, artifactDef), + ); + + const isAutocommitPolling = useSelector((state: GitRootState) => + selectAutocommitPolling(state, artifactDef), + ); + + return { + isToggleAutocommitLoading: toggleAutocommitState?.loading ?? false, + toggleAutocommitError: toggleAutocommitState?.error ?? null, + toggleAutocommit, + isAutocommitDisableModalOpen, + toggleAutocommitDisableModal, + isAutocommitEnabled, + isAutocommitPolling, + }; +} diff --git a/app/client/src/git/hooks/useDisconnect.ts b/app/client/src/git/hooks/useDisconnect.ts new file mode 100644 index 000000000000..b320dfff0824 --- /dev/null +++ b/app/client/src/git/hooks/useDisconnect.ts @@ -0,0 +1,54 @@ +import { useGitContext } from "git/components/GitContextProvider"; +import { gitArtifactActions } from "git/store/gitArtifactSlice"; +import { + selectDisconnectArtifactName, + selectDisconnectBaseArtifactId, + selectDisconnectState, +} from "git/store/selectors/gitSingleArtifactSelectors"; +import type { GitRootState } from "git/store/types"; +import { useCallback } from "react"; +import { useDispatch, useSelector } from "react-redux"; + +export default function useDisconnect() { + const { artifact, artifactDef } = useGitContext(); + const artifactName = artifact?.name ?? "application"; + + const dispatch = useDispatch(); + + const disconnectState = useSelector((state: GitRootState) => + selectDisconnectState(state, artifactDef), + ); + + const disconnect = useCallback(() => { + dispatch(gitArtifactActions.disconnectInit(artifactDef)); + }, [artifactDef, dispatch]); + + const diconnectBaseArtifactId = useSelector((state: GitRootState) => + selectDisconnectBaseArtifactId(state, artifactDef), + ); + + const disconnectArtifactName = useSelector((state: GitRootState) => + selectDisconnectArtifactName(state, artifactDef), + ); + + const openDisconnectModal = useCallback(() => { + dispatch( + gitArtifactActions.openDisconnectModal({ ...artifactDef, artifactName }), + ); + }, [artifactDef, artifactName, dispatch]); + + const closeDisconnectModal = useCallback(() => { + dispatch(gitArtifactActions.closeDisconnectModal(artifactDef)); + }, [artifactDef, dispatch]); + + return { + isDisconnectLoading: disconnectState?.loading ?? false, + disconnectError: disconnectState?.error ?? null, + disconnect, + isDisconnectModalOpen: !!diconnectBaseArtifactId, + diconnectBaseArtifactId, + disconnectArtifactName, + openDisconnectModal, + closeDisconnectModal, + }; +} diff --git a/app/client/src/git/hooks/useMetadata.ts b/app/client/src/git/hooks/useMetadata.ts new file mode 100644 index 000000000000..ae202588e37a --- /dev/null +++ b/app/client/src/git/hooks/useMetadata.ts @@ -0,0 +1,26 @@ +import { useGitContext } from "git/components/GitContextProvider"; +import { + selectGitConnected, + selectMetadataState, +} from "git/store/selectors/gitSingleArtifactSelectors"; +import type { GitRootState } from "git/store/types"; +import { useSelector } from "react-redux"; + +export default function useMetadata() { + const { artifactDef } = useGitContext(); + + const metadataState = useSelector((state: GitRootState) => + selectMetadataState(state, artifactDef), + ); + + const isGitConnected = useSelector((state: GitRootState) => + selectGitConnected(state, artifactDef), + ); + + return { + metadata: metadataState.value ?? null, + fetchMetadataLoading: metadataState.loading ?? false, + fetchMetadataError: metadataState.error ?? null, + isGitConnected, + }; +} diff --git a/app/client/src/git/hooks/useSettings.ts b/app/client/src/git/hooks/useSettings.ts new file mode 100644 index 000000000000..d94f9c0e530b --- /dev/null +++ b/app/client/src/git/hooks/useSettings.ts @@ -0,0 +1,42 @@ +import { useGitContext } from "git/components/GitContextProvider"; +import { GitSettingsTab } from "git/constants/enums"; +import { gitArtifactActions } from "git/store/gitArtifactSlice"; +import { + selectSettingsModalOpen, + selectSettingsModalTab, +} from "git/store/selectors/gitSingleArtifactSelectors"; +import type { GitRootState } from "git/store/types"; +import { useCallback } from "react"; +import { useDispatch, useSelector } from "react-redux"; + +export default function useSettings() { + const { artifactDef } = useGitContext(); + + const dispatch = useDispatch(); + + const settingsModalOpen = useSelector((state: GitRootState) => + selectSettingsModalOpen(state, artifactDef), + ); + + const settingsModalTab = useSelector((state: GitRootState) => + selectSettingsModalTab(state, artifactDef), + ); + + const toggleSettingsModal = useCallback( + ( + open: boolean, + tab: keyof typeof GitSettingsTab = GitSettingsTab.General, + ) => { + dispatch( + gitArtifactActions.toggleSettingsModal({ ...artifactDef, open, tab }), + ); + }, + [artifactDef, dispatch], + ); + + return { + isSettingsModalOpen: settingsModalOpen ?? false, + settingsModalTab: settingsModalTab ?? GitSettingsTab.General, + toggleSettingsModal, + }; +} diff --git a/app/client/src/git/requests/fetchGitMetadataRequest.ts b/app/client/src/git/requests/fetchMetadataRequest.ts similarity index 54% rename from app/client/src/git/requests/fetchGitMetadataRequest.ts rename to app/client/src/git/requests/fetchMetadataRequest.ts index 7b3376b8ef0e..72c7762af4c4 100644 --- a/app/client/src/git/requests/fetchGitMetadataRequest.ts +++ b/app/client/src/git/requests/fetchMetadataRequest.ts @@ -1,10 +1,10 @@ import Api from "api/Api"; import { GIT_BASE_URL } from "./constants"; import type { AxiosPromise } from "axios"; -import type { FetchGitMetadataResponse } from "./fetchGitMetadataRequest.types"; +import type { FetchMetadataResponse } from "./fetchMetadataRequest.types"; -export default async function fetchGitMetadataRequest( +export default async function fetchMetadataRequest( baseApplicationId: string, -): AxiosPromise { +): AxiosPromise { return Api.get(`${GIT_BASE_URL}/metadata/app/${baseApplicationId}`); } diff --git a/app/client/src/git/requests/fetchGitMetadataRequest.types.ts b/app/client/src/git/requests/fetchMetadataRequest.types.ts similarity index 74% rename from app/client/src/git/requests/fetchGitMetadataRequest.types.ts rename to app/client/src/git/requests/fetchMetadataRequest.types.ts index c532052e9793..f93568cc9f08 100644 --- a/app/client/src/git/requests/fetchGitMetadataRequest.types.ts +++ b/app/client/src/git/requests/fetchMetadataRequest.types.ts @@ -1,6 +1,6 @@ import type { ApiResponse } from "api/types"; -export interface FetchGitMetadataResponseData { +export interface FetchMetadataResponseData { branchName: string; defaultBranchName: string; remoteUrl: string; @@ -16,5 +16,4 @@ export interface FetchGitMetadataResponseData { isAutoDeploymentEnabled?: boolean; } -export type FetchGitMetadataResponse = - ApiResponse; +export type FetchMetadataResponse = ApiResponse; diff --git a/app/client/src/git/sagas/fetchGitMetadataSaga.ts b/app/client/src/git/sagas/fetchMetadataSaga.ts similarity index 65% rename from app/client/src/git/sagas/fetchGitMetadataSaga.ts rename to app/client/src/git/sagas/fetchMetadataSaga.ts index a91122b83682..3e2029b6c6b8 100644 --- a/app/client/src/git/sagas/fetchGitMetadataSaga.ts +++ b/app/client/src/git/sagas/fetchMetadataSaga.ts @@ -1,26 +1,24 @@ import { captureException } from "@sentry/react"; -import fetchGitMetadataRequest from "git/requests/fetchGitMetadataRequest"; -import type { FetchGitMetadataResponse } from "git/requests/fetchGitMetadataRequest.types"; +import fetchMetadataRequest from "git/requests/fetchMetadataRequest"; +import type { FetchMetadataResponse } from "git/requests/fetchMetadataRequest.types"; import { gitArtifactActions } from "git/store/gitArtifactSlice"; import type { GitArtifactPayloadAction } from "git/store/types"; import log from "loglevel"; import { call, put } from "redux-saga/effects"; import { validateResponse } from "sagas/ErrorSagas"; -export default function* fetchGitMetadataSaga( - action: GitArtifactPayloadAction, -) { +export default function* fetchMetadataSaga(action: GitArtifactPayloadAction) { const { artifactType, baseArtifactId } = action.payload; const basePayload = { artifactType, baseArtifactId }; - let response: FetchGitMetadataResponse | undefined; + let response: FetchMetadataResponse | undefined; try { - response = yield call(fetchGitMetadataRequest, baseArtifactId); + response = yield call(fetchMetadataRequest, baseArtifactId); const isValidResponse: boolean = yield validateResponse(response, false); if (response && isValidResponse) { yield put( - gitArtifactActions.fetchGitMetadataSuccess({ + gitArtifactActions.fetchMetadataSuccess({ ...basePayload, responseData: response.data, }), @@ -31,7 +29,7 @@ export default function* fetchGitMetadataSaga( const { error } = response.responseMeta; yield put( - gitArtifactActions.fetchGitMetadataError({ + gitArtifactActions.fetchMetadataError({ ...basePayload, error, }), diff --git a/app/client/src/git/sagas/index.ts b/app/client/src/git/sagas/index.ts index d0ac2c5c89e5..42ea31b0a985 100644 --- a/app/client/src/git/sagas/index.ts +++ b/app/client/src/git/sagas/index.ts @@ -18,7 +18,6 @@ import fetchLocalProfileSaga from "./fetchLocalProfileSaga"; import updateLocalProfileSaga from "./updateLocalProfileSaga"; import updateGlobalProfileSaga from "./updateGlobalProfileSaga"; import initGitForEditorSaga from "./initGitSaga"; -import fetchGitMetadataSaga from "./fetchGitMetadataSaga"; import triggerAutocommitSaga from "./triggerAutocommitSaga"; import fetchStatusSaga from "./fetchStatusSaga"; import fetchProtectedBranchesSaga from "./fetchProtectedBranchesSaga"; @@ -29,6 +28,7 @@ import { gitRequestNonBlockingActionsEE, } from "ee/git/sagas"; import updateProtectedBranchesSaga from "./updateProtectedBranchesSaga"; +import fetchMetadataSaga from "./fetchMetadataSaga"; const gitRequestBlockingActions: Record< string, @@ -36,7 +36,7 @@ const gitRequestBlockingActions: Record< (action: PayloadAction) => Generator > = { // init - [gitArtifactActions.fetchGitMetadataInit.type]: fetchGitMetadataSaga, + [gitArtifactActions.fetchMetadataInit.type]: fetchMetadataSaga, // connect [gitArtifactActions.connectInit.type]: connectSaga, diff --git a/app/client/src/git/sagas/initGitSaga.ts b/app/client/src/git/sagas/initGitSaga.ts index c0177f32f5bd..2c62fd31851b 100644 --- a/app/client/src/git/sagas/initGitSaga.ts +++ b/app/client/src/git/sagas/initGitSaga.ts @@ -14,8 +14,8 @@ export default function* initGitForEditorSaga( if (artifactType === GitArtifactType.Application) { if (!!artifact.gitApplicationMetadata) { - yield put(gitArtifactActions.fetchGitMetadataInit(basePayload)); - yield take(gitArtifactActions.fetchGitMetadataSuccess.type); + yield put(gitArtifactActions.fetchMetadataInit(basePayload)); + yield take(gitArtifactActions.fetchMetadataSuccess.type); yield put( gitArtifactActions.triggerAutocommitInit({ ...basePayload, diff --git a/app/client/src/git/store/actions/fetchGitMetadataActions.ts b/app/client/src/git/store/actions/fetchMetadataActions.ts similarity index 54% rename from app/client/src/git/store/actions/fetchGitMetadataActions.ts rename to app/client/src/git/store/actions/fetchMetadataActions.ts index 6bbb8d41d380..176413dfbaaa 100644 --- a/app/client/src/git/store/actions/fetchGitMetadataActions.ts +++ b/app/client/src/git/store/actions/fetchMetadataActions.ts @@ -1,18 +1,16 @@ import type { GitAsyncErrorPayload, GitAsyncSuccessPayload } from "../types"; import { createSingleArtifactAction } from "../helpers/createSingleArtifactAction"; -import type { FetchGitMetadataResponseData } from "git/requests/fetchGitMetadataRequest.types"; +import type { FetchMetadataResponseData } from "git/requests/fetchMetadataRequest.types"; -export const fetchGitMetadataInitAction = createSingleArtifactAction( - (state) => { - state.apiResponses.metadata.loading = true; - state.apiResponses.metadata.error = null; +export const fetchMetadataInitAction = createSingleArtifactAction((state) => { + state.apiResponses.metadata.loading = true; + state.apiResponses.metadata.error = null; - return state; - }, -); + return state; +}); -export const fetchGitMetadataSuccessAction = createSingleArtifactAction< - GitAsyncSuccessPayload +export const fetchMetadataSuccessAction = createSingleArtifactAction< + GitAsyncSuccessPayload >((state, action) => { state.apiResponses.metadata.loading = false; state.apiResponses.metadata.value = action.payload.responseData; @@ -20,7 +18,7 @@ export const fetchGitMetadataSuccessAction = createSingleArtifactAction< return state; }); -export const fetchGitMetadataErrorAction = +export const fetchMetadataErrorAction = createSingleArtifactAction((state, action) => { const { error } = action.payload; diff --git a/app/client/src/git/store/actions/initGitActions.ts b/app/client/src/git/store/actions/initGitActions.ts index 5ba453b0edaf..d93cf955eeec 100644 --- a/app/client/src/git/store/actions/initGitActions.ts +++ b/app/client/src/git/store/actions/initGitActions.ts @@ -1,11 +1,11 @@ -import type { FetchGitMetadataResponseData } from "git/requests/fetchGitMetadataRequest.types"; +import type { FetchMetadataResponseData } from "git/requests/fetchMetadataRequest.types"; import { createSingleArtifactAction } from "../helpers/createSingleArtifactAction"; export interface InitGitForEditorPayload { artifact: { id: string; baseId: string; - gitApplicationMetadata?: Partial; + gitApplicationMetadata?: Partial; }; } diff --git a/app/client/src/git/store/actions/uiActions.ts b/app/client/src/git/store/actions/uiActions.ts index 3d5c76252e52..6780ee64a4bb 100644 --- a/app/client/src/git/store/actions/uiActions.ts +++ b/app/client/src/git/store/actions/uiActions.ts @@ -1,46 +1,43 @@ import type { GitOpsTab, GitSettingsTab } from "git/constants/enums"; import { createSingleArtifactAction } from "../helpers/createSingleArtifactAction"; -interface ToggleRepoLimitModalPayload { +// connect modal +export interface ToggleConnectModalPayload { open: boolean; } -export const toggleRepoLimitErrorModalAction = - createSingleArtifactAction((state, action) => { +export const toggleConnectModalAction = + createSingleArtifactAction((state, action) => { const { open } = action.payload; - state.ui.repoLimitErrorModal.open = open; + state.ui.connectModal.open = open; return state; }); -interface ToggleConflictErrorModalPayload { - open: boolean; +// disconnect modal +export interface OpenDisconnectModalPayload { + artifactName: string; } -export const toggleConflictErrorModalAction = - createSingleArtifactAction( - (state, action) => { - const { open } = action.payload; - - state.ui.conflictErrorModalOpen = open; - - return state; - }, - ); - -interface BranchListPopupPayload { - open: boolean; -} +export const openDisconnectModalAction = + createSingleArtifactAction((state, action) => { + state.ui.disconnectBaseArtifactId = action.payload.baseArtifactId; + state.ui.disconnectArtifactName = action.payload.artifactName; -export const toggleBranchListPopupAction = - createSingleArtifactAction((state, action) => { - const { open } = action.payload; + return state; + }); - state.ui.branchListPopup.open = open; +export const closeDisconnectModalAction = createSingleArtifactAction( + (state) => { + state.ui.disconnectBaseArtifactId = null; + state.ui.disconnectArtifactName = null; return state; - }); + }, +); + +// ops modal export interface ToggleOpsModalPayload { open: boolean; @@ -57,6 +54,7 @@ export const toggleOpsModalAction = return state; }); +// settings modal export interface ToggleSettingsModalPayload { open: boolean; tab: keyof typeof GitSettingsTab; @@ -72,15 +70,61 @@ export const toggleSettingsModalAction = return state; }); -export interface ToggleConnectModalPayload { +// autocommit modal +interface ToggleAutocommitDisableModalPayload { open: boolean; } -export const toggleConnectModalAction = - createSingleArtifactAction((state, action) => { +export const toggleAutocommitDisableModalAction = + createSingleArtifactAction( + (state, action) => { + const { open } = action.payload; + + state.ui.autocommitDisableModalOpen = open; + + return state; + }, + ); + +// branch popup +interface BranchListPopupPayload { + open: boolean; +} + +export const toggleBranchListPopupAction = + createSingleArtifactAction((state, action) => { const { open } = action.payload; - state.ui.connectModal.open = open; + state.ui.branchListPopup.open = open; return state; }); + +// error modals +interface ToggleRepoLimitModalPayload { + open: boolean; +} + +export const toggleRepoLimitErrorModalAction = + createSingleArtifactAction((state, action) => { + const { open } = action.payload; + + state.ui.repoLimitErrorModal.open = open; + + return state; + }); + +interface ToggleConflictErrorModalPayload { + open: boolean; +} + +export const toggleConflictErrorModalAction = + createSingleArtifactAction( + (state, action) => { + const { open } = action.payload; + + state.ui.conflictErrorModalOpen = open; + + return state; + }, + ); diff --git a/app/client/src/git/store/gitArtifactSlice.ts b/app/client/src/git/store/gitArtifactSlice.ts index 6c68c1aa1674..8a8ffd686f83 100644 --- a/app/client/src/git/store/gitArtifactSlice.ts +++ b/app/client/src/git/store/gitArtifactSlice.ts @@ -7,10 +7,10 @@ import { connectSuccessAction, } from "./actions/connectActions"; import { - fetchGitMetadataErrorAction, - fetchGitMetadataInitAction, - fetchGitMetadataSuccessAction, -} from "./actions/fetchGitMetadataActions"; + fetchMetadataErrorAction, + fetchMetadataInitAction, + fetchMetadataSuccessAction, +} from "./actions/fetchMetadataActions"; import { fetchBranchesErrorAction, fetchBranchesInitAction, @@ -59,6 +59,9 @@ import { toggleSettingsModalAction, toggleRepoLimitErrorModalAction, toggleConflictErrorModalAction, + openDisconnectModalAction, + closeDisconnectModalAction, + toggleAutocommitDisableModalAction, } from "./actions/uiActions"; import { checkoutBranchErrorAction, @@ -111,6 +114,11 @@ import { fetchAutocommitProgressSuccessAction, } from "./actions/fetchAutocommitProgressActions"; import gitArtifactCaseReducersEE from "ee/git/store/actions"; +import { + disconnectErrorAction, + disconnectInitAction, + disconnectSuccessAction, +} from "./actions/disconnectActions"; const initialState: GitArtifactReduxState = {}; @@ -123,15 +131,20 @@ export const gitArtifactSlice = createSlice({ initGitForEditor: initGitForEditorAction, mount: mountAction, unmount: unmountAction, - fetchGitMetadataInit: fetchGitMetadataInitAction, - fetchGitMetadataSuccess: fetchGitMetadataSuccessAction, - fetchGitMetadataError: fetchGitMetadataErrorAction, + fetchMetadataInit: fetchMetadataInitAction, + fetchMetadataSuccess: fetchMetadataSuccessAction, + fetchMetadataError: fetchMetadataErrorAction, // connect connectInit: connectInitAction, connectSuccess: connectSuccessAction, connectError: connectErrorAction, + disconnectInit: disconnectInitAction, + disconnectSuccess: disconnectSuccessAction, + disconnectError: disconnectErrorAction, toggleConnectModal: toggleConnectModalAction, + openDisconnectModal: openDisconnectModalAction, + closeDisconnectModal: closeDisconnectModalAction, toggleRepoLimitErrorModal: toggleRepoLimitErrorModalAction, // git ops @@ -201,6 +214,7 @@ export const gitArtifactSlice = createSlice({ fetchAutocommitProgressError: fetchAutocommitProgressErrorAction, pollAutocommitProgressStart: pollAutocommitProgressStartAction, pollAutocommitProgressStop: pollAutocommitProgressStopAction, + toggleAutocommitDisableModal: toggleAutocommitDisableModalAction, // EE ...gitArtifactCaseReducersEE, diff --git a/app/client/src/git/store/helpers/gitSingleArtifactInitialState.ts b/app/client/src/git/store/helpers/gitSingleArtifactInitialState.ts index 91c8d6b57eb0..13d0ec975cf4 100644 --- a/app/client/src/git/store/helpers/gitSingleArtifactInitialState.ts +++ b/app/client/src/git/store/helpers/gitSingleArtifactInitialState.ts @@ -19,6 +19,8 @@ const gitSingleArtifactInitialUIState: GitSingleArtifactUIReduxState = { open: false, step: GitConnectStep.Provider, }, + disconnectBaseArtifactId: null, + disconnectArtifactName: null, importModal: { open: false, step: GitImportStep.Provider, @@ -28,14 +30,14 @@ const gitSingleArtifactInitialUIState: GitSingleArtifactUIReduxState = { }, opsModalOpen: false, opsModalTab: GitOpsTab.Deploy, - conflictErrorModalOpen: false, settingsModalOpen: false, settingsModalTab: GitSettingsTab.General, + autocommitDisableModalOpen: false, + autocommitPolling: false, + conflictErrorModalOpen: false, repoLimitErrorModal: { open: false, }, - autocommitModalOpen: false, - autocommitPolling: false, // EE ...gitSingleArtifactInitialUIStateEE, }; diff --git a/app/client/src/git/store/selectors/gitSingleArtifactSelectors.ts b/app/client/src/git/store/selectors/gitSingleArtifactSelectors.ts index 3682da48fa34..a42338ee507c 100644 --- a/app/client/src/git/store/selectors/gitSingleArtifactSelectors.ts +++ b/app/client/src/git/store/selectors/gitSingleArtifactSelectors.ts @@ -16,7 +16,7 @@ export const selectGitArtifact = ( }; // metadata -export const selectGitMetadata = ( +export const selectMetadataState = ( state: GitRootState, artifactDef: GitArtifactDef, ) => selectGitArtifact(state, artifactDef)?.apiResponses.metadata; @@ -24,7 +24,23 @@ export const selectGitMetadata = ( export const selectGitConnected = ( state: GitRootState, artifactDef: GitArtifactDef, -) => !!selectGitMetadata(state, artifactDef).value; +) => !!selectMetadataState(state, artifactDef)?.value; + +// CONNECT +export const selectDisconnectState = ( + state: GitRootState, + artifactDef: GitArtifactDef, +) => selectGitArtifact(state, artifactDef)?.apiResponses.disconnect; + +export const selectDisconnectBaseArtifactId = ( + state: GitRootState, + artifactDef: GitArtifactDef, +) => selectGitArtifact(state, artifactDef)?.ui.disconnectBaseArtifactId; + +export const selectDisconnectArtifactName = ( + state: GitRootState, + artifactDef: GitArtifactDef, +) => selectGitArtifact(state, artifactDef)?.ui.disconnectArtifactName; // git ops export const selectCommit = ( @@ -74,7 +90,7 @@ export const selectCurrentBranch = ( state: GitRootState, artifactDef: GitArtifactDef, ) => { - const gitMetadataState = selectGitMetadata(state, artifactDef).value; + const gitMetadataState = selectMetadataState(state, artifactDef).value; return gitMetadataState?.branchName; }; @@ -113,13 +129,23 @@ export const selectUpdateLocalProfileState = ( ) => selectGitArtifact(state, artifactDef)?.apiResponses.updateLocalProfile; // autocommit +export const selectToggleAutocommitState = ( + state: GitRootState, + artifactDef: GitArtifactDef, +) => selectGitArtifact(state, artifactDef)?.apiResponses.toggleAutocommit; + +export const selectAutocommitDisableModalOpen = ( + state: GitRootState, + artifactDef: GitArtifactDef, +) => selectGitArtifact(state, artifactDef)?.ui.autocommitDisableModalOpen; + export const selectAutocommitEnabled = ( state: GitRootState, artifactDef: GitArtifactDef, ) => { - const gitMetadata = selectGitMetadata(state, artifactDef).value; + const gitMetadata = selectMetadataState(state, artifactDef).value; - return gitMetadata?.autoCommitConfig?.enabled; + return gitMetadata?.autoCommitConfig?.enabled ?? false; }; export const selectAutocommitPolling = ( @@ -131,7 +157,7 @@ export const selectAutocommitPolling = ( export const selectDefaultBranch = ( state: GitRootState, artifactDef: GitArtifactDef, -) => selectGitMetadata(state, artifactDef)?.value?.defaultBranchName ?? null; +) => selectMetadataState(state, artifactDef)?.value?.defaultBranchName ?? null; // protected branches export const selectFetchProtectedBranchesState = ( diff --git a/app/client/src/git/store/types.ts b/app/client/src/git/store/types.ts index 803f40d4f85b..9f931992f5d3 100644 --- a/app/client/src/git/store/types.ts +++ b/app/client/src/git/store/types.ts @@ -11,7 +11,7 @@ import type { FetchBranchesResponseData } from "../requests/fetchBranchesRequest import type { FetchLocalProfileResponseData } from "../requests/fetchLocalProfileRequest.types"; import type { FetchStatusResponseData } from "git/requests/fetchStatusRequest.types"; import type { FetchMergeStatusResponseData } from "git/requests/fetchMergeStatusRequest.types"; -import type { FetchGitMetadataResponseData } from "git/requests/fetchGitMetadataRequest.types"; +import type { FetchMetadataResponseData } from "git/requests/fetchMetadataRequest.types"; import type { FetchProtectedBranchesResponseData } from "git/requests/fetchProtectedBranchesRequest.types"; import type { ApiResponseError } from "api/types"; import type { @@ -38,7 +38,7 @@ export interface GitAsyncStateWithoutValue { } export interface GitSingleArtifactAPIResponsesReduxState extends GitSingleArtifactAPIResponsesReduxStateEE { - metadata: GitAsyncState; + metadata: GitAsyncState; connect: GitAsyncStateWithoutValue; status: GitAsyncState; commit: GitAsyncStateWithoutValue; @@ -68,6 +68,8 @@ export interface GitSingleArtifactUIReduxState open: boolean; step: keyof typeof GitConnectStep; }; + disconnectBaseArtifactId: string | null; + disconnectArtifactName: string | null; importModal: { open: boolean; step: keyof typeof GitImportStep; @@ -77,14 +79,14 @@ export interface GitSingleArtifactUIReduxState }; opsModalOpen: boolean; opsModalTab: keyof typeof GitOpsTab; - conflictErrorModalOpen: boolean; settingsModalOpen: boolean; settingsModalTab: keyof typeof GitSettingsTab; + autocommitDisableModalOpen: boolean; + autocommitPolling: boolean; + conflictErrorModalOpen: boolean; repoLimitErrorModal: { open: boolean; }; - autocommitPolling: boolean; - autocommitModalOpen: boolean; } export interface GitSingleArtifactReduxState { ui: GitSingleArtifactUIReduxState; From a7f5832333ae92d23f28e42676fa99aa76b112ed Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Sat, 14 Dec 2024 09:34:00 +0800 Subject: [PATCH 059/143] chore: added disconnect modal --- ....test.tsx => DisconnectModalView.test.tsx} | 33 ++-- .../DisconnectModal/DisconnectModalView.tsx | 151 ++++++++++++++++ .../git/components/DisconnectModal/index.tsx | 163 +++--------------- app/client/src/git/hooks/useDisconnect.ts | 2 +- 4 files changed, 191 insertions(+), 158 deletions(-) rename app/client/src/git/components/DisconnectModal/{index.test.tsx => DisconnectModalView.test.tsx} (86%) create mode 100644 app/client/src/git/components/DisconnectModal/DisconnectModalView.tsx diff --git a/app/client/src/git/components/DisconnectModal/index.test.tsx b/app/client/src/git/components/DisconnectModal/DisconnectModalView.test.tsx similarity index 86% rename from app/client/src/git/components/DisconnectModal/index.test.tsx rename to app/client/src/git/components/DisconnectModal/DisconnectModalView.test.tsx index 70f6fb14ea26..9f86a461c329 100644 --- a/app/client/src/git/components/DisconnectModal/index.test.tsx +++ b/app/client/src/git/components/DisconnectModal/DisconnectModalView.test.tsx @@ -2,7 +2,7 @@ import React from "react"; import { render, screen, fireEvent } from "@testing-library/react"; import "@testing-library/jest-dom"; import AnalyticsUtil from "ee/utils/AnalyticsUtil"; -import DisconnectModal from "."; +import DisconnectModal from "./DisconnectModalView"; jest.mock("ee/utils/AnalyticsUtil", () => ({ logEvent: jest.fn(), @@ -10,14 +10,12 @@ jest.mock("ee/utils/AnalyticsUtil", () => ({ describe("DisconnectModal", () => { const defaultProps = { - isModalOpen: true, - disconnectingApp: { - id: "app123", - name: "TestApp", - }, - closeModal: jest.fn(), - onBackClick: jest.fn(), - onDisconnect: jest.fn(), + closeDisconnectModal: jest.fn(), + disconnect: jest.fn(), + disconnectArtifactName: "TestApp", + isDisconnectLoading: false, + isDisconnectModalOpen: true, + toggleSettingsModal: jest.fn(), }; afterEach(() => { @@ -30,7 +28,7 @@ describe("DisconnectModal", () => { }); it("should not render the modal when isModalOpen is false", () => { - render(); + render(); expect( screen.queryByTestId("t--disconnect-git-modal"), ).not.toBeInTheDocument(); @@ -56,7 +54,7 @@ describe("DisconnectModal", () => { expect(input).toHaveValue("TestApp"); }); - it("should enable Revoke button when appName matches disconnectingApp.name", () => { + it("should enable Revoke button when appName matches disconnectAppName", () => { render(); const input = screen.getByLabelText("Application name"); const revokeButton = document.getElementsByClassName( @@ -69,7 +67,7 @@ describe("DisconnectModal", () => { expect(revokeButton).toBeEnabled(); }); - it("should disable Revoke button when appName does not match disconnectingApp.name", () => { + it("should disable Revoke button when appName does not match disconnectAppName", () => { render(); const input = screen.getByLabelText("Application name"); const revokeButton = document.getElementsByClassName( @@ -87,7 +85,8 @@ describe("DisconnectModal", () => { )[0]; fireEvent.click(goBackButton); - expect(defaultProps.onBackClick).toHaveBeenCalledTimes(1); + expect(defaultProps.closeDisconnectModal).toHaveBeenCalledTimes(1); + expect(defaultProps.toggleSettingsModal).toHaveBeenCalledTimes(1); }); it("should call onDisconnect when Revoke button is clicked", () => { @@ -100,7 +99,7 @@ describe("DisconnectModal", () => { fireEvent.change(input, { target: { value: "TestApp" } }); fireEvent.click(revokeButton); - expect(defaultProps.onDisconnect).toHaveBeenCalledTimes(1); + expect(defaultProps.disconnect).toHaveBeenCalledTimes(1); }); it("should disable Revoke button when isRevoking is true", () => { @@ -115,9 +114,9 @@ describe("DisconnectModal", () => { fireEvent.click(revokeButton); // Rerender to reflect state change - rerender(); + rerender(); - expect(defaultProps.onDisconnect).toHaveBeenCalledTimes(1); + expect(defaultProps.disconnect).toHaveBeenCalledTimes(1); expect(revokeButton).toBeDisabled(); }); @@ -160,6 +159,6 @@ describe("DisconnectModal", () => { )[0]; fireEvent.click(revokeButton); - expect(defaultProps.onDisconnect).not.toHaveBeenCalled(); + expect(defaultProps.disconnect).not.toHaveBeenCalled(); }); }); diff --git a/app/client/src/git/components/DisconnectModal/DisconnectModalView.tsx b/app/client/src/git/components/DisconnectModal/DisconnectModalView.tsx new file mode 100644 index 000000000000..be4cd975f3bf --- /dev/null +++ b/app/client/src/git/components/DisconnectModal/DisconnectModalView.tsx @@ -0,0 +1,151 @@ +import React, { useCallback, useState } from "react"; +import { + Button, + Callout, + Flex, + Input, + Modal, + ModalBody, + ModalContent, + ModalFooter, + ModalHeader, + Text, +} from "@appsmith/ads"; +import { + APPLICATION_NAME, + createMessage, + GIT_REVOKE_ACCESS, + GIT_TYPE_REPO_NAME_FOR_REVOKING_ACCESS, + GO_BACK, + NONE_REVERSIBLE_MESSAGE, + REVOKE, +} from "ee/constants/messages"; +import AnalyticsUtil from "ee/utils/AnalyticsUtil"; +import styled from "styled-components"; +import noop from "lodash/noop"; +import { GitSettingsTab } from "git/constants/enums"; + +const DOCS_URL = + "https://docs.appsmith.com/advanced-concepts/version-control-with-git/disconnect-the-git-repository"; +const DOCS_LINK_PROPS = [ + { + children: "Learn more", + to: DOCS_URL, + className: "t--disconnect-learn-more", + }, +]; +const MODAL_WIDTH = 640; + +const StyledModalContent = styled(ModalContent)` + width: ${MODAL_WIDTH}px; +`; + +interface DisconnectModalProps { + closeDisconnectModal: () => void; + disconnect: () => void; + disconnectArtifactName: string | null; + isDisconnectLoading: boolean; + isDisconnectModalOpen: boolean; + toggleSettingsModal: ( + open: boolean, + tab?: keyof typeof GitSettingsTab, + ) => void; +} + +function DisconnectModalView({ + closeDisconnectModal = noop, + disconnect = noop, + disconnectArtifactName = null, + isDisconnectLoading = false, + isDisconnectModalOpen = false, + toggleSettingsModal = noop, +}: DisconnectModalProps) { + const [artifactName, setArtifactName] = useState(""); + + const handleClickOnBack = useCallback(() => { + closeDisconnectModal(); + toggleSettingsModal(true, GitSettingsTab.General); + }, [closeDisconnectModal, toggleSettingsModal]); + + const handleClickOnDisconnect = useCallback(() => { + disconnect(); + }, [disconnect]); + + const shouldDisableRevokeButton = + artifactName !== disconnectArtifactName || isDisconnectLoading; + + const onModalOpenValueChange = useCallback( + (open: boolean) => { + if (!open) { + closeDisconnectModal(); + } + }, + [closeDisconnectModal], + ); + + const inputOnBlur = useCallback( + (event: React.FocusEvent) => { + AnalyticsUtil.logEvent("GS_MATCHING_REPO_NAME_ON_GIT_DISCONNECT_MODAL", { + value: "value" in event.target ? event.target.value : "", + expecting: disconnectArtifactName, + }); + }, + [disconnectArtifactName], + ); + + const inputOnChange = useCallback((value: string) => { + setArtifactName(value); + }, []); + + return ( + + + + {createMessage(GIT_REVOKE_ACCESS, disconnectArtifactName)} + + + + + {createMessage( + GIT_TYPE_REPO_NAME_FOR_REVOKING_ACCESS, + disconnectArtifactName, + )} + + + + {createMessage(NONE_REVERSIBLE_MESSAGE)} + + + + + + + + + + ); +} + +export default DisconnectModalView; diff --git a/app/client/src/git/components/DisconnectModal/index.tsx b/app/client/src/git/components/DisconnectModal/index.tsx index b18750a38422..b96c401c34e7 100644 --- a/app/client/src/git/components/DisconnectModal/index.tsx +++ b/app/client/src/git/components/DisconnectModal/index.tsx @@ -1,145 +1,28 @@ -import React, { useCallback, useState } from "react"; -import { - Button, - Callout, - Flex, - Input, - Modal, - ModalBody, - ModalContent, - ModalFooter, - ModalHeader, - Text, -} from "@appsmith/ads"; -import { - APPLICATION_NAME, - createMessage, - GIT_REVOKE_ACCESS, - GIT_TYPE_REPO_NAME_FOR_REVOKING_ACCESS, - GO_BACK, - NONE_REVERSIBLE_MESSAGE, - REVOKE, -} from "ee/constants/messages"; -import AnalyticsUtil from "ee/utils/AnalyticsUtil"; -import styled from "styled-components"; - -const DOCS_URL = - "https://docs.appsmith.com/advanced-concepts/version-control-with-git/disconnect-the-git-repository"; -const DOCS_LINK_PROPS = [ - { - children: "Learn more", - to: DOCS_URL, - className: "t--disconnect-learn-more", - }, -]; -const MODAL_WIDTH = 640; - -interface DisconnectModalProps { - isModalOpen: boolean; - disconnectingApp: { - id: string; - name: string; - }; - closeModal: () => void; - onBackClick: () => void; - onDisconnect: () => void; -} - -const StyledModalContent = styled(ModalContent)` - width: ${MODAL_WIDTH}px; -`; - -function DisconnectModal({ - closeModal, - disconnectingApp, - isModalOpen, - onBackClick, - onDisconnect, -}: DisconnectModalProps) { - const [appName, setAppName] = useState(""); - const [isRevoking, setIsRevoking] = useState(false); - - const onDisconnectGit = useCallback(() => { - setIsRevoking(true); - onDisconnect(); - }, [onDisconnect]); - - const shouldDisableRevokeButton = - disconnectingApp.id === "" || - appName !== disconnectingApp.name || - isRevoking; - - const onModalOpenValueChange = useCallback( - (open: boolean) => { - if (!open) { - closeModal(); - } - }, - [closeModal], - ); - - const inputOnBlur = useCallback( - (event: React.FocusEvent) => { - AnalyticsUtil.logEvent("GS_MATCHING_REPO_NAME_ON_GIT_DISCONNECT_MODAL", { - value: "value" in event.target ? event.target.value : "", - expecting: disconnectingApp.name, - }); - }, - [disconnectingApp.name], - ); - - const inputOnChange = useCallback((value: string) => { - setAppName(value); - }, []); +import useDisconnect from "git/hooks/useDisconnect"; +import useSettings from "git/hooks/useSettings"; +import React from "react"; +import DisconnectModalView from "./DisconnectModalView"; + +function DisconnectModal() { + const { + closeDisconnectModal, + disconnect, + disconnectArtifactName, + isDisconnectLoading, + isDisconnectModalOpen, + } = useDisconnect(); + + const { toggleSettingsModal } = useSettings(); return ( - - - - {createMessage(GIT_REVOKE_ACCESS, disconnectingApp.name)} - - - - - {createMessage( - GIT_TYPE_REPO_NAME_FOR_REVOKING_ACCESS, - disconnectingApp.name, - )} - - - - {createMessage(NONE_REVERSIBLE_MESSAGE)} - - - - - - - - - + ); } diff --git a/app/client/src/git/hooks/useDisconnect.ts b/app/client/src/git/hooks/useDisconnect.ts index b320dfff0824..74eecb11219c 100644 --- a/app/client/src/git/hooks/useDisconnect.ts +++ b/app/client/src/git/hooks/useDisconnect.ts @@ -11,7 +11,7 @@ import { useDispatch, useSelector } from "react-redux"; export default function useDisconnect() { const { artifact, artifactDef } = useGitContext(); - const artifactName = artifact?.name ?? "application"; + const artifactName = artifact?.name ?? ""; const dispatch = useDispatch(); From 7b48aa288c04ef4779be18be152386f12ba8a4f0 Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Sat, 14 Dec 2024 09:53:58 +0800 Subject: [PATCH 060/143] chore: adding disable autocommit modal --- .../DisableAutocommitModalView.tsx | 85 +++++++++++++++++++ .../DisableAutocommitModal/index.tsx | 23 +++++ .../DisconnectModal/DisconnectModalView.tsx | 2 +- app/client/src/git/components/GitModals.tsx | 4 + 4 files changed, 113 insertions(+), 1 deletion(-) create mode 100644 app/client/src/git/components/DisableAutocommitModal/DisableAutocommitModalView.tsx create mode 100644 app/client/src/git/components/DisableAutocommitModal/index.tsx diff --git a/app/client/src/git/components/DisableAutocommitModal/DisableAutocommitModalView.tsx b/app/client/src/git/components/DisableAutocommitModal/DisableAutocommitModalView.tsx new file mode 100644 index 000000000000..cfa814b27792 --- /dev/null +++ b/app/client/src/git/components/DisableAutocommitModal/DisableAutocommitModalView.tsx @@ -0,0 +1,85 @@ +import { + AUTOCOMMIT_CONFIRM_DISABLE_MESSAGE, + AUTOCOMMIT_DISABLE, + createMessage, +} from "ee/constants/messages"; +import { + Button, + Callout, + Modal, + ModalBody, + ModalContent, + ModalFooter, + ModalHeader, + Text, +} from "@appsmith/ads"; +import React, { useCallback } from "react"; +import AnalyticsUtil from "ee/utils/AnalyticsUtil"; +import noop from "lodash/noop"; +import styled from "styled-components"; + +const StyledModalContent = styled(ModalContent)` + width: 640px; +`; + +const StyledModalHeader = styled(ModalHeader)` + margin: 0; +`; + +interface DisableAutocommitModalViewProps { + isAutocommitDisableModalOpen?: boolean; + isToggleAutocommitLoading?: boolean; + toggleAutocommit?: () => void; + toggleAutocommitDisableModal?: (open: boolean) => void; +} + +function DisableAutocommitModalView({ + isAutocommitDisableModalOpen = false, + isToggleAutocommitLoading = false, + toggleAutocommit = noop, + toggleAutocommitDisableModal = noop, +}: DisableAutocommitModalViewProps) { + const handleDisableAutocommit = useCallback(() => { + toggleAutocommit(); + AnalyticsUtil.logEvent("GS_AUTO_COMMIT_DISABLED"); + toggleAutocommitDisableModal(false); + }, [toggleAutocommit, toggleAutocommitDisableModal]); + + const handleModalOpenChange = useCallback( + (open: boolean) => { + if (!open) toggleAutocommitDisableModal(false); + }, + [toggleAutocommitDisableModal], + ); + + return ( + + + + {createMessage(AUTOCOMMIT_DISABLE)} + + + + {createMessage(AUTOCOMMIT_CONFIRM_DISABLE_MESSAGE)} + + + + + + + + ); +} + +export default DisableAutocommitModalView; diff --git a/app/client/src/git/components/DisableAutocommitModal/index.tsx b/app/client/src/git/components/DisableAutocommitModal/index.tsx new file mode 100644 index 000000000000..520575f6b5c5 --- /dev/null +++ b/app/client/src/git/components/DisableAutocommitModal/index.tsx @@ -0,0 +1,23 @@ +import React from "react"; +import DisableAutocommitModalView from "./DisableAutocommitModalView"; +import useAutocommit from "git/hooks/useAutocommit"; + +function DisableAutocommitModal() { + const { + isAutocommitDisableModalOpen, + isToggleAutocommitLoading, + toggleAutocommit, + toggleAutocommitDisableModal, + } = useAutocommit(); + + return ( + + ); +} + +export default DisableAutocommitModal; diff --git a/app/client/src/git/components/DisconnectModal/DisconnectModalView.tsx b/app/client/src/git/components/DisconnectModal/DisconnectModalView.tsx index be4cd975f3bf..8cfb010f5675 100644 --- a/app/client/src/git/components/DisconnectModal/DisconnectModalView.tsx +++ b/app/client/src/git/components/DisconnectModal/DisconnectModalView.tsx @@ -104,7 +104,7 @@ function DisconnectModalView({ {createMessage(GIT_REVOKE_ACCESS, disconnectArtifactName)} - + {createMessage( GIT_TYPE_REPO_NAME_FOR_REVOKING_ACCESS, diff --git a/app/client/src/git/components/GitModals.tsx b/app/client/src/git/components/GitModals.tsx index 6dbdc9ec00d8..ddfe4cbedf7c 100644 --- a/app/client/src/git/components/GitModals.tsx +++ b/app/client/src/git/components/GitModals.tsx @@ -2,12 +2,16 @@ import React from "react"; import ConflictErrorModal from "./ConflictErrorModal"; import SettingsModal from "./SettingsModal"; import OpsModal from "./OpsModal"; +import DisconnectModal from "./DisconnectModal"; +import DisableAutocommitModal from "./DisableAutocommitModal"; export default function GitModals() { return ( <> + + ); From 57aa219848912eefe5c235cd70681d4d73ad3604 Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Sat, 14 Dec 2024 17:17:32 +0800 Subject: [PATCH 061/143] chore: adding disconnect and toggle autocommit saga --- .../DisconnectModal/DisconnectModalView.tsx | 1 + .../git/requests/disconnectRequest.types.ts | 6 +- .../requests/toggleAutocommitRequest.types.ts | 7 ++- app/client/src/git/sagas/disconnectSaga.ts | 61 +++++++++++++++++++ app/client/src/git/sagas/index.ts | 4 ++ .../src/git/sagas/toggleAutocommitSaga.ts | 37 +++++++++++ 6 files changed, 114 insertions(+), 2 deletions(-) create mode 100644 app/client/src/git/sagas/disconnectSaga.ts create mode 100644 app/client/src/git/sagas/toggleAutocommitSaga.ts diff --git a/app/client/src/git/components/DisconnectModal/DisconnectModalView.tsx b/app/client/src/git/components/DisconnectModal/DisconnectModalView.tsx index 8cfb010f5675..e01086623dcc 100644 --- a/app/client/src/git/components/DisconnectModal/DisconnectModalView.tsx +++ b/app/client/src/git/components/DisconnectModal/DisconnectModalView.tsx @@ -136,6 +136,7 @@ function DisconnectModalView({ + )} + {possibleSteps.includes(activeStep) && + currentIndex > 0 && + !isLoading && ( + + )} + + + ); +} + +export default ConnectModalView; diff --git a/app/client/src/git/components/ConnectModal/GenerateSSH.tsx b/app/client/src/git/components/ConnectModal/GenerateSSH.tsx index c598cce17dad..fbf9558b41aa 100644 --- a/app/client/src/git/components/ConnectModal/GenerateSSH.tsx +++ b/app/client/src/git/components/ConnectModal/GenerateSSH.tsx @@ -32,7 +32,7 @@ import { import { GIT_DEMO_GIF } from "./constants"; import { isValidGitRemoteUrl } from "../utils"; import type { GitProvider } from "./ChooseGitProvider"; -import type { ApiResponse } from "api/ApiResponses"; +import type { GitApiError } from "git/store/types"; interface GenerateSSHState { gitProvider?: GitProvider; @@ -41,14 +41,14 @@ interface GenerateSSHState { interface GenerateSSHProps { onChange: (args: Partial) => void; value: Partial; - errorData?: ApiResponse; + connectError: GitApiError | null; } const CONNECTING_TO_GIT_DOCS_URL = "https://docs.appsmith.com/advanced-concepts/version-control-with-git/connecting-to-git-repository"; function GenerateSSH({ - errorData, + connectError, onChange = noop, value = {}, }: GenerateSSHProps) { @@ -69,7 +69,7 @@ function GenerateSSH({ return ( <> {/* hardcoding messages because server doesn't support feature flag. Will change this later */} - {errorData && errorData?.responseMeta?.error?.code === "AE-GIT-4033" && ( + {connectError && connectError?.code === "AE-GIT-4033" && ( {createMessage(ERROR_REPO_NOT_EMPTY_TITLE)} diff --git a/app/client/src/git/components/ConnectModal/index.tsx b/app/client/src/git/components/ConnectModal/index.tsx index f7c8d097213d..4db6f03adc83 100644 --- a/app/client/src/git/components/ConnectModal/index.tsx +++ b/app/client/src/git/components/ConnectModal/index.tsx @@ -1,338 +1,49 @@ -import React, { useCallback, useState } from "react"; -import styled from "styled-components"; +import React from "react"; +import ConnectModalView from "./ConnectModalView"; +import { useGitContext } from "../GitContextProvider"; +import useConnect from "git/hooks/useConnect"; -import AddDeployKey, { type AddDeployKeyProps } from "./AddDeployKey"; -import AnalyticsUtil from "ee/utils/AnalyticsUtil"; -import ChooseGitProvider from "./ChooseGitProvider"; -import GenerateSSH from "./GenerateSSH"; -import Steps from "./Steps"; -import Statusbar from "../Statusbar"; -import { Button, ModalBody, ModalFooter } from "@appsmith/ads"; -import { GIT_CONNECT_STEPS } from "./constants"; -import type { GitProvider } from "./ChooseGitProvider"; -import { - ADD_DEPLOY_KEY_STEP, - CHOOSE_A_GIT_PROVIDER_STEP, - CONFIGURE_GIT, - CONNECT_GIT_TEXT, - GENERATE_SSH_KEY_STEP, - GIT_CONNECT_WAITING, - GIT_IMPORT_WAITING, - IMPORT_APP_CTA, - PREVIOUS_STEP, - createMessage, -} from "ee/constants/messages"; -import { isValidGitRemoteUrl } from "../utils"; -import type { ApiResponse } from "api/ApiResponses"; - -const OFFSET = 200; -const OUTER_PADDING = 32; -const FOOTER = 56; -const HEADER = 44; - -const StyledModalBody = styled(ModalBody)` - flex: 1; - overflow-y: initial; - display: flex; - flex-direction: column; - max-height: calc( - 100vh - ${OFFSET}px - ${OUTER_PADDING}px - ${FOOTER}px - ${HEADER}px - ); -`; - -const StyledModalFooter = styled(ModalFooter)` - justify-content: space-between; - flex-direction: ${(p) => (!p.loading ? "row-reverse" : "row")}; -`; - -const steps = [ - { - key: GIT_CONNECT_STEPS.CHOOSE_PROVIDER, - text: createMessage(CHOOSE_A_GIT_PROVIDER_STEP), - }, - { - key: GIT_CONNECT_STEPS.GENERATE_SSH_KEY, - text: createMessage(GENERATE_SSH_KEY_STEP), - }, - { - key: GIT_CONNECT_STEPS.ADD_DEPLOY_KEY, - text: createMessage(ADD_DEPLOY_KEY_STEP), - }, -]; - -const possibleSteps = steps.map((s) => s.key); - -interface StyledModalFooterProps { - loading?: boolean; -} - -interface FormDataState { - gitProvider?: GitProvider; - gitEmptyRepoExists?: string; - gitExistingRepoExists?: boolean; - remoteUrl?: string; - isAddedDeployKey?: boolean; - sshKeyType?: "RSA" | "ECDSA"; -} - -interface GitProfile { - authorName: string; - authorEmail: string; - useDefaultProfile?: boolean; -} - -interface ConnectOrImportPayload { - remoteUrl: string; - gitProfile: GitProfile; -} - -interface ConnectOrImportProps { - payload: ConnectOrImportPayload; - onErrorCallback: (error: Error, response: ApiResponse) => void; -} - -// Remove comments after integration interface ConnectModalProps { isImport?: boolean; - // It replaces const isImportingViaGit in GitConnectionV2/index.tsx - isImporting?: boolean; - // Replaces dispatch(importAppFromGit) - importFrom: (props: ConnectOrImportProps) => void; - // Replaces connectToGit from useGitConnect hook - connectTo: (props: ConnectOrImportProps) => void; - // Replaces isConnectingToGit - isConnectingTo?: boolean; - isConnecting: boolean; - artifactId: string; - artifactType: string; - // Replaces handleImport in original ChooseGitProvider.tsx - onImportFromCalloutLinkClick: () => void; - // Replaces hasCreateNewApplicationPermission = hasCreateNewAppPermission(workspace.userPermissions) - canCreateNewArtifact: boolean; - isModalOpen: boolean; - deployKeyDocUrl: AddDeployKeyProps["deployKeyDocUrl"]; - isFetchingSSHKeyPair: AddDeployKeyProps["isFetchingSSHKeyPair"]; - fetchSSHKeyPair: AddDeployKeyProps["fetchSSHKeyPair"]; - generateSSHKey: AddDeployKeyProps["generateSSHKey"]; - isGeneratingSSHKey: AddDeployKeyProps["isGeneratingSSHKey"]; - sshKeyPair: AddDeployKeyProps["sshKeyPair"]; } -function ConnectModal({ - artifactId, - artifactType, - canCreateNewArtifact, - connectTo, - deployKeyDocUrl, - fetchSSHKeyPair, - generateSSHKey, - importFrom, - isConnecting = false, - isFetchingSSHKeyPair, - isGeneratingSSHKey, - isImport = false, - isImporting = false, - isModalOpen, - onImportFromCalloutLinkClick, - sshKeyPair, -}: ConnectModalProps) { - const [errorData, setErrorData] = useState>(); - - const nextStepText = { - [GIT_CONNECT_STEPS.CHOOSE_PROVIDER]: createMessage(CONFIGURE_GIT), - [GIT_CONNECT_STEPS.GENERATE_SSH_KEY]: createMessage(GENERATE_SSH_KEY_STEP), - [GIT_CONNECT_STEPS.ADD_DEPLOY_KEY]: createMessage( - isImport ? IMPORT_APP_CTA : CONNECT_GIT_TEXT, - ), - }; - - const [formData, setFormData] = useState({ - gitProvider: undefined, - gitEmptyRepoExists: undefined, - gitExistingRepoExists: false, - remoteUrl: undefined, - isAddedDeployKey: false, - sshKeyType: "ECDSA", - }); - - const handleChange = (partialFormData: Partial) => { - setFormData((s) => ({ ...s, ...partialFormData })); - }; - - const [activeStep, setActiveStep] = useState( - GIT_CONNECT_STEPS.CHOOSE_PROVIDER, - ); - const currentIndex = steps.findIndex((s) => s.key === activeStep); - - const isDisabled = { - [GIT_CONNECT_STEPS.CHOOSE_PROVIDER]: !isImport - ? !formData.gitProvider || - !formData.gitEmptyRepoExists || - formData.gitEmptyRepoExists === "no" - : !formData.gitProvider || !formData.gitExistingRepoExists, - [GIT_CONNECT_STEPS.GENERATE_SSH_KEY]: - typeof formData?.remoteUrl !== "string" || - !isValidGitRemoteUrl(formData?.remoteUrl), - [GIT_CONNECT_STEPS.ADD_DEPLOY_KEY]: !formData.isAddedDeployKey, - }; - - const handlePreviousStep = useCallback(() => { - if (currentIndex > 0) { - setActiveStep(steps[currentIndex - 1].key); - } - }, [currentIndex]); - - const handleNextStep = useCallback(() => { - if (currentIndex < steps.length) { - switch (activeStep) { - case GIT_CONNECT_STEPS.CHOOSE_PROVIDER: { - setActiveStep(GIT_CONNECT_STEPS.GENERATE_SSH_KEY); - AnalyticsUtil.logEvent("GS_CONFIGURE_GIT"); - break; - } - case GIT_CONNECT_STEPS.GENERATE_SSH_KEY: { - setActiveStep(GIT_CONNECT_STEPS.ADD_DEPLOY_KEY); - AnalyticsUtil.logEvent("GS_GENERATE_KEY_BUTTON_CLICK", { - repoUrl: formData?.remoteUrl, - connectFlow: "v2", - }); - break; - } - case GIT_CONNECT_STEPS.ADD_DEPLOY_KEY: { - const gitProfile = { - authorName: "", - authorEmail: "", - useGlobalProfile: true, - }; - - if (formData.remoteUrl) { - if (!isImport) { - connectTo({ - payload: { - remoteUrl: formData.remoteUrl, - gitProfile, - }, - onErrorCallback: (error, response) => { - // AE-GIT-4033 is repo not empty error - if (response?.responseMeta?.error?.code === "AE-GIT-4033") { - setActiveStep(GIT_CONNECT_STEPS.GENERATE_SSH_KEY); - } - - setErrorData(response); - }, - }); - AnalyticsUtil.logEvent( - "GS_CONNECT_BUTTON_ON_GIT_SYNC_MODAL_CLICK", - { repoUrl: formData?.remoteUrl, connectFlow: "v2" }, - ); - } else { - importFrom({ - payload: { - remoteUrl: formData.remoteUrl, - gitProfile, - // isDefaultProfile: true, - }, - onErrorCallback(error, response) { - setErrorData(response); - }, - }); - } - } - - break; - } - } - } - }, [ - activeStep, - connectTo, - currentIndex, - formData.remoteUrl, - importFrom, - isImport, - ]); - - const stepProps = { - onChange: handleChange, - value: formData, - isImport, - errorData, - }; - - const loading = (!isImport && isConnecting) || (isImport && isImporting); +function ConnectModal({ isImport = false }: ConnectModalProps) { + const { artifactDef } = useGitContext(); + const { + connect, + connectError, + fetchSSHKey, + generateSSHKey, + gitImport, + isConnectLoading, + isConnectModalOpen, + isFetchSSHKeyLoading, + isGenerateSSHKeyLoading, + isGitImportLoading, + sshKey, + togglleConnectModal, + } = useConnect(); + + const { artifactType } = artifactDef; + const sshPublicKey = sshKey?.publicKey ?? null; return ( - <> - - {possibleSteps.includes(activeStep) && ( - - )} - {activeStep === GIT_CONNECT_STEPS.CHOOSE_PROVIDER && ( - - )} - {activeStep === GIT_CONNECT_STEPS.GENERATE_SSH_KEY && ( - - )} - {activeStep === GIT_CONNECT_STEPS.ADD_DEPLOY_KEY && ( - - )} - - - {loading && ( - - )} - {!loading && ( - - )} - {possibleSteps.includes(activeStep) && currentIndex > 0 && !loading && ( - - )} - - + ); } diff --git a/app/client/src/git/components/ConnectModal/types.ts b/app/client/src/git/components/ConnectModal/types.ts new file mode 100644 index 000000000000..024375064f35 --- /dev/null +++ b/app/client/src/git/components/ConnectModal/types.ts @@ -0,0 +1,10 @@ +import type { GitProvider } from "./ChooseGitProvider"; + +export interface ConnectFormDataState { + gitProvider?: GitProvider; + gitEmptyRepoExists?: string; + gitExistingRepoExists?: boolean; + remoteUrl?: string; + isAddedDeployKey?: boolean; + sshKeyType?: "RSA" | "ECDSA"; +} diff --git a/app/client/src/git/components/GitModals/GitModalsCE.tsx b/app/client/src/git/components/GitModals/GitModalsCE.tsx index 194bfe792097..976ae764cfcb 100644 --- a/app/client/src/git/components/GitModals/GitModalsCE.tsx +++ b/app/client/src/git/components/GitModals/GitModalsCE.tsx @@ -4,10 +4,12 @@ import SettingsModal from "../SettingsModal"; import OpsModal from "../OpsModal"; import DisconnectModal from "../DisconnectModal"; import DisableAutocommitModal from "../DisableAutocommitModal"; +import ConnectModal from "../ConnectModal"; function GitModalsCE() { return ( <> + diff --git a/app/client/src/git/components/ImportModal/index.tsx b/app/client/src/git/components/ImportModal/index.tsx new file mode 100644 index 000000000000..f55a468d702b --- /dev/null +++ b/app/client/src/git/components/ImportModal/index.tsx @@ -0,0 +1,8 @@ +import React from "react"; +import ConnectModal from "../ConnectModal"; + +function ImportModal() { + return ; +} + +export default ImportModal; diff --git a/app/client/src/git/components/index.tsx b/app/client/src/git/components/index.tsx index ec1d504d030a..a7c25c1cb90d 100644 --- a/app/client/src/git/components/index.tsx +++ b/app/client/src/git/components/index.tsx @@ -1,2 +1,3 @@ export { default as GitModals } from "./GitModals"; +export { default as GitImportModal } from "./ImportModal"; export { default as GitQuickActions } from "./QuickActions"; diff --git a/app/client/src/git/hooks/useConnect.ts b/app/client/src/git/hooks/useConnect.ts new file mode 100644 index 000000000000..ac38c4e881c1 --- /dev/null +++ b/app/client/src/git/hooks/useConnect.ts @@ -0,0 +1,87 @@ +import { useGitContext } from "git/components/GitContextProvider"; +import type { ConnectRequestParams } from "git/requests/connectRequest.types"; +import { gitArtifactActions } from "git/store/gitArtifactSlice"; +import { + selectConnectModalOpen, + selectConnectState, + selectFetchSSHKeysState, + selectGenerateSSHKeyState, + selectGitImportState, +} from "git/store/selectors/gitSingleArtifactSelectors"; +import type { GitRootState } from "git/store/types"; +import { useCallback } from "react"; +import { useDispatch } from "react-redux"; +import { useSelector } from "react-redux"; + +export default function useConnect() { + const { artifactDef } = useGitContext(); + + const dispatch = useDispatch(); + + const connectState = useSelector((state: GitRootState) => + selectConnectState(state, artifactDef), + ); + + const connect = useCallback( + (params: ConnectRequestParams) => { + dispatch(gitArtifactActions.connectInit({ ...artifactDef, ...params })); + }, + [artifactDef, dispatch], + ); + + const gitImportState = useSelector((state: GitRootState) => + selectGitImportState(state, artifactDef), + ); + + const gitImport = useCallback( + (params) => { + dispatch(gitArtifactActions.gitImportInit({ ...artifactDef, ...params })); + }, + [artifactDef, dispatch], + ); + + const fetchSSHKeyState = useSelector((state: GitRootState) => + selectFetchSSHKeysState(state, artifactDef), + ); + + const fetchSSHKey = useCallback(() => { + dispatch(gitArtifactActions.fetchSSHKeyInit(artifactDef)); + }, [artifactDef, dispatch]); + + const generateSSHKeyState = useSelector((state: GitRootState) => + selectGenerateSSHKeyState(state, artifactDef), + ); + + const generateSSHKey = useCallback(() => { + dispatch(gitArtifactActions.generateSSHKeyInit(artifactDef)); + }, [artifactDef, dispatch]); + + const isConnectModalOpen = useSelector((state: GitRootState) => + selectConnectModalOpen(state, artifactDef), + ); + + const togglleConnectModal = useCallback( + (open: boolean) => { + dispatch(gitArtifactActions.toggleConnectModal({ ...artifactDef, open })); + }, + [artifactDef, dispatch], + ); + + return { + isConnectLoading: connectState?.loading ?? false, + connectError: connectState?.error ?? null, + connect, + isGitImportLoading: gitImportState?.loading ?? false, + gitImportError: gitImportState?.error ?? null, + gitImport, + sshKey: fetchSSHKeyState?.value ?? null, + isFetchSSHKeyLoading: fetchSSHKeyState?.loading ?? false, + fetchSSHKeyError: fetchSSHKeyState?.error ?? null, + fetchSSHKey, + isGenerateSSHKeyLoading: generateSSHKeyState?.loading ?? false, + generateSSHKeyError: generateSSHKeyState?.error ?? null, + generateSSHKey, + isConnectModalOpen, + togglleConnectModal, + }; +} diff --git a/app/client/src/git/requests/fetchSSHKeyRequest.types.ts b/app/client/src/git/requests/fetchSSHKeyRequest.types.ts index 55b4f305b666..b507a15c8077 100644 --- a/app/client/src/git/requests/fetchSSHKeyRequest.types.ts +++ b/app/client/src/git/requests/fetchSSHKeyRequest.types.ts @@ -1,6 +1,10 @@ -export interface FetchSSHKeyResponse { +import type { ApiResponse } from "api/types"; + +export interface FetchSSHKeyResponseData { publicKey: string; docUrl: string; isRegeneratedKey: boolean; regeneratedKey: boolean; } + +export type FetchSSHKeyResponse = ApiResponse; diff --git a/app/client/src/git/requests/generateSSHKeyRequest.types.ts b/app/client/src/git/requests/generateSSHKeyRequest.types.ts index ced29ad6dbc0..3cd45cf965e9 100644 --- a/app/client/src/git/requests/generateSSHKeyRequest.types.ts +++ b/app/client/src/git/requests/generateSSHKeyRequest.types.ts @@ -1,11 +1,15 @@ +import type { ApiResponse } from "api/types"; + export interface GenerateSSHKeyRequestParams { keyType: string; isImporting: boolean; } -export interface GenerateSSHKeyResponse { +export interface GenerateSSHKeyResponseData { publicKey: string; docUrl: string; isRegeneratedKey: boolean; regeneratedKey: boolean; } + +export type GenerateSSHKeyResponse = ApiResponse; diff --git a/app/client/src/git/requests/importGitRequest.ts b/app/client/src/git/requests/gitImportRequest.ts similarity index 52% rename from app/client/src/git/requests/importGitRequest.ts rename to app/client/src/git/requests/gitImportRequest.ts index 522cd187ebe3..94ad9b5d95c9 100644 --- a/app/client/src/git/requests/importGitRequest.ts +++ b/app/client/src/git/requests/gitImportRequest.ts @@ -1,14 +1,14 @@ import Api from "api/Api"; import { GIT_BASE_URL } from "./constants"; import type { - ImportGitRequestParams, - ImportGitResponse, -} from "./importGitRequest.types"; + GitImportRequestParams, + GitImportResponse, +} from "./gitImportRequest.types"; import type { AxiosPromise } from "axios"; -export default async function importGitRequest( +export default async function gitImportRequest( workspaceId: string, - params: ImportGitRequestParams, -): AxiosPromise { + params: GitImportRequestParams, +): AxiosPromise { return Api.post(`${GIT_BASE_URL}/import/${workspaceId}`, params); } diff --git a/app/client/src/git/requests/importGitRequest.types.ts b/app/client/src/git/requests/gitImportRequest.types.ts similarity index 69% rename from app/client/src/git/requests/importGitRequest.types.ts rename to app/client/src/git/requests/gitImportRequest.types.ts index b0f3113d7a6e..9f76b379c9cc 100644 --- a/app/client/src/git/requests/importGitRequest.types.ts +++ b/app/client/src/git/requests/gitImportRequest.types.ts @@ -1,4 +1,6 @@ -export interface ImportGitRequestParams { +import type { ApiResponse } from "api/types"; + +export interface GitImportRequestParams { remoteUrl: string; gitProfile?: { authorName: string; @@ -7,7 +9,7 @@ export interface ImportGitRequestParams { }; } -export interface ImportGitResponse { +export interface GitImportResponseData { id: string; baseId: string; gitApplicationMetadata: { @@ -22,3 +24,5 @@ export interface ImportGitResponse { repoName: string; }; } + +export type GitImportResponse = ApiResponse; diff --git a/app/client/src/git/store/actions/fetchSSHKeyActions.ts b/app/client/src/git/store/actions/fetchSSHKeyActions.ts index b802160ce0af..0b76b70fe87c 100644 --- a/app/client/src/git/store/actions/fetchSSHKeyActions.ts +++ b/app/client/src/git/store/actions/fetchSSHKeyActions.ts @@ -1,9 +1,6 @@ -import type { - GitArtifactPayloadAction, - GitArtifactErrorPayloadAction, - GitSSHKey, -} from "../types"; +import type { GitAsyncErrorPayload, GitAsyncSuccessPayload } from "../types"; import { createSingleArtifactAction } from "../helpers/createSingleArtifactAction"; +import type { FetchSSHKeyResponseData } from "git/requests/fetchSSHKeyRequest.types"; export const fetchSSHKeyInitAction = createSingleArtifactAction((state) => { state.apiResponses.sshKey.loading = true; @@ -12,22 +9,22 @@ export const fetchSSHKeyInitAction = createSingleArtifactAction((state) => { return state; }); -export const fetchSSHKeySuccessAction = createSingleArtifactAction( - (state, action: GitArtifactPayloadAction<{ sshKey: GitSSHKey }>) => { - state.apiResponses.sshKey.loading = false; - state.apiResponses.sshKey.value = action.payload.sshKey; +export const fetchSSHKeySuccessAction = createSingleArtifactAction< + GitAsyncSuccessPayload +>((state, action) => { + state.apiResponses.sshKey.loading = false; + state.apiResponses.sshKey.error = null; + state.apiResponses.sshKey.value = action.payload.responseData; - return state; - }, -); + return state; +}); -export const fetchSSHKeyErrorAction = createSingleArtifactAction( - (state, action: GitArtifactErrorPayloadAction) => { +export const fetchSSHKeyErrorAction = + createSingleArtifactAction((state, action) => { const { error } = action.payload; state.apiResponses.sshKey.loading = false; state.apiResponses.sshKey.error = error; return state; - }, -); + }); diff --git a/app/client/src/git/store/actions/generateSSHKey.ts b/app/client/src/git/store/actions/generateSSHKey.ts deleted file mode 100644 index 52698c65a8e1..000000000000 --- a/app/client/src/git/store/actions/generateSSHKey.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { createSingleArtifactAction } from "../helpers/createSingleArtifactAction"; -import type { GitArtifactErrorPayloadAction } from "../types"; - -export const generateSSHKeyInitAction = createSingleArtifactAction((state) => { - state.apiResponses.generateSSHKey.loading = true; - state.apiResponses.generateSSHKey.error = null; - - return state; -}); - -export const generateSSHKeySuccessAction = createSingleArtifactAction( - (state) => { - state.apiResponses.generateSSHKey.loading = false; - - return state; - }, -); - -export const generateSSHKeyErrorAction = createSingleArtifactAction( - (state, action: GitArtifactErrorPayloadAction) => { - const { error } = action.payload; - - state.apiResponses.generateSSHKey.loading = false; - state.apiResponses.generateSSHKey.error = error; - - return state; - }, -); diff --git a/app/client/src/git/store/actions/generateSSHKeyActions.ts b/app/client/src/git/store/actions/generateSSHKeyActions.ts new file mode 100644 index 000000000000..bad6de1405c4 --- /dev/null +++ b/app/client/src/git/store/actions/generateSSHKeyActions.ts @@ -0,0 +1,30 @@ +import type { GenerateSSHKeyResponseData } from "git/requests/generateSSHKeyRequest.types"; +import { createSingleArtifactAction } from "../helpers/createSingleArtifactAction"; +import type { GitAsyncErrorPayload, GitAsyncSuccessPayload } from "../types"; + +export const generateSSHKeyInitAction = createSingleArtifactAction((state) => { + state.apiResponses.generateSSHKey.loading = true; + state.apiResponses.generateSSHKey.error = null; + + return state; +}); + +export const generateSSHKeySuccessAction = createSingleArtifactAction< + GitAsyncSuccessPayload +>((state, action) => { + state.apiResponses.generateSSHKey.loading = false; + state.apiResponses.generateSSHKey.error = null; + state.apiResponses.sshKey.value = action.payload.responseData; + + return state; +}); + +export const generateSSHKeyErrorAction = + createSingleArtifactAction((state, action) => { + const { error } = action.payload; + + state.apiResponses.generateSSHKey.loading = false; + state.apiResponses.generateSSHKey.error = error; + + return state; + }); diff --git a/app/client/src/git/store/actions/gitImportActions.ts b/app/client/src/git/store/actions/gitImportActions.ts new file mode 100644 index 000000000000..49411b55dd55 --- /dev/null +++ b/app/client/src/git/store/actions/gitImportActions.ts @@ -0,0 +1,25 @@ +import { createSingleArtifactAction } from "../helpers/createSingleArtifactAction"; +import type { GitAsyncErrorPayload } from "../types"; + +export const gitImportInitAction = createSingleArtifactAction((state) => { + state.apiResponses.gitImport.loading = true; + state.apiResponses.gitImport.error = null; + + return state; +}); + +export const gitImportSuccessAction = createSingleArtifactAction((state) => { + state.apiResponses.gitImport.loading = false; + + return state; +}); + +export const gitImportErrorAction = + createSingleArtifactAction((state, action) => { + const { error } = action.payload; + + state.apiResponses.gitImport.loading = false; + state.apiResponses.gitImport.error = error; + + return state; + }); diff --git a/app/client/src/git/store/gitArtifactSlice.ts b/app/client/src/git/store/gitArtifactSlice.ts index 8a8ffd686f83..bcc607ecca18 100644 --- a/app/client/src/git/store/gitArtifactSlice.ts +++ b/app/client/src/git/store/gitArtifactSlice.ts @@ -119,6 +119,21 @@ import { disconnectInitAction, disconnectSuccessAction, } from "./actions/disconnectActions"; +import { + gitImportErrorAction, + gitImportInitAction, + gitImportSuccessAction, +} from "./actions/gitImportActions"; +import { + fetchSSHKeyErrorAction, + fetchSSHKeyInitAction, + fetchSSHKeySuccessAction, +} from "./actions/fetchSSHKeyActions"; +import { + generateSSHKeyErrorAction, + generateSSHKeyInitAction, + generateSSHKeySuccessAction, +} from "./actions/generateSSHKeyActions"; const initialState: GitArtifactReduxState = {}; @@ -139,6 +154,15 @@ export const gitArtifactSlice = createSlice({ connectInit: connectInitAction, connectSuccess: connectSuccessAction, connectError: connectErrorAction, + gitImportInit: gitImportInitAction, + gitImportSuccess: gitImportSuccessAction, + gitImportError: gitImportErrorAction, + fetchSSHKeyInit: fetchSSHKeyInitAction, + fetchSSHKeySuccess: fetchSSHKeySuccessAction, + fetchSSHKeyError: fetchSSHKeyErrorAction, + generateSSHKeyInit: generateSSHKeyInitAction, + generateSSHKeySuccess: generateSSHKeySuccessAction, + generateSSHKeyError: generateSSHKeyErrorAction, disconnectInit: disconnectInitAction, disconnectSuccess: disconnectSuccessAction, disconnectError: disconnectErrorAction, diff --git a/app/client/src/git/store/helpers/gitSingleArtifactInitialState.ts b/app/client/src/git/store/helpers/gitSingleArtifactInitialState.ts index 13d0ec975cf4..8acf140bb2b0 100644 --- a/app/client/src/git/store/helpers/gitSingleArtifactInitialState.ts +++ b/app/client/src/git/store/helpers/gitSingleArtifactInitialState.ts @@ -3,7 +3,6 @@ import { gitSingleArtifactInitialUIStateEE, } from "ee/git/store/helpers/gitSingleArtifactInitialState"; import { - GitConnectStep, GitImportStep, GitOpsTab, GitSettingsTab, @@ -15,10 +14,7 @@ import type { } from "../types"; const gitSingleArtifactInitialUIState: GitSingleArtifactUIReduxState = { - connectModal: { - open: false, - step: GitConnectStep.Provider, - }, + connectModalOpen: false, disconnectBaseArtifactId: null, disconnectArtifactName: null, importModal: { @@ -53,6 +49,10 @@ const gitSingleArtifactInitialAPIResponses: GitSingleArtifactAPIResponsesReduxSt loading: false, error: null, }, + gitImport: { + loading: false, + error: null, + }, status: { value: null, loading: false, diff --git a/app/client/src/git/store/selectors/gitSingleArtifactSelectors.ts b/app/client/src/git/store/selectors/gitSingleArtifactSelectors.ts index a42338ee507c..5ee245f7b49e 100644 --- a/app/client/src/git/store/selectors/gitSingleArtifactSelectors.ts +++ b/app/client/src/git/store/selectors/gitSingleArtifactSelectors.ts @@ -27,6 +27,31 @@ export const selectGitConnected = ( ) => !!selectMetadataState(state, artifactDef)?.value; // CONNECT +export const selectConnectState = ( + state: GitRootState, + artifactDef: GitArtifactDef, +) => selectGitArtifact(state, artifactDef)?.apiResponses.connect; + +export const selectGitImportState = ( + state: GitRootState, + artifactDef: GitArtifactDef, +) => selectGitArtifact(state, artifactDef)?.apiResponses.gitImport; + +export const selectFetchSSHKeysState = ( + state: GitRootState, + artifactDef: GitArtifactDef, +) => selectGitArtifact(state, artifactDef)?.apiResponses.sshKey; + +export const selectGenerateSSHKeyState = ( + state: GitRootState, + artifactDef: GitArtifactDef, +) => selectGitArtifact(state, artifactDef)?.apiResponses.generateSSHKey; + +export const selectConnectModalOpen = ( + state: GitRootState, + artifactDef: GitArtifactDef, +) => selectGitArtifact(state, artifactDef)?.ui.connectModalOpen; + export const selectDisconnectState = ( state: GitRootState, artifactDef: GitArtifactDef, diff --git a/app/client/src/git/store/types.ts b/app/client/src/git/store/types.ts index 9f931992f5d3..c9957a965444 100644 --- a/app/client/src/git/store/types.ts +++ b/app/client/src/git/store/types.ts @@ -1,7 +1,6 @@ import type { PayloadAction } from "@reduxjs/toolkit"; import type { GitArtifactType, - GitConnectStep, GitImportStep, GitOpsTab, GitSettingsTab, @@ -18,8 +17,7 @@ import type { GitSingleArtifactAPIResponsesReduxStateEE, GitSingleArtifactUIReduxStateEE, } from "ee/git/store/types"; - -export type GitSSHKey = Record; +import type { FetchSSHKeyResponseData } from "git/requests/fetchSSHKeyRequest.types"; export interface GitApiError extends ApiResponseError { errorType?: string; @@ -40,6 +38,7 @@ export interface GitSingleArtifactAPIResponsesReduxState extends GitSingleArtifactAPIResponsesReduxStateEE { metadata: GitAsyncState; connect: GitAsyncStateWithoutValue; + gitImport: GitAsyncStateWithoutValue; status: GitAsyncState; commit: GitAsyncStateWithoutValue; pull: GitAsyncStateWithoutValue; @@ -58,16 +57,13 @@ export interface GitSingleArtifactAPIResponsesReduxState autocommitProgress: GitAsyncStateWithoutValue; toggleAutocommit: GitAsyncStateWithoutValue; triggerAutocommit: GitAsyncStateWithoutValue; - sshKey: GitAsyncState; + sshKey: GitAsyncState; generateSSHKey: GitAsyncStateWithoutValue; } export interface GitSingleArtifactUIReduxState extends GitSingleArtifactUIReduxStateEE { - connectModal: { - open: boolean; - step: keyof typeof GitConnectStep; - }; + connectModalOpen: boolean; disconnectBaseArtifactId: string | null; disconnectArtifactName: string | null; importModal: { From 34f7a0051d2370cfd112345c91514b4a99445340 Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Sun, 15 Dec 2024 23:19:44 +0800 Subject: [PATCH 066/143] chore: adding logic for connect modal --- .../AddDeployKey.test.tsx | 109 ++---- .../{ => ConnectInitialize}/AddDeployKey.tsx | 27 +- .../ChooseGitProvider.test.tsx | 0 .../ChooseGitProvider.tsx | 0 .../{ => ConnectInitialize}/CopyButton.tsx | 0 .../GenerateSSH.test.tsx | 31 +- .../{ => ConnectInitialize}/GenerateSSH.tsx | 2 +- .../{ => ConnectInitialize}/Steps.tsx | 0 .../{ => ConnectInitialize}/common.tsx | 0 .../{ => ConnectInitialize}/constants.ts | 0 .../index.test.tsx} | 110 +++--- .../ConnectModal/ConnectInitialize/index.tsx | 304 ++++++++++++++++ .../{ => ConnectInitialize}/types.ts | 0 .../ConnectModal/ConnectModalView.tsx | 330 ++++-------------- .../ConnectModal/ConnectSuccess/index.tsx | 178 ++++++++++ .../src/git/components/ConnectModal/index.tsx | 20 +- .../DefaultBranch/DefaultBranchCE.tsx | 4 +- .../GitContextProvider/hooks/useGitConnect.ts | 37 -- .../hooks/useGitContextValue.ts | 13 +- .../hooks/useGitMetadata.ts | 0 .../components/OpsModal/TabDeploy/index.tsx | 3 +- .../components/OpsModal/TabMerge/index.tsx | 7 +- .../components/ProtectedBranches/index.tsx | 4 +- .../src/git/components/QuickActions/index.tsx | 3 +- app/client/src/git/constants/enums.ts | 1 + .../useBranches.ts} | 67 +--- app/client/src/git/hooks/useConnect.ts | 27 +- .../src/git/requests/generateSSHKeyRequest.ts | 4 +- .../requests/generateSSHKeyRequest.types.ts | 2 +- app/client/src/git/sagas/connectSaga.ts | 14 +- app/client/src/git/sagas/fetchSSHKeySaga.ts | 37 ++ .../src/git/sagas/generateSSHKeySaga.ts | 60 ++++ app/client/src/git/sagas/index.ts | 6 + app/client/src/git/sagas/initGitSaga.ts | 2 +- .../git/store/actions/fetchSSHKeyActions.ts | 8 + .../store/actions/generateSSHKeyActions.ts | 26 +- app/client/src/git/store/actions/uiActions.ts | 2 +- app/client/src/git/store/gitArtifactSlice.ts | 4 + 38 files changed, 875 insertions(+), 567 deletions(-) rename app/client/src/git/components/ConnectModal/{ => ConnectInitialize}/AddDeployKey.test.tsx (70%) rename app/client/src/git/components/ConnectModal/{ => ConnectInitialize}/AddDeployKey.tsx (93%) rename app/client/src/git/components/ConnectModal/{ => ConnectInitialize}/ChooseGitProvider.test.tsx (100%) rename app/client/src/git/components/ConnectModal/{ => ConnectInitialize}/ChooseGitProvider.tsx (100%) rename app/client/src/git/components/ConnectModal/{ => ConnectInitialize}/CopyButton.tsx (100%) rename app/client/src/git/components/ConnectModal/{ => ConnectInitialize}/GenerateSSH.test.tsx (86%) rename app/client/src/git/components/ConnectModal/{ => ConnectInitialize}/GenerateSSH.tsx (98%) rename app/client/src/git/components/ConnectModal/{ => ConnectInitialize}/Steps.tsx (100%) rename app/client/src/git/components/ConnectModal/{ => ConnectInitialize}/common.tsx (100%) rename app/client/src/git/components/ConnectModal/{ => ConnectInitialize}/constants.ts (100%) rename app/client/src/git/components/ConnectModal/{ConnectModalView.test.tsx => ConnectInitialize/index.test.tsx} (68%) create mode 100644 app/client/src/git/components/ConnectModal/ConnectInitialize/index.tsx rename app/client/src/git/components/ConnectModal/{ => ConnectInitialize}/types.ts (100%) create mode 100644 app/client/src/git/components/ConnectModal/ConnectSuccess/index.tsx delete mode 100644 app/client/src/git/components/GitContextProvider/hooks/useGitConnect.ts delete mode 100644 app/client/src/git/components/GitContextProvider/hooks/useGitMetadata.ts rename app/client/src/git/{components/GitContextProvider/hooks/useGitBranches.ts => hooks/useBranches.ts} (57%) create mode 100644 app/client/src/git/sagas/fetchSSHKeySaga.ts create mode 100644 app/client/src/git/sagas/generateSSHKeySaga.ts diff --git a/app/client/src/git/components/ConnectModal/AddDeployKey.test.tsx b/app/client/src/git/components/ConnectModal/ConnectInitialize/AddDeployKey.test.tsx similarity index 70% rename from app/client/src/git/components/ConnectModal/AddDeployKey.test.tsx rename to app/client/src/git/components/ConnectModal/ConnectInitialize/AddDeployKey.test.tsx index 632c67334731..176dc5247887 100644 --- a/app/client/src/git/components/ConnectModal/AddDeployKey.test.tsx +++ b/app/client/src/git/components/ConnectModal/ConnectInitialize/AddDeployKey.test.tsx @@ -18,18 +18,19 @@ const DEFAULT_DOCS_URL = "https://docs.appsmith.com/advanced-concepts/version-control-with-git/connecting-to-git-repository"; const defaultProps: AddDeployKeyProps = { - isModalOpen: true, + connectError: null, + isLoading: false, onChange: jest.fn(), value: { gitProvider: "github", isAddedDeployKey: false, remoteUrl: "git@github.com:owner/repo.git", }, - fetchSSHKeyPair: jest.fn(), + fetchSSHKey: jest.fn(), generateSSHKey: jest.fn(), - isFetchingSSHKeyPair: false, - isGeneratingSSHKey: false, - sshKeyPair: "ecdsa-sha2-nistp256 AAAAE2VjZHNhAAAIBaj...", + isFetchSSHKeyLoading: false, + isGenerateSSHKeyLoading: false, + sshPublicKey: "ecdsa-sha2-nistp256 AAAAE2VjZHNhAAAIBaj...", }; describe("AddDeployKey Component", () => { @@ -44,25 +45,27 @@ describe("AddDeployKey Component", () => { ).toBeInTheDocument(); expect(screen.getByRole("combobox")).toBeInTheDocument(); // Should show ECDSA by default since sshKeyPair includes "ecdsa" - expect(screen.getByText(defaultProps.sshKeyPair)).toBeInTheDocument(); + expect( + screen.getByText(defaultProps.sshPublicKey as string), + ).toBeInTheDocument(); expect( screen.getByText("I've added the deploy key and gave it write access"), ).toBeInTheDocument(); }); - it("calls fetchSSHKeyPair if modal is open and not importing", () => { + it("calls fetchSSHKey if modal is open and not importing", () => { render(); - expect(defaultProps.fetchSSHKeyPair).toHaveBeenCalledTimes(1); + expect(defaultProps.fetchSSHKey).toHaveBeenCalledTimes(1); }); - it("does not call fetchSSHKeyPair if importing", () => { + it("does not call fetchSSHKey if importing", () => { render(); - expect(defaultProps.fetchSSHKeyPair).not.toHaveBeenCalled(); + expect(defaultProps.fetchSSHKey).not.toHaveBeenCalled(); }); it("shows dummy key loader if loading keys", () => { render( - , + , ); // The actual key text should not be displayed expect(screen.queryByText("ecdsa-sha2-nistp256")).not.toBeInTheDocument(); @@ -75,7 +78,7 @@ describe("AddDeployKey Component", () => { , ); @@ -85,46 +88,32 @@ describe("AddDeployKey Component", () => { fireEvent.click(rsaOption); await waitFor(() => { - expect(generateSSHKey).toHaveBeenCalledWith("RSA", expect.any(Object)); + expect(generateSSHKey).toHaveBeenCalledWith("RSA", false); }); }); it("displays a generic error when errorData is provided and error code is not AE-GIT-4032 or AE-GIT-4033", () => { // eslint-disable-next-line react-perf/jsx-no-new-object-as-prop - const errorData = { - data: {}, - responseMeta: { - success: false, - status: 503, - error: { - code: "GENERIC-ERROR", - errorType: "Some Error", - message: "Something went wrong", - }, - }, + const connectError = { + code: "GENERIC-ERROR", + errorType: "Some Error", + message: "Something went wrong", }; - render(); + render(); expect(screen.getByText("Some Error")).toBeInTheDocument(); expect(screen.getByText("Something went wrong")).toBeInTheDocument(); }); it("displays a misconfiguration error if error code is AE-GIT-4032", () => { // eslint-disable-next-line react-perf/jsx-no-new-object-as-prop - const errorData = { - data: {}, - responseMeta: { - success: false, - status: 503, - error: { - code: "AE-GIT-4032", - errorType: "SSH Key Error", - message: "SSH Key misconfiguration", - }, - }, + const connectError = { + code: "AE-GIT-4032", + errorType: "SSH Key Error", + message: "SSH Key misconfiguration", }; - render(); + render(); expect(screen.getByText("SSH key misconfiguration")).toBeInTheDocument(); expect( screen.getByText( @@ -154,7 +143,7 @@ describe("AddDeployKey Component", () => { }); it("hides copy button when connectLoading is true", () => { - render(); + render(); expect(screen.queryByTestId("t--copy-generic")).not.toBeInTheDocument(); }); @@ -172,6 +161,7 @@ describe("AddDeployKey Component", () => { render( , ); @@ -217,54 +207,25 @@ describe("AddDeployKey Component", () => { expect(docsLink).toHaveAttribute("href", DEFAULT_DOCS_URL); }); - it("uses custom documentation link if provided", () => { - render( - , - ); - const docsLink = screen.getByRole("link", { name: "Read Docs" }); - - expect(docsLink).toHaveAttribute("href", "https://custom-docs.com"); - }); - - it("does not generate SSH key if modal is closed", () => { - const generateSSHKey = jest.fn(); - - render( - , - ); - // Should not call generateSSHKey since modal is not open - expect(generateSSHKey).not.toHaveBeenCalled(); - }); - it("generates SSH key if none is present and conditions are met", async () => { - const fetchSSHKeyPair = jest.fn((props) => { - props.onSuccessCallback && props.onSuccessCallback(); - }); + const fetchSSHKey = jest.fn(); const generateSSHKey = jest.fn(); render( , ); - expect(fetchSSHKeyPair).toHaveBeenCalledTimes(1); + expect(fetchSSHKey).toHaveBeenCalledTimes(1); await waitFor(() => { - expect(generateSSHKey).toHaveBeenCalledWith("ECDSA", expect.any(Object)); + expect(generateSSHKey).toHaveBeenCalledWith("ECDSA", false); }); }); }); diff --git a/app/client/src/git/components/ConnectModal/AddDeployKey.tsx b/app/client/src/git/components/ConnectModal/ConnectInitialize/AddDeployKey.tsx similarity index 93% rename from app/client/src/git/components/ConnectModal/AddDeployKey.tsx rename to app/client/src/git/components/ConnectModal/ConnectInitialize/AddDeployKey.tsx index cc8f0f795519..75a4a7a50e86 100644 --- a/app/client/src/git/components/ConnectModal/AddDeployKey.tsx +++ b/app/client/src/git/components/ConnectModal/ConnectInitialize/AddDeployKey.tsx @@ -137,8 +137,7 @@ const DEPLOY_DOCS_URL = export interface AddDeployKeyProps { connectError: GitApiError | null; fetchSSHKey: () => void; - generateSSHKey: (keyType: string) => void; - isConnectModalOpen: boolean; + generateSSHKey: (keyType: string, isImport?: boolean) => void; isFetchSSHKeyLoading: boolean; isGenerateSSHKeyLoading: boolean; isImport?: boolean; @@ -152,7 +151,6 @@ function AddDeployKey({ connectError = null, fetchSSHKey = noop, generateSSHKey = noop, - isConnectModalOpen = false, isFetchSSHKeyLoading = false, isGenerateSSHKeyLoading = false, isImport = false, @@ -166,7 +164,7 @@ function AddDeployKey({ useEffect( function fetchKeyPairOnInitEffect() { - if (isConnectModalOpen && !isImport) { + if (!isImport) { if (!fetched) { fetchSSHKey(); setFetched(true); @@ -186,12 +184,12 @@ function AddDeployKey({ } } }, - [isImport, isConnectModalOpen, fetched, fetchSSHKey], + [isImport, fetched, fetchSSHKey], ); useEffect( function setSSHKeyTypeonInitEffect() { - if (isConnectModalOpen && fetched && !isFetchSSHKeyLoading) { + if (fetched && !isFetchSSHKeyLoading) { if (sshPublicKey && sshPublicKey.includes("rsa")) { setSshKeyType("RSA"); } else if ( @@ -205,23 +203,16 @@ function AddDeployKey({ } } }, - [ - isConnectModalOpen, - fetched, - sshPublicKey, - isFetchSSHKeyLoading, - value?.remoteUrl, - ], + [fetched, sshPublicKey, isFetchSSHKeyLoading, value?.remoteUrl], ); useEffect( function generateSSHOnInitEffect() { if ( - isConnectModalOpen && - ((sshKeyType && !sshPublicKey) || - (sshKeyType && !sshPublicKey?.includes(sshKeyType.toLowerCase()))) + (sshKeyType && !sshPublicKey) || + (sshKeyType && !sshPublicKey?.includes(sshKeyType.toLowerCase())) ) { - generateSSHKey(sshKeyType); + generateSSHKey(sshKeyType, isImport); // doesn't support callback anymore // generateSSHKey(sshKeyType, { // onSuccessCallback: () => { @@ -230,7 +221,7 @@ function AddDeployKey({ // }); } }, - [sshKeyType, sshPublicKey, isConnectModalOpen, generateSSHKey], + [sshKeyType, sshPublicKey, generateSSHKey, isImport], ); const repositorySettingsUrl = getRepositorySettingsUrl( diff --git a/app/client/src/git/components/ConnectModal/ChooseGitProvider.test.tsx b/app/client/src/git/components/ConnectModal/ConnectInitialize/ChooseGitProvider.test.tsx similarity index 100% rename from app/client/src/git/components/ConnectModal/ChooseGitProvider.test.tsx rename to app/client/src/git/components/ConnectModal/ConnectInitialize/ChooseGitProvider.test.tsx diff --git a/app/client/src/git/components/ConnectModal/ChooseGitProvider.tsx b/app/client/src/git/components/ConnectModal/ConnectInitialize/ChooseGitProvider.tsx similarity index 100% rename from app/client/src/git/components/ConnectModal/ChooseGitProvider.tsx rename to app/client/src/git/components/ConnectModal/ConnectInitialize/ChooseGitProvider.tsx diff --git a/app/client/src/git/components/ConnectModal/CopyButton.tsx b/app/client/src/git/components/ConnectModal/ConnectInitialize/CopyButton.tsx similarity index 100% rename from app/client/src/git/components/ConnectModal/CopyButton.tsx rename to app/client/src/git/components/ConnectModal/ConnectInitialize/CopyButton.tsx diff --git a/app/client/src/git/components/ConnectModal/GenerateSSH.test.tsx b/app/client/src/git/components/ConnectModal/ConnectInitialize/GenerateSSH.test.tsx similarity index 86% rename from app/client/src/git/components/ConnectModal/GenerateSSH.test.tsx rename to app/client/src/git/components/ConnectModal/ConnectInitialize/GenerateSSH.test.tsx index 36a0c0ab4a7f..d082ee44546d 100644 --- a/app/client/src/git/components/ConnectModal/GenerateSSH.test.tsx +++ b/app/client/src/git/components/ConnectModal/ConnectInitialize/GenerateSSH.test.tsx @@ -1,12 +1,12 @@ /* eslint-disable react-perf/jsx-no-new-object-as-prop */ import React from "react"; import { render, screen, fireEvent, waitFor } from "@testing-library/react"; -import { isValidGitRemoteUrl } from "../utils"; +import { isValidGitRemoteUrl } from "../../utils"; import GenerateSSH from "./GenerateSSH"; import type { GitProvider } from "./ChooseGitProvider"; import "@testing-library/jest-dom"; -jest.mock("../utils", () => ({ +jest.mock("../../utils", () => ({ isValidGitRemoteUrl: jest.fn(), })); @@ -16,6 +16,7 @@ const defaultProps = { gitProvider: "github" as GitProvider, remoteUrl: "", }, + connectError: null, }; describe("GenerateSSH Component", () => { @@ -33,18 +34,11 @@ describe("GenerateSSH Component", () => { it("renders an error callout when errorData has code 'AE-GIT-4033'", () => { const errorData = { - data: {}, - responseMeta: { - status: 503, - success: false, - error: { - message: "", - code: "AE-GIT-4033", - }, - }, + message: "", + code: "AE-GIT-4033", }; - render(); + render(); expect( screen.getByText("The repo you added isn't empty"), ).toBeInTheDocument(); @@ -57,18 +51,11 @@ describe("GenerateSSH Component", () => { it("does not render error callout for other error codes", () => { const errorData = { - data: {}, - responseMeta: { - status: 503, - success: false, - error: { - message: "", - code: "SOME_OTHER_ERROR", - }, - }, + message: "", + code: "SOME_OTHER_ERROR", }; - render(); + render(); expect( screen.queryByText("The repo you added isn't empty"), ).not.toBeInTheDocument(); diff --git a/app/client/src/git/components/ConnectModal/GenerateSSH.tsx b/app/client/src/git/components/ConnectModal/ConnectInitialize/GenerateSSH.tsx similarity index 98% rename from app/client/src/git/components/ConnectModal/GenerateSSH.tsx rename to app/client/src/git/components/ConnectModal/ConnectInitialize/GenerateSSH.tsx index fbf9558b41aa..5318b0bd8554 100644 --- a/app/client/src/git/components/ConnectModal/GenerateSSH.tsx +++ b/app/client/src/git/components/ConnectModal/ConnectInitialize/GenerateSSH.tsx @@ -30,7 +30,7 @@ import { createMessage, } from "ee/constants/messages"; import { GIT_DEMO_GIF } from "./constants"; -import { isValidGitRemoteUrl } from "../utils"; +import { isValidGitRemoteUrl } from "../../utils"; import type { GitProvider } from "./ChooseGitProvider"; import type { GitApiError } from "git/store/types"; diff --git a/app/client/src/git/components/ConnectModal/Steps.tsx b/app/client/src/git/components/ConnectModal/ConnectInitialize/Steps.tsx similarity index 100% rename from app/client/src/git/components/ConnectModal/Steps.tsx rename to app/client/src/git/components/ConnectModal/ConnectInitialize/Steps.tsx diff --git a/app/client/src/git/components/ConnectModal/common.tsx b/app/client/src/git/components/ConnectModal/ConnectInitialize/common.tsx similarity index 100% rename from app/client/src/git/components/ConnectModal/common.tsx rename to app/client/src/git/components/ConnectModal/ConnectInitialize/common.tsx diff --git a/app/client/src/git/components/ConnectModal/constants.ts b/app/client/src/git/components/ConnectModal/ConnectInitialize/constants.ts similarity index 100% rename from app/client/src/git/components/ConnectModal/constants.ts rename to app/client/src/git/components/ConnectModal/ConnectInitialize/constants.ts diff --git a/app/client/src/git/components/ConnectModal/ConnectModalView.test.tsx b/app/client/src/git/components/ConnectModal/ConnectInitialize/index.test.tsx similarity index 68% rename from app/client/src/git/components/ConnectModal/ConnectModalView.test.tsx rename to app/client/src/git/components/ConnectModal/ConnectInitialize/index.test.tsx index 9ec1f782bc92..5d0e84b660ce 100644 --- a/app/client/src/git/components/ConnectModal/ConnectModalView.test.tsx +++ b/app/client/src/git/components/ConnectModal/ConnectInitialize/index.test.tsx @@ -1,34 +1,37 @@ import React from "react"; import { render, screen, fireEvent, waitFor } from "@testing-library/react"; -import { isValidGitRemoteUrl } from "../utils"; -import ConnectModalView from "./ConnectModalView"; +import { isValidGitRemoteUrl } from "../../utils"; import "@testing-library/jest-dom"; +import ConnectInitialize from "."; jest.mock("ee/utils/AnalyticsUtil", () => ({ logEvent: jest.fn(), })); -jest.mock("../utils", () => ({ +jest.mock("../../utils", () => ({ isValidGitRemoteUrl: jest.fn(), })); +jest.mock("@appsmith/ads", () => ({ + ...jest.requireActual("@appsmith/ads"), + ModalHeader: ({ children }: { children: React.ReactNode }) => ( +
{children}
+ ), +})); + const defaultProps = { - artifactId: "artifact-123", - artifactType: "application", - canCreateNewArtifact: true, - connectTo: jest.fn(), - importFrom: jest.fn(), - isConnecting: false, - isImport: false, - isImporting: false, - onImportFromCalloutLinkClick: jest.fn(), - deployKeyDocUrl: "https://docs.example.com", - fetchSSHKeyPair: jest.fn(), + artifactType: "Application", + connect: jest.fn(), + connectError: null, + fetchSSHKey: jest.fn(), generateSSHKey: jest.fn(), - isFetchingSSHKeyPair: false, - isGeneratingSSHKey: false, - sshKeyPair: "ssh-rsa AAAAB3...", - isModalOpen: true, + gitImport: jest.fn(), + isConnectLoading: false, + isFetchSSHKeyLoading: false, + isGenerateSSHKeyLoading: false, + isGitImportLoading: false, + isImport: false, + sshPublicKey: "ssh-rsa AAAAB3...", }; function completeChooseProviderStep(isImport = false) { @@ -64,7 +67,7 @@ describe("ConnectModal Component", () => { }); it("renders the initial step (ChooseGitProvider)", () => { - render(); + render(); expect( screen.getByText("i. To begin with, choose your Git service provider"), ).toBeInTheDocument(); @@ -74,12 +77,12 @@ describe("ConnectModal Component", () => { }); it("disables the next button when form data is incomplete in ChooseGitProvider step", () => { - render(); + render(); expect(screen.getByTestId("t--git-connect-next-button")).toBeDisabled(); }); it("navigates to the next step (GenerateSSH) and validates SSH URL input", () => { - render(); + render(); completeChooseProviderStep(); @@ -103,7 +106,7 @@ describe("ConnectModal Component", () => { }); it("renders AddDeployKey step and validates state transitions", () => { - render(); + render(); completeChooseProviderStep(); completeGenerateSSHKeyStep(); @@ -113,58 +116,63 @@ describe("ConnectModal Component", () => { ).toBeInTheDocument(); }); - it("calls connectTo on completing AddDeployKey step in connect mode", async () => { - render(); + it("calls connect on completing AddDeployKey step in connect mode", async () => { + render(); completeChooseProviderStep(); completeGenerateSSHKeyStep(); completeAddDeployKeyStep(); await waitFor(() => { - expect(defaultProps.connectTo).toHaveBeenCalledWith( + expect(defaultProps.connect).toHaveBeenCalledWith( expect.objectContaining({ - payload: { - remoteUrl: "git@example.com:user/repo.git", - gitProfile: { - authorName: "", - authorEmail: "", - useGlobalProfile: true, - }, + remoteUrl: "git@example.com:user/repo.git", + gitProfile: { + authorName: "", + authorEmail: "", + useGlobalProfile: true, }, }), ); }); }); - it("calls importFrom on completing AddDeployKey step in import mode", async () => { - render(); + it("calls gitImport on completing AddDeployKey step in import mode", async () => { + render(); completeChooseProviderStep(true); completeGenerateSSHKeyStep(); completeAddDeployKeyStep(); await waitFor(() => { - expect(defaultProps.importFrom).toHaveBeenCalledWith( + expect(defaultProps.gitImport).toHaveBeenCalledWith( expect.objectContaining({ - payload: { - remoteUrl: "git@example.com:user/repo.git", - gitProfile: { - authorName: "", - authorEmail: "", - useGlobalProfile: true, - }, + remoteUrl: "git@example.com:user/repo.git", + gitProfile: { + authorName: "", + authorEmail: "", + useGlobalProfile: true, }, }), ); }); }); - it("shows an error callout when an error occurs during connectTo", async () => { - const mockConnectTo = jest.fn((props) => { - props.onErrorCallback(new Error("Error"), { - responseMeta: { error: { code: "AE-GIT-4033" } }, - }); + it("shows an error callout when an error occurs during connect", async () => { + const mockConnect = jest.fn(() => { + // eslint-disable-next-line react-perf/jsx-no-new-object-as-prop + const connectError = { + code: "AE-GIT-4033", + message: "", + }; + + rerender( + , + ); }); - render(); + const { rerender } = render( + , + ); + completeChooseProviderStep(); completeGenerateSSHKeyStep(); @@ -182,7 +190,7 @@ describe("ConnectModal Component", () => { }); it("renders the previous step when Previous button is clicked", () => { - render(); + render(); expect( screen.getByText("i. To begin with, choose your Git service provider"), ).toBeInTheDocument(); @@ -197,7 +205,7 @@ describe("ConnectModal Component", () => { }); it("disables next button when form data is invalid in any step", () => { - render(); + render(); const nextButton = screen.getByTestId("t--git-connect-next-button"); fireEvent.click(nextButton); // Try to move to next step @@ -205,7 +213,7 @@ describe("ConnectModal Component", () => { }); it("renders loading state and removes buttons when connecting", () => { - render(); + render(); expect( screen.getByText("Please wait while we connect to Git..."), ).toBeInTheDocument(); diff --git a/app/client/src/git/components/ConnectModal/ConnectInitialize/index.tsx b/app/client/src/git/components/ConnectModal/ConnectInitialize/index.tsx new file mode 100644 index 000000000000..af7a39ad6580 --- /dev/null +++ b/app/client/src/git/components/ConnectModal/ConnectInitialize/index.tsx @@ -0,0 +1,304 @@ +import React, { useCallback, useEffect, useState } from "react"; +import styled from "styled-components"; + +import AddDeployKey from "./AddDeployKey"; +import AnalyticsUtil from "ee/utils/AnalyticsUtil"; +import ChooseGitProvider from "./ChooseGitProvider"; +import GenerateSSH from "./GenerateSSH"; +import Steps from "./Steps"; +import Statusbar from "../../Statusbar"; +import { Button, ModalBody, ModalFooter, ModalHeader } from "@appsmith/ads"; +import { GIT_CONNECT_STEPS } from "./constants"; +import { + ADD_DEPLOY_KEY_STEP, + CHOOSE_A_GIT_PROVIDER_STEP, + CONFIGURE_GIT, + CONNECT_GIT_TEXT, + GENERATE_SSH_KEY_STEP, + GIT_CONNECT_WAITING, + GIT_IMPORT_WAITING, + IMPORT_APP, + IMPORT_APP_CTA, + PREVIOUS_STEP, + createMessage, +} from "ee/constants/messages"; +import { isValidGitRemoteUrl } from "../../utils"; +import type { ConnectRequestParams } from "git/requests/connectRequest.types"; +import noop from "lodash/noop"; +import type { GitApiError } from "git/store/types"; +import type { ConnectFormDataState } from "./types"; +import type { GitImportRequestParams } from "git/requests/gitImportRequest.types"; +import { GitErrorCodes } from "git/constants/enums"; + +const OFFSET = 200; +const OUTER_PADDING = 32; +const FOOTER = 56; +const HEADER = 44; + +const StyledModalBody = styled(ModalBody)` + flex: 1; + overflow-y: initial; + display: flex; + flex-direction: column; + max-height: calc( + 100vh - ${OFFSET}px - ${OUTER_PADDING}px - ${FOOTER}px - ${HEADER}px + ); +`; + +const StyledModalFooter = styled(ModalFooter)` + justify-content: space-between; + flex-direction: ${(p) => (!p.loading ? "row-reverse" : "row")}; +`; + +const steps = [ + { + key: GIT_CONNECT_STEPS.CHOOSE_PROVIDER, + text: createMessage(CHOOSE_A_GIT_PROVIDER_STEP), + }, + { + key: GIT_CONNECT_STEPS.GENERATE_SSH_KEY, + text: createMessage(GENERATE_SSH_KEY_STEP), + }, + { + key: GIT_CONNECT_STEPS.ADD_DEPLOY_KEY, + text: createMessage(ADD_DEPLOY_KEY_STEP), + }, +]; + +const possibleSteps = steps.map((s) => s.key); + +interface StyledModalFooterProps { + loading?: boolean; +} + +interface ConnectModalViewProps { + artifactType: string; + connect: (params: ConnectRequestParams) => void; + connectError: GitApiError | null; + fetchSSHKey: () => void; + generateSSHKey: (keyType: string) => void; + gitImport: (params: GitImportRequestParams) => void; + isConnectLoading: boolean; + isFetchSSHKeyLoading: boolean; + isGenerateSSHKeyLoading: boolean; + isGitImportLoading: boolean; + isImport: boolean; + sshPublicKey: string | null; +} + +function ConnectInitialize({ + artifactType, + connect = noop, + connectError = null, + fetchSSHKey = noop, + generateSSHKey = noop, + gitImport = noop, + isConnectLoading = false, + isFetchSSHKeyLoading = false, + isGenerateSSHKeyLoading = false, + isGitImportLoading = false, + isImport = false, + sshPublicKey = null, + // isCreateArtifactPermitted = false, + // onImportFromCalloutLinkClick, +}: ConnectModalViewProps) { + const nextStepText = { + [GIT_CONNECT_STEPS.CHOOSE_PROVIDER]: createMessage(CONFIGURE_GIT), + [GIT_CONNECT_STEPS.GENERATE_SSH_KEY]: createMessage(GENERATE_SSH_KEY_STEP), + [GIT_CONNECT_STEPS.ADD_DEPLOY_KEY]: createMessage( + isImport ? IMPORT_APP_CTA : CONNECT_GIT_TEXT, + ), + }; + + const [formData, setFormData] = useState({ + gitProvider: undefined, + gitEmptyRepoExists: undefined, + gitExistingRepoExists: false, + remoteUrl: undefined, + isAddedDeployKey: false, + sshKeyType: "ECDSA", + }); + + const [activeStep, setActiveStep] = useState( + GIT_CONNECT_STEPS.CHOOSE_PROVIDER, + ); + + const isLoading = + (!isImport && isConnectLoading) || (isImport && isGitImportLoading); + + const currentIndex = steps.findIndex((s) => s.key === activeStep); + + const isDisabled = { + [GIT_CONNECT_STEPS.CHOOSE_PROVIDER]: !isImport + ? !formData.gitProvider || + !formData.gitEmptyRepoExists || + formData.gitEmptyRepoExists === "no" + : !formData.gitProvider || !formData.gitExistingRepoExists, + [GIT_CONNECT_STEPS.GENERATE_SSH_KEY]: + typeof formData?.remoteUrl !== "string" || + !isValidGitRemoteUrl(formData?.remoteUrl), + [GIT_CONNECT_STEPS.ADD_DEPLOY_KEY]: !formData.isAddedDeployKey, + }; + + const handleChange = useCallback( + (partialFormData: Partial) => { + setFormData((s) => ({ ...s, ...partialFormData })); + }, + [], + ); + + const handlePreviousStep = useCallback(() => { + if (currentIndex > 0) { + setActiveStep(steps[currentIndex - 1].key); + } + }, [currentIndex]); + + const handleNextStep = useCallback(() => { + if (currentIndex < steps.length) { + switch (activeStep) { + case GIT_CONNECT_STEPS.CHOOSE_PROVIDER: { + setActiveStep(GIT_CONNECT_STEPS.GENERATE_SSH_KEY); + AnalyticsUtil.logEvent("GS_CONFIGURE_GIT"); + break; + } + case GIT_CONNECT_STEPS.GENERATE_SSH_KEY: { + setActiveStep(GIT_CONNECT_STEPS.ADD_DEPLOY_KEY); + AnalyticsUtil.logEvent("GS_GENERATE_KEY_BUTTON_CLICK", { + repoUrl: formData?.remoteUrl, + connectFlow: "v2", + }); + break; + } + case GIT_CONNECT_STEPS.ADD_DEPLOY_KEY: { + const gitProfile = { + authorName: "", + authorEmail: "", + useGlobalProfile: true, + }; + + if (formData.remoteUrl) { + if (!isImport) { + AnalyticsUtil.logEvent( + "GS_CONNECT_BUTTON_ON_GIT_SYNC_MODAL_CLICK", + { repoUrl: formData?.remoteUrl, connectFlow: "v2" }, + ); + connect({ + remoteUrl: formData.remoteUrl, + gitProfile, + }); + } else { + gitImport({ + remoteUrl: formData.remoteUrl, + gitProfile, + }); + } + } + + break; + } + } + } + }, [ + activeStep, + connect, + currentIndex, + formData.remoteUrl, + gitImport, + isImport, + ]); + + useEffect( + function changeStepOnErrorEffect() { + if (connectError?.code === GitErrorCodes.REPO_NOT_EMPTY) { + setActiveStep(GIT_CONNECT_STEPS.GENERATE_SSH_KEY); + } + }, + [connectError?.code], + ); + + return ( + <> + + {isImport ? createMessage(IMPORT_APP) : createMessage(CONFIGURE_GIT)} + + + {possibleSteps.includes(activeStep) && ( + + )} + {activeStep === GIT_CONNECT_STEPS.CHOOSE_PROVIDER && ( + + )} + {activeStep === GIT_CONNECT_STEPS.GENERATE_SSH_KEY && ( + + )} + {activeStep === GIT_CONNECT_STEPS.ADD_DEPLOY_KEY && ( + + )} + + + {isLoading && ( + + )} + {!isLoading && ( + + )} + {possibleSteps.includes(activeStep) && + currentIndex > 0 && + !isLoading && ( + + )} + + + ); +} + +export default ConnectInitialize; diff --git a/app/client/src/git/components/ConnectModal/types.ts b/app/client/src/git/components/ConnectModal/ConnectInitialize/types.ts similarity index 100% rename from app/client/src/git/components/ConnectModal/types.ts rename to app/client/src/git/components/ConnectModal/ConnectInitialize/types.ts diff --git a/app/client/src/git/components/ConnectModal/ConnectModalView.tsx b/app/client/src/git/components/ConnectModal/ConnectModalView.tsx index a50284482846..bd5b8b68172f 100644 --- a/app/client/src/git/components/ConnectModal/ConnectModalView.tsx +++ b/app/client/src/git/components/ConnectModal/ConnectModalView.tsx @@ -1,74 +1,24 @@ -import React, { useCallback, useState } from "react"; -import styled from "styled-components"; - -import AddDeployKey from "./AddDeployKey"; -import AnalyticsUtil from "ee/utils/AnalyticsUtil"; -import ChooseGitProvider from "./ChooseGitProvider"; -import GenerateSSH from "./GenerateSSH"; -import Steps from "./Steps"; -import Statusbar from "../Statusbar"; -import { Button, Modal, ModalBody, ModalFooter } from "@appsmith/ads"; -import { GIT_CONNECT_STEPS } from "./constants"; -import { - ADD_DEPLOY_KEY_STEP, - CHOOSE_A_GIT_PROVIDER_STEP, - CONFIGURE_GIT, - CONNECT_GIT_TEXT, - GENERATE_SSH_KEY_STEP, - GIT_CONNECT_WAITING, - GIT_IMPORT_WAITING, - IMPORT_APP_CTA, - PREVIOUS_STEP, - createMessage, -} from "ee/constants/messages"; -import { isValidGitRemoteUrl } from "../utils"; +import { Modal, ModalContent } from "@appsmith/ads"; import type { ConnectRequestParams } from "git/requests/connectRequest.types"; -import noop from "lodash/noop"; -import type { GitApiError } from "git/store/types"; -import type { ConnectFormDataState } from "./types"; import type { GitImportRequestParams } from "git/requests/gitImportRequest.types"; +import type { GitApiError } from "git/store/types"; +import React, { useCallback } from "react"; +import ConnectInitialize from "./ConnectInitialize"; +import ConnectSuccess from "./ConnectSuccess"; +import { noop } from "lodash"; +import type { GitSettingsTab } from "git/constants/enums"; +import styled from "styled-components"; -const OFFSET = 200; -const OUTER_PADDING = 32; -const FOOTER = 56; -const HEADER = 44; - -const StyledModalBody = styled(ModalBody)` - flex: 1; - overflow-y: initial; - display: flex; - flex-direction: column; - max-height: calc( - 100vh - ${OFFSET}px - ${OUTER_PADDING}px - ${FOOTER}px - ${HEADER}px - ); -`; - -const StyledModalFooter = styled(ModalFooter)` - justify-content: space-between; - flex-direction: ${(p) => (!p.loading ? "row-reverse" : "row")}; +const StyledModalContent = styled(ModalContent)` + &&& { + width: 640px; + transform: none !important; + top: 100px; + left: calc(50% - 320px); + max-height: calc(100vh - 200px); + } `; -const steps = [ - { - key: GIT_CONNECT_STEPS.CHOOSE_PROVIDER, - text: createMessage(CHOOSE_A_GIT_PROVIDER_STEP), - }, - { - key: GIT_CONNECT_STEPS.GENERATE_SSH_KEY, - text: createMessage(GENERATE_SSH_KEY_STEP), - }, - { - key: GIT_CONNECT_STEPS.ADD_DEPLOY_KEY, - text: createMessage(ADD_DEPLOY_KEY_STEP), - }, -]; - -const possibleSteps = steps.map((s) => s.key); - -interface StyledModalFooterProps { - loading?: boolean; -} - interface ConnectModalViewProps { artifactType: string; connect: (params: ConnectRequestParams) => void; @@ -82,227 +32,65 @@ interface ConnectModalViewProps { isGenerateSSHKeyLoading: boolean; isGitImportLoading: boolean; isImport: boolean; + resetFetchSSHKey: () => void; + resetGenerateSSHKey: () => void; sshPublicKey: string | null; toggleConnectModal: (open: boolean) => void; + isGitConnected: boolean; + remoteUrl: string | null; + toggleSettingsModal: ( + open: boolean, + tab?: keyof typeof GitSettingsTab, + ) => void; + defaultBranch: string | null; + repoName: string | null; } function ConnectModalView({ - artifactType, - connect = noop, - connectError = null, - fetchSSHKey = noop, - generateSSHKey = noop, - gitImport = noop, - isConnectLoading = false, + defaultBranch = null, isConnectModalOpen = false, - isFetchSSHKeyLoading = false, - isGenerateSSHKeyLoading = false, - isGitImportLoading = false, - isImport = false, - sshPublicKey = null, + isGitConnected = false, + remoteUrl = null, + repoName = null, + resetFetchSSHKey = noop, + resetGenerateSSHKey = noop, toggleConnectModal = noop, - // isCreateArtifactPermitted = false, - // onImportFromCalloutLinkClick, + toggleSettingsModal = noop, + ...rest }: ConnectModalViewProps) { - const nextStepText = { - [GIT_CONNECT_STEPS.CHOOSE_PROVIDER]: createMessage(CONFIGURE_GIT), - [GIT_CONNECT_STEPS.GENERATE_SSH_KEY]: createMessage(GENERATE_SSH_KEY_STEP), - [GIT_CONNECT_STEPS.ADD_DEPLOY_KEY]: createMessage( - isImport ? IMPORT_APP_CTA : CONNECT_GIT_TEXT, - ), - }; - - const [formData, setFormData] = useState({ - gitProvider: undefined, - gitEmptyRepoExists: undefined, - gitExistingRepoExists: false, - remoteUrl: undefined, - isAddedDeployKey: false, - sshKeyType: "ECDSA", - }); - - const [activeStep, setActiveStep] = useState( - GIT_CONNECT_STEPS.CHOOSE_PROVIDER, - ); - - const isLoading = - (!isImport && isConnectLoading) || (isImport && isGitImportLoading); - - const currentIndex = steps.findIndex((s) => s.key === activeStep); - - const isDisabled = { - [GIT_CONNECT_STEPS.CHOOSE_PROVIDER]: !isImport - ? !formData.gitProvider || - !formData.gitEmptyRepoExists || - formData.gitEmptyRepoExists === "no" - : !formData.gitProvider || !formData.gitExistingRepoExists, - [GIT_CONNECT_STEPS.GENERATE_SSH_KEY]: - typeof formData?.remoteUrl !== "string" || - !isValidGitRemoteUrl(formData?.remoteUrl), - [GIT_CONNECT_STEPS.ADD_DEPLOY_KEY]: !formData.isAddedDeployKey, - }; - - const handleChange = useCallback( - (partialFormData: Partial) => { - setFormData((s) => ({ ...s, ...partialFormData })); - }, - [], - ); - - const handlePreviousStep = useCallback(() => { - if (currentIndex > 0) { - setActiveStep(steps[currentIndex - 1].key); - } - }, [currentIndex]); - - const handleNextStep = useCallback(() => { - if (currentIndex < steps.length) { - switch (activeStep) { - case GIT_CONNECT_STEPS.CHOOSE_PROVIDER: { - setActiveStep(GIT_CONNECT_STEPS.GENERATE_SSH_KEY); - AnalyticsUtil.logEvent("GS_CONFIGURE_GIT"); - break; - } - case GIT_CONNECT_STEPS.GENERATE_SSH_KEY: { - setActiveStep(GIT_CONNECT_STEPS.ADD_DEPLOY_KEY); - AnalyticsUtil.logEvent("GS_GENERATE_KEY_BUTTON_CLICK", { - repoUrl: formData?.remoteUrl, - connectFlow: "v2", - }); - break; - } - case GIT_CONNECT_STEPS.ADD_DEPLOY_KEY: { - const gitProfile = { - authorName: "", - authorEmail: "", - useGlobalProfile: true, - }; - - if (formData.remoteUrl) { - if (!isImport) { - AnalyticsUtil.logEvent( - "GS_CONNECT_BUTTON_ON_GIT_SYNC_MODAL_CLICK", - { repoUrl: formData?.remoteUrl, connectFlow: "v2" }, - ); - connect({ - remoteUrl: formData.remoteUrl, - gitProfile, - // ! case: connect doesnt support error callback. use effect instead - // onErrorCallback: (error, response) => { - // if (response?.responseMeta?.error?.code === "AE-GIT-4033") { - // setActiveStep(GIT_CONNECT_STEPS.GENERATE_SSH_KEY); - // } - // } - }); - } else { - gitImport({ - remoteUrl: formData.remoteUrl, - gitProfile, - }); - } - } - - break; - } - } - } - }, [ - activeStep, - connect, - currentIndex, - formData.remoteUrl, - gitImport, - isImport, - ]); - const handleModalOpenChange = useCallback( - (isOpen: boolean) => { - if (!isOpen) { - toggleConnectModal(false); + (open: boolean) => { + if (!open) { + resetFetchSSHKey(); + resetGenerateSSHKey(); } + + toggleConnectModal(open); }, - [toggleConnectModal], + [resetFetchSSHKey, resetGenerateSSHKey, toggleConnectModal], ); return ( - - {possibleSteps.includes(activeStep) && ( - - )} - {activeStep === GIT_CONNECT_STEPS.CHOOSE_PROVIDER && ( - - )} - {activeStep === GIT_CONNECT_STEPS.GENERATE_SSH_KEY && ( - - )} - {activeStep === GIT_CONNECT_STEPS.ADD_DEPLOY_KEY && ( - - )} - - - {isLoading && ( - + {isConnectModalOpen ? ( + // need fragment to arrange conditions properly + // eslint-disable-next-line react/jsx-no-useless-fragment + <> + {isGitConnected ? ( + + ) : ( + )} - /> - )} - {!isLoading && ( - - )} - {possibleSteps.includes(activeStep) && - currentIndex > 0 && - !isLoading && ( - - )} - + + ) : null} + ); } diff --git a/app/client/src/git/components/ConnectModal/ConnectSuccess/index.tsx b/app/client/src/git/components/ConnectModal/ConnectSuccess/index.tsx new file mode 100644 index 000000000000..47f762b6bb5b --- /dev/null +++ b/app/client/src/git/components/ConnectModal/ConnectSuccess/index.tsx @@ -0,0 +1,178 @@ +import { + GIT_CONNECT_SUCCESS_PROTECTION_MSG, + GIT_CONNECT_SUCCESS_TITLE, + GIT_CONNECT_SUCCESS_ACTION_SETTINGS, + GIT_CONNECT_SUCCESS_ACTION_CONTINUE, + createMessage, + GIT_CONNECT_SUCCESS_PROTECTION_DOC_CTA, + GIT_CONNECT_SUCCESS_DEFAULT_BRANCH, + GIT_CONNECT_SUCCESS_REPO_NAME, + GIT_CONNECT_SUCCESS_DEFAULT_BRANCH_TOOLTIP, +} from "ee/constants/messages"; +import { + Button, + Icon, + ModalBody, + ModalFooter, + Text, + Link, + Tooltip, +} from "@appsmith/ads"; +import React, { useCallback } from "react"; +import styled from "styled-components"; +import AnalyticsUtil from "ee/utils/AnalyticsUtil"; +import { DOCS_BRANCH_PROTECTION_URL } from "constants/ThirdPartyConstants"; +import noop from "lodash/noop"; +import type { GitSettingsTab } from "git/constants/enums"; + +const TitleText = styled(Text)` + flex: 1; + font-weight: 600; +`; + +const LinkText = styled(Text)` + span { + font-weight: 500; + } +`; + +function ConnectionSuccessTitle() { + return ( +
+ + + {createMessage(GIT_CONNECT_SUCCESS_TITLE)} + +
+ ); +} + +interface ConnectSuccessModalViewProps { + repoName: string | null; + defaultBranch: string | null; +} + +function ConnectSuccessModalView({ + defaultBranch, + repoName, +}: ConnectSuccessModalViewProps) { + return ( + <> +
+
+
+ + + {createMessage(GIT_CONNECT_SUCCESS_REPO_NAME)} + +
+ {repoName || "-"} +
+
+
+ + + {createMessage(GIT_CONNECT_SUCCESS_DEFAULT_BRANCH)} + + + + +
+ {defaultBranch || "-"} +
+
+
+ + {createMessage(GIT_CONNECT_SUCCESS_PROTECTION_MSG)} + +
+ + + {createMessage(GIT_CONNECT_SUCCESS_PROTECTION_DOC_CTA)} + + + + ); +} + +interface ConnectSuccessProps { + defaultBranch: string | null; + remoteUrl: string | null; + repoName: string | null; + toggleConnectModal: (open: boolean) => void; + toggleSettingsModal: ( + open: boolean, + tab?: keyof typeof GitSettingsTab, + ) => void; +} + +function ConnectSuccess({ + defaultBranch, + remoteUrl = null, + repoName, + toggleConnectModal = noop, + toggleSettingsModal = noop, +}: ConnectSuccessProps) { + const handleStartGit = useCallback(() => { + toggleConnectModal(false); + AnalyticsUtil.logEvent("GS_START_USING_GIT", { + repoUrl: remoteUrl, + }); + }, [remoteUrl, toggleConnectModal]); + + const handleOpenSettings = useCallback(() => { + toggleConnectModal(false); + toggleSettingsModal(true); + AnalyticsUtil.logEvent("GS_OPEN_GIT_SETTINGS", { + repoUrl: remoteUrl, + }); + }, [remoteUrl, toggleConnectModal, toggleSettingsModal]); + + return ( + <> + + + + + + + + + + ); +} + +export default ConnectSuccess; diff --git a/app/client/src/git/components/ConnectModal/index.tsx b/app/client/src/git/components/ConnectModal/index.tsx index 4db6f03adc83..0e1cc31894ab 100644 --- a/app/client/src/git/components/ConnectModal/index.tsx +++ b/app/client/src/git/components/ConnectModal/index.tsx @@ -2,6 +2,8 @@ import React from "react"; import ConnectModalView from "./ConnectModalView"; import { useGitContext } from "../GitContextProvider"; import useConnect from "git/hooks/useConnect"; +import useMetadata from "git/hooks/useMetadata"; +import useSettings from "git/hooks/useSettings"; interface ConnectModalProps { isImport?: boolean; @@ -20,18 +22,26 @@ function ConnectModal({ isImport = false }: ConnectModalProps) { isFetchSSHKeyLoading, isGenerateSSHKeyLoading, isGitImportLoading, + resetFetchSSHKey, + resetGenerateSSHKey, sshKey, - togglleConnectModal, + toggleConnectModal, } = useConnect(); + const { isGitConnected, metadata } = useMetadata(); + const { toggleSettingsModal } = useSettings(); const { artifactType } = artifactDef; const sshPublicKey = sshKey?.publicKey ?? null; + const remoteUrl = metadata?.remoteUrl ?? null; + const repoName = metadata?.repoName ?? null; + const defaultBranch = metadata?.defaultBranchName ?? null; return ( ); } diff --git a/app/client/src/git/components/DefaultBranch/DefaultBranchCE.tsx b/app/client/src/git/components/DefaultBranch/DefaultBranchCE.tsx index e305972ba61e..c1f9d7c3ca1c 100644 --- a/app/client/src/git/components/DefaultBranch/DefaultBranchCE.tsx +++ b/app/client/src/git/components/DefaultBranch/DefaultBranchCE.tsx @@ -1,9 +1,9 @@ import React from "react"; import DefaultBranchView from "./DefaultBranchView"; -import { useGitContext } from "../GitContextProvider"; +import useBranches from "git/hooks/useBranches"; export default function DefaultBranchCE() { - const { branches } = useGitContext(); + const { branches } = useBranches(); return ( void; -} - -export default function useGitConnect({ - artifactType, - baseArtifactId, -}: UseGitConnectParams): UseGitConnectReturnValue { - const dispatch = useDispatch(); - const basePayload = useMemo( - () => ({ artifactType, baseArtifactId }), - [artifactType, baseArtifactId], - ); - - const toggleConnectModal = (open: boolean) => { - dispatch( - gitArtifactActions.toggleConnectModal({ - ...basePayload, - open, - }), - ); - }; - - return { - toggleConnectModal, - }; -} diff --git a/app/client/src/git/components/GitContextProvider/hooks/useGitContextValue.ts b/app/client/src/git/components/GitContextProvider/hooks/useGitContextValue.ts index 9b62bc1ba4cf..35decfce1662 100644 --- a/app/client/src/git/components/GitContextProvider/hooks/useGitContextValue.ts +++ b/app/client/src/git/components/GitContextProvider/hooks/useGitContextValue.ts @@ -1,10 +1,6 @@ import type { GitArtifactType } from "git/constants/enums"; -import type { UseGitConnectReturnValue } from "./useGitConnect"; import type { UseGitOpsReturnValue } from "./useGitOps"; -import type { UseGitBranchesReturnValue } from "./useGitBranches"; -import useGitConnect from "./useGitConnect"; import useGitOps from "./useGitOps"; -import useGitBranches from "./useGitBranches"; import { useMemo } from "react"; // internal dependencies @@ -21,10 +17,7 @@ export interface UseGitContextValueParams { ) => StatusTreeStruct[] | null; } -export interface GitContextValue - extends UseGitConnectReturnValue, - UseGitOpsReturnValue, - UseGitBranchesReturnValue { +export interface GitContextValue extends UseGitOpsReturnValue { artifactType: keyof typeof GitArtifactType; baseArtifactId: string; artifactDef: { @@ -47,12 +40,10 @@ export default function useGitContextValue({ () => ({ artifactType, baseArtifactId }), [artifactType, baseArtifactId], ); - const useGitConnectReturnValue = useGitConnect(artifactDef); const useGitOpsReturnValue = useGitOps({ ...artifactDef, artifactId: artifact?.id ?? null, }); - const useGitBranchesReturnValue = useGitBranches(artifactDef); return { artifactType, @@ -61,7 +52,5 @@ export default function useGitContextValue({ statusTransformer, artifact, ...useGitOpsReturnValue, - ...useGitBranchesReturnValue, - ...useGitConnectReturnValue, }; } diff --git a/app/client/src/git/components/GitContextProvider/hooks/useGitMetadata.ts b/app/client/src/git/components/GitContextProvider/hooks/useGitMetadata.ts deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/app/client/src/git/components/OpsModal/TabDeploy/index.tsx b/app/client/src/git/components/OpsModal/TabDeploy/index.tsx index 53d1a8f4c6af..5c7fcf774aac 100644 --- a/app/client/src/git/components/OpsModal/TabDeploy/index.tsx +++ b/app/client/src/git/components/OpsModal/TabDeploy/index.tsx @@ -2,6 +2,7 @@ import React from "react"; import TabDeployView from "./TabDeployView"; import { useGitContext } from "git/components/GitContextProvider"; import useMetadata from "git/hooks/useMetadata"; +import useBranches from "git/hooks/useBranches"; export default function TabDeploy() { const { @@ -11,7 +12,6 @@ export default function TabDeploy() { commit, commitError, commitLoading, - currentBranch, discard, discardError, discardLoading, @@ -21,6 +21,7 @@ export default function TabDeploy() { pullLoading, status, } = useGitContext(); + const { currentBranch } = useBranches(); const { metadata } = useMetadata(); const lastDeployedAt = artifact?.lastDeployedAt ?? null; diff --git a/app/client/src/git/components/OpsModal/TabMerge/index.tsx b/app/client/src/git/components/OpsModal/TabMerge/index.tsx index adeb24ee9914..47350adc597d 100644 --- a/app/client/src/git/components/OpsModal/TabMerge/index.tsx +++ b/app/client/src/git/components/OpsModal/TabMerge/index.tsx @@ -2,14 +2,11 @@ import React from "react"; import TabMergeView from "./TabMergeView"; import { useGitContext } from "git/components/GitContextProvider"; import useProtectedBranches from "git/hooks/useProtectedBranches"; +import useBranches from "git/hooks/useBranches"; export default function TabMerge() { const { - branches, clearMergeStatus, - currentBranch, - fetchBranches, - fetchBranchesLoading, fetchMergeStatus, fetchMergeStatusLoading, fetchStatusLoading, @@ -19,6 +16,8 @@ export default function TabMerge() { mergeStatus, status, } = useGitContext(); + const { branches, currentBranch, fetchBranches, fetchBranchesLoading } = + useBranches(); const { protectedBranches } = useProtectedBranches(); const isStatusClean = status?.isClean ?? false; diff --git a/app/client/src/git/components/ProtectedBranches/index.tsx b/app/client/src/git/components/ProtectedBranches/index.tsx index 8f1381ca67c9..651ebd577529 100644 --- a/app/client/src/git/components/ProtectedBranches/index.tsx +++ b/app/client/src/git/components/ProtectedBranches/index.tsx @@ -1,12 +1,12 @@ import React from "react"; import ProtectedBranchesView from "./ProtectedBranchesView"; -import { useGitContext } from "../GitContextProvider"; import useDefaultBranch from "git/hooks/useDefaultBranch"; import useProtectedBranches from "git/hooks/useProtectedBranches"; import useGitFeatureFlags from "git/hooks/useGitFeatureFlags"; +import useBranches from "git/hooks/useBranches"; function ProtectedBranches() { - const { branches } = useGitContext(); + const { branches } = useBranches(); const { defaultBranch } = useDefaultBranch(); const { isUpdateProtectedBranchesLoading, diff --git a/app/client/src/git/components/QuickActions/index.tsx b/app/client/src/git/components/QuickActions/index.tsx index 88055bc5ccb4..be617d5e8af4 100644 --- a/app/client/src/git/components/QuickActions/index.tsx +++ b/app/client/src/git/components/QuickActions/index.tsx @@ -7,6 +7,7 @@ import useGitPermissions from "git/hooks/useGitPermissions"; import useAutocommit from "git/hooks/useAutocommit"; import useSettings from "git/hooks/useSettings"; import useMetadata from "git/hooks/useMetadata"; +import useConnect from "git/hooks/useConnect"; function QuickActions() { const { @@ -17,7 +18,6 @@ function QuickActions() { pullError, pullLoading, status, - toggleConnectModal, toggleOpsModal, } = useGitContext(); const { isGitConnected } = useMetadata(); @@ -25,6 +25,7 @@ function QuickActions() { const { isConnectPermitted } = useGitPermissions(); const { isAutocommitEnabled, isAutocommitPolling } = useAutocommit(); const { toggleSettingsModal } = useSettings(); + const { toggleConnectModal } = useConnect(); const isPullFailing = !!pullError; const isStatusClean = status?.isClean ?? false; diff --git a/app/client/src/git/constants/enums.ts b/app/client/src/git/constants/enums.ts index 244f2237a760..fe5673d1ac3d 100644 --- a/app/client/src/git/constants/enums.ts +++ b/app/client/src/git/constants/enums.ts @@ -45,6 +45,7 @@ export enum MergeStatusState { } export enum GitErrorCodes { + REPO_NOT_EMPTY = "AE-GIT-4033", REPO_LIMIT_REACHED = "AE-GIT-4043", PUSH_FAILED_REMOTE_COUNTERPART_IS_AHEAD = "AE-GIT-4048", } diff --git a/app/client/src/git/components/GitContextProvider/hooks/useGitBranches.ts b/app/client/src/git/hooks/useBranches.ts similarity index 57% rename from app/client/src/git/components/GitContextProvider/hooks/useGitBranches.ts rename to app/client/src/git/hooks/useBranches.ts index 551338860fad..8785f0563a7b 100644 --- a/app/client/src/git/components/GitContextProvider/hooks/useGitBranches.ts +++ b/app/client/src/git/hooks/useBranches.ts @@ -1,5 +1,4 @@ -import type { GitArtifactType } from "git/constants/enums"; -import type { FetchBranchesResponseData } from "git/requests/fetchBranchesRequest.types"; +import { useGitContext } from "git/components/GitContextProvider"; import { gitArtifactActions } from "git/store/gitArtifactSlice"; import { selectBranches, @@ -8,112 +7,84 @@ import { selectCurrentBranch, selectDeleteBranch, } from "git/store/selectors/gitSingleArtifactSelectors"; -import type { GitApiError, GitRootState } from "git/store/types"; -import { useCallback, useMemo } from "react"; +import type { GitRootState } from "git/store/types"; +import { useCallback } from "react"; import { useDispatch, useSelector } from "react-redux"; -interface UseGitBranchesParams { - artifactType: keyof typeof GitArtifactType; - baseArtifactId: string; -} - -export interface UseGitBranchesReturnValue { - branches: FetchBranchesResponseData | null; - fetchBranchesLoading: boolean; - fetchBranchesError: GitApiError | null; - fetchBranches: () => void; - createBranchLoading: boolean; - createBranchError: GitApiError | null; - createBranch: (branchName: string) => void; - deleteBranchLoading: boolean; - deleteBranchError: GitApiError | null; - deleteBranch: (branchName: string) => void; - checkoutBranchLoading: boolean; - checkoutBranchError: GitApiError | null; - checkoutBranch: (branchName: string) => void; - currentBranch: string | null; - toggleBranchListPopup: (open: boolean) => void; -} +export default function useBranches() { + const { artifactDef } = useGitContext(); -export default function useGitBranches({ - artifactType, - baseArtifactId, -}: UseGitBranchesParams): UseGitBranchesReturnValue { - const basePayload = useMemo( - () => ({ artifactType, baseArtifactId }), - [artifactType, baseArtifactId], - ); const dispatch = useDispatch(); // fetch branches const branchesState = useSelector((state: GitRootState) => - selectBranches(state, basePayload), + selectBranches(state, artifactDef), ); const fetchBranches = useCallback(() => { dispatch( gitArtifactActions.fetchBranchesInit({ - ...basePayload, + ...artifactDef, pruneBranches: true, }), ); - }, [basePayload, dispatch]); + }, [artifactDef, dispatch]); // create branch const createBranchState = useSelector((state: GitRootState) => - selectCreateBranch(state, basePayload), + selectCreateBranch(state, artifactDef), ); const createBranch = useCallback( (branchName: string) => { dispatch( gitArtifactActions.createBranchInit({ - ...basePayload, + ...artifactDef, branchName, }), ); }, - [basePayload, dispatch], + [artifactDef, dispatch], ); // delete branch const deleteBranchState = useSelector((state: GitRootState) => - selectDeleteBranch(state, basePayload), + selectDeleteBranch(state, artifactDef), ); const deleteBranch = useCallback( (branchName: string) => { dispatch( gitArtifactActions.deleteBranchInit({ - ...basePayload, + ...artifactDef, branchName, }), ); }, - [basePayload, dispatch], + [artifactDef, dispatch], ); // checkout branch const checkoutBranchState = useSelector((state: GitRootState) => - selectCheckoutBranch(state, basePayload), + selectCheckoutBranch(state, artifactDef), ); const checkoutBranch = useCallback( (branchName: string) => { dispatch( gitArtifactActions.checkoutBranchInit({ - ...basePayload, + ...artifactDef, branchName, }), ); }, - [basePayload, dispatch], + [artifactDef, dispatch], ); // derived const currentBranch = useSelector((state: GitRootState) => - selectCurrentBranch(state, basePayload), + selectCurrentBranch(state, artifactDef), ); // git branch list popup const toggleBranchListPopup = (open: boolean) => { dispatch( gitArtifactActions.toggleBranchListPopup({ - ...basePayload, + ...artifactDef, open, }), ); diff --git a/app/client/src/git/hooks/useConnect.ts b/app/client/src/git/hooks/useConnect.ts index ac38c4e881c1..1064ce7ff26e 100644 --- a/app/client/src/git/hooks/useConnect.ts +++ b/app/client/src/git/hooks/useConnect.ts @@ -48,19 +48,36 @@ export default function useConnect() { dispatch(gitArtifactActions.fetchSSHKeyInit(artifactDef)); }, [artifactDef, dispatch]); + const resetFetchSSHKey = useCallback(() => { + dispatch(gitArtifactActions.resetFetchSSHKey(artifactDef)); + }, [artifactDef, dispatch]); + const generateSSHKeyState = useSelector((state: GitRootState) => selectGenerateSSHKeyState(state, artifactDef), ); - const generateSSHKey = useCallback(() => { - dispatch(gitArtifactActions.generateSSHKeyInit(artifactDef)); + const generateSSHKey = useCallback( + (keyType: string, isImport: boolean = false) => { + dispatch( + gitArtifactActions.generateSSHKeyInit({ + ...artifactDef, + keyType, + isImport, + }), + ); + }, + [artifactDef, dispatch], + ); + + const resetGenerateSSHKey = useCallback(() => { + dispatch(gitArtifactActions.resetGenerateSSHKey(artifactDef)); }, [artifactDef, dispatch]); const isConnectModalOpen = useSelector((state: GitRootState) => selectConnectModalOpen(state, artifactDef), ); - const togglleConnectModal = useCallback( + const toggleConnectModal = useCallback( (open: boolean) => { dispatch(gitArtifactActions.toggleConnectModal({ ...artifactDef, open })); }, @@ -78,10 +95,12 @@ export default function useConnect() { isFetchSSHKeyLoading: fetchSSHKeyState?.loading ?? false, fetchSSHKeyError: fetchSSHKeyState?.error ?? null, fetchSSHKey, + resetFetchSSHKey, isGenerateSSHKeyLoading: generateSSHKeyState?.loading ?? false, generateSSHKeyError: generateSSHKeyState?.error ?? null, generateSSHKey, + resetGenerateSSHKey, isConnectModalOpen, - togglleConnectModal, + toggleConnectModal, }; } diff --git a/app/client/src/git/requests/generateSSHKeyRequest.ts b/app/client/src/git/requests/generateSSHKeyRequest.ts index 7c747f94371e..896426347f30 100644 --- a/app/client/src/git/requests/generateSSHKeyRequest.ts +++ b/app/client/src/git/requests/generateSSHKeyRequest.ts @@ -10,9 +10,9 @@ export default async function generateSSHKeyRequest( baseApplicationId: string, params: GenerateSSHKeyRequestParams, ): AxiosPromise { - const url = params.isImporting + const url = params.isImport ? `${GIT_BASE_URL}/import/keys?keyType=${params.keyType}` : `${APPLICATION_BASE_URL}/ssh-keypair/${baseApplicationId}?keyType=${params.keyType}`; - return params.isImporting ? Api.get(url) : Api.post(url); + return params.isImport ? Api.get(url) : Api.post(url); } diff --git a/app/client/src/git/requests/generateSSHKeyRequest.types.ts b/app/client/src/git/requests/generateSSHKeyRequest.types.ts index 3cd45cf965e9..45374e42d5b1 100644 --- a/app/client/src/git/requests/generateSSHKeyRequest.types.ts +++ b/app/client/src/git/requests/generateSSHKeyRequest.types.ts @@ -2,7 +2,7 @@ import type { ApiResponse } from "api/types"; export interface GenerateSSHKeyRequestParams { keyType: string; - isImporting: boolean; + isImport: boolean; } export interface GenerateSSHKeyResponseData { diff --git a/app/client/src/git/sagas/connectSaga.ts b/app/client/src/git/sagas/connectSaga.ts index b1bfa286e778..b13c2f6c2c2a 100644 --- a/app/client/src/git/sagas/connectSaga.ts +++ b/app/client/src/git/sagas/connectSaga.ts @@ -53,6 +53,13 @@ export default function* connectSaga( history.replace(newUrl); // ! case for updating lastDeployedAt in application manually? } + + yield put( + gitArtifactActions.initGitForEditor({ + ...basePayload, + artifact: response.data, + }), + ); } } catch (e) { if (response && response.responseMeta.error) { @@ -67,12 +74,7 @@ export default function* connectSaga( ); } - yield put( - gitArtifactActions.connectError({ - ...basePayload, - error, - }), - ); + yield put(gitArtifactActions.connectError({ ...basePayload, error })); } else { log.error(e); captureException(e); diff --git a/app/client/src/git/sagas/fetchSSHKeySaga.ts b/app/client/src/git/sagas/fetchSSHKeySaga.ts new file mode 100644 index 000000000000..02f797edae66 --- /dev/null +++ b/app/client/src/git/sagas/fetchSSHKeySaga.ts @@ -0,0 +1,37 @@ +import { captureException } from "@sentry/react"; +import fetchSSHKeyRequest from "git/requests/fetchSSHKeyRequest"; +import type { FetchSSHKeyResponse } from "git/requests/fetchSSHKeyRequest.types"; +import { gitArtifactActions } from "git/store/gitArtifactSlice"; +import type { GitArtifactPayloadAction } from "git/store/types"; +import log from "loglevel"; +import { call, put } from "redux-saga/effects"; +import { validateResponse } from "sagas/ErrorSagas"; + +export function* fetchSSHKeySaga(action: GitArtifactPayloadAction) { + const { artifactType, baseArtifactId } = action.payload; + const artifactDef = { artifactType, baseArtifactId }; + let response: FetchSSHKeyResponse | undefined; + + try { + response = yield call(fetchSSHKeyRequest, baseArtifactId); + const isValidResponse: boolean = yield validateResponse(response, false); + + if (response && isValidResponse) { + yield put( + gitArtifactActions.fetchSSHKeySuccess({ + ...artifactDef, + responseData: response.data, + }), + ); + } + } catch (e) { + if (response && response.responseMeta.error) { + const { error } = response.responseMeta; + + yield put(gitArtifactActions.fetchSSHKeyError({ ...artifactDef, error })); + } else { + log.error(e); + captureException(e); + } + } +} diff --git a/app/client/src/git/sagas/generateSSHKeySaga.ts b/app/client/src/git/sagas/generateSSHKeySaga.ts new file mode 100644 index 000000000000..09773f9dc0d4 --- /dev/null +++ b/app/client/src/git/sagas/generateSSHKeySaga.ts @@ -0,0 +1,60 @@ +import { captureException } from "@sentry/react"; +import { GitErrorCodes } from "git/constants/enums"; +import generateSSHKeyRequest from "git/requests/generateSSHKeyRequest"; +import type { + GenerateSSHKeyRequestParams, + GenerateSSHKeyResponse, +} from "git/requests/generateSSHKeyRequest.types"; +import type { GenerateSSHKeyInitPayload } from "git/store/actions/generateSSHKeyActions"; +import { gitArtifactActions } from "git/store/gitArtifactSlice"; +import type { GitArtifactPayloadAction } from "git/store/types"; +import log from "loglevel"; +import { call, put } from "redux-saga/effects"; +import { validateResponse } from "sagas/ErrorSagas"; + +export function* generateSSHKeySaga( + action: GitArtifactPayloadAction, +) { + const { artifactType, baseArtifactId } = action.payload; + const artifactDef = { artifactType, baseArtifactId }; + let response: GenerateSSHKeyResponse | undefined; + + try { + const params: GenerateSSHKeyRequestParams = { + keyType: action.payload.keyType, + isImport: action.payload.isImport, + }; + + response = yield call(generateSSHKeyRequest, baseArtifactId, params); + const isValidResponse: boolean = yield validateResponse(response); + + if (response && isValidResponse) { + yield put( + gitArtifactActions.generateSSHKeySuccess({ + ...artifactDef, + responseData: response.data, + }), + ); + } + } catch (e) { + if (response && response.responseMeta.error) { + const { error } = response.responseMeta; + + if (GitErrorCodes.REPO_LIMIT_REACHED === error.code) { + yield put( + gitArtifactActions.toggleRepoLimitErrorModal({ + ...artifactDef, + open: true, + }), + ); + } + + yield put( + gitArtifactActions.generateSSHKeyError({ ...artifactDef, error }), + ); + } else { + log.error(e); + captureException(e); + } + } +} diff --git a/app/client/src/git/sagas/index.ts b/app/client/src/git/sagas/index.ts index 0d933a34ff81..0bd96a008b3a 100644 --- a/app/client/src/git/sagas/index.ts +++ b/app/client/src/git/sagas/index.ts @@ -31,6 +31,8 @@ import updateProtectedBranchesSaga from "./updateProtectedBranchesSaga"; import fetchMetadataSaga from "./fetchMetadataSaga"; import toggleAutocommitSaga from "./toggleAutocommitSaga"; import disconnectSaga from "./disconnectSaga"; +import { fetchSSHKeySaga } from "./fetchSSHKeySaga"; +import { generateSSHKeySaga } from "./generateSSHKeySaga"; const gitRequestBlockingActions: Record< string, @@ -81,6 +83,10 @@ const gitRequestNonBlockingActions: Record< [gitArtifactActions.initGitForEditor.type]: initGitForEditorSaga, [gitArtifactActions.toggleAutocommitInit.type]: toggleAutocommitSaga, + // ssh key + [gitArtifactActions.fetchSSHKeyInit.type]: fetchSSHKeySaga, + [gitArtifactActions.generateSSHKeyInit.type]: generateSSHKeySaga, + // EE ...gitRequestNonBlockingActionsEE, }; diff --git a/app/client/src/git/sagas/initGitSaga.ts b/app/client/src/git/sagas/initGitSaga.ts index 2c62fd31851b..aa50efce17b1 100644 --- a/app/client/src/git/sagas/initGitSaga.ts +++ b/app/client/src/git/sagas/initGitSaga.ts @@ -13,7 +13,7 @@ export default function* initGitForEditorSaga( yield put(gitArtifactActions.mount(basePayload)); if (artifactType === GitArtifactType.Application) { - if (!!artifact.gitApplicationMetadata) { + if (!!artifact.gitApplicationMetadata?.remoteUrl) { yield put(gitArtifactActions.fetchMetadataInit(basePayload)); yield take(gitArtifactActions.fetchMetadataSuccess.type); yield put( diff --git a/app/client/src/git/store/actions/fetchSSHKeyActions.ts b/app/client/src/git/store/actions/fetchSSHKeyActions.ts index 0b76b70fe87c..828cf6ebcb75 100644 --- a/app/client/src/git/store/actions/fetchSSHKeyActions.ts +++ b/app/client/src/git/store/actions/fetchSSHKeyActions.ts @@ -28,3 +28,11 @@ export const fetchSSHKeyErrorAction = return state; }); + +export const resetFetchSSHKeyAction = createSingleArtifactAction((state) => { + state.apiResponses.sshKey.loading = false; + state.apiResponses.sshKey.error = null; + state.apiResponses.sshKey.value = null; + + return state; +}); diff --git a/app/client/src/git/store/actions/generateSSHKeyActions.ts b/app/client/src/git/store/actions/generateSSHKeyActions.ts index bad6de1405c4..fa70c3a1ba28 100644 --- a/app/client/src/git/store/actions/generateSSHKeyActions.ts +++ b/app/client/src/git/store/actions/generateSSHKeyActions.ts @@ -1,13 +1,20 @@ -import type { GenerateSSHKeyResponseData } from "git/requests/generateSSHKeyRequest.types"; +import type { + GenerateSSHKeyRequestParams, + GenerateSSHKeyResponseData, +} from "git/requests/generateSSHKeyRequest.types"; import { createSingleArtifactAction } from "../helpers/createSingleArtifactAction"; import type { GitAsyncErrorPayload, GitAsyncSuccessPayload } from "../types"; -export const generateSSHKeyInitAction = createSingleArtifactAction((state) => { - state.apiResponses.generateSSHKey.loading = true; - state.apiResponses.generateSSHKey.error = null; +export interface GenerateSSHKeyInitPayload + extends GenerateSSHKeyRequestParams {} - return state; -}); +export const generateSSHKeyInitAction = + createSingleArtifactAction((state) => { + state.apiResponses.generateSSHKey.loading = true; + state.apiResponses.generateSSHKey.error = null; + + return state; + }); export const generateSSHKeySuccessAction = createSingleArtifactAction< GitAsyncSuccessPayload @@ -28,3 +35,10 @@ export const generateSSHKeyErrorAction = return state; }); + +export const resetGenerateSSHKeyAction = createSingleArtifactAction((state) => { + state.apiResponses.generateSSHKey.loading = false; + state.apiResponses.generateSSHKey.error = null; + + return state; +}); diff --git a/app/client/src/git/store/actions/uiActions.ts b/app/client/src/git/store/actions/uiActions.ts index 6780ee64a4bb..fe861358d5ac 100644 --- a/app/client/src/git/store/actions/uiActions.ts +++ b/app/client/src/git/store/actions/uiActions.ts @@ -10,7 +10,7 @@ export const toggleConnectModalAction = createSingleArtifactAction((state, action) => { const { open } = action.payload; - state.ui.connectModal.open = open; + state.ui.connectModalOpen = open; return state; }); diff --git a/app/client/src/git/store/gitArtifactSlice.ts b/app/client/src/git/store/gitArtifactSlice.ts index bcc607ecca18..f5bb5bc6b9eb 100644 --- a/app/client/src/git/store/gitArtifactSlice.ts +++ b/app/client/src/git/store/gitArtifactSlice.ts @@ -128,11 +128,13 @@ import { fetchSSHKeyErrorAction, fetchSSHKeyInitAction, fetchSSHKeySuccessAction, + resetFetchSSHKeyAction, } from "./actions/fetchSSHKeyActions"; import { generateSSHKeyErrorAction, generateSSHKeyInitAction, generateSSHKeySuccessAction, + resetGenerateSSHKeyAction, } from "./actions/generateSSHKeyActions"; const initialState: GitArtifactReduxState = {}; @@ -160,9 +162,11 @@ export const gitArtifactSlice = createSlice({ fetchSSHKeyInit: fetchSSHKeyInitAction, fetchSSHKeySuccess: fetchSSHKeySuccessAction, fetchSSHKeyError: fetchSSHKeyErrorAction, + resetFetchSSHKey: resetFetchSSHKeyAction, generateSSHKeyInit: generateSSHKeyInitAction, generateSSHKeySuccess: generateSSHKeySuccessAction, generateSSHKeyError: generateSSHKeyErrorAction, + resetGenerateSSHKey: resetGenerateSSHKeyAction, disconnectInit: disconnectInitAction, disconnectSuccess: disconnectSuccessAction, disconnectError: disconnectErrorAction, From a71a6643767eb5cdbfaf3d531788ee64acf78d98 Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Mon, 16 Dec 2024 01:39:32 +0800 Subject: [PATCH 067/143] chore: adding fixes --- .../components/ConflictErrorModal/index.tsx | 4 +- .../ChooseGitProvider.test.tsx | 11 +- .../ConnectInitialize/ChooseGitProvider.tsx | 44 ++-- .../ConnectInitialize/index.test.tsx | 3 + .../ConnectModal/ConnectInitialize/index.tsx | 13 +- .../ConnectModal/ConnectModalView.tsx | 7 +- .../src/git/components/ConnectModal/index.tsx | 5 +- .../hooks/useGitContextValue.ts | 56 ----- .../GitContextProvider/hooks/useGitOps.ts | 225 ------------------ .../components/GitContextProvider/index.tsx | 79 +++++- .../components/OpsModal/TabDeploy/index.tsx | 37 ++- .../components/OpsModal/TabMerge/index.tsx | 18 +- .../src/git/components/OpsModal/index.tsx | 7 +- .../src/git/components/QuickActions/index.tsx | 25 +- .../git/components/StatusChanges/index.tsx | 6 +- app/client/src/git/hooks/useCommit.ts | 39 +++ app/client/src/git/hooks/useDiscard.ts | 30 +++ app/client/src/git/hooks/useMerge.ts | 58 +++++ app/client/src/git/hooks/useMetadata.ts | 6 +- app/client/src/git/hooks/useOps.ts | 57 +++++ app/client/src/git/hooks/usePull.ts | 31 +++ app/client/src/git/hooks/useStatus.ts | 31 +++ .../selectors/gitSingleArtifactSelectors.ts | 20 +- 23 files changed, 437 insertions(+), 375 deletions(-) delete mode 100644 app/client/src/git/components/GitContextProvider/hooks/useGitContextValue.ts delete mode 100644 app/client/src/git/components/GitContextProvider/hooks/useGitOps.ts create mode 100644 app/client/src/git/hooks/useCommit.ts create mode 100644 app/client/src/git/hooks/useDiscard.ts create mode 100644 app/client/src/git/hooks/useMerge.ts create mode 100644 app/client/src/git/hooks/useOps.ts create mode 100644 app/client/src/git/hooks/usePull.ts create mode 100644 app/client/src/git/hooks/useStatus.ts diff --git a/app/client/src/git/components/ConflictErrorModal/index.tsx b/app/client/src/git/components/ConflictErrorModal/index.tsx index 0de96380c6d1..db9568836032 100644 --- a/app/client/src/git/components/ConflictErrorModal/index.tsx +++ b/app/client/src/git/components/ConflictErrorModal/index.tsx @@ -1,9 +1,9 @@ import React from "react"; import ConflictErrorModalView from "./ConflictErrorModalView"; -import { useGitContext } from "../GitContextProvider"; +import useOps from "git/hooks/useOps"; export default function ConflictErrorModal() { - const { conflictErrorModalOpen, toggleConflictErrorModal } = useGitContext(); + const { conflictErrorModalOpen, toggleConflictErrorModal } = useOps(); return ( { @@ -166,19 +169,19 @@ describe("ChooseGitProvider Component", () => { }); it("clicking on 'Import via git' link calls onImportFromCalloutLinkClick", () => { - const onImportFromCalloutLinkClick = jest.fn(); + const mockSetImportWorkspaceId = jest.fn(); render( , ); fireEvent.click(screen.getByText("Import via git")); - expect(onImportFromCalloutLinkClick).toHaveBeenCalledTimes(1); + expect(mockSetImportWorkspaceId).toHaveBeenCalledTimes(1); }); it("when isImport = true, shows a checkbox for existing repo", () => { @@ -215,7 +218,7 @@ describe("ChooseGitProvider Component", () => { render( , ); diff --git a/app/client/src/git/components/ConnectModal/ConnectInitialize/ChooseGitProvider.tsx b/app/client/src/git/components/ConnectModal/ConnectInitialize/ChooseGitProvider.tsx index 258b4b8d9c33..d24c31de20de 100644 --- a/app/client/src/git/components/ConnectModal/ConnectInitialize/ChooseGitProvider.tsx +++ b/app/client/src/git/components/ConnectModal/ConnectInitialize/ChooseGitProvider.tsx @@ -1,4 +1,4 @@ -import React, { useCallback } from "react"; +import React, { useCallback, useMemo } from "react"; import { DemoImage, FieldContainer, @@ -26,6 +26,7 @@ import { CHOOSE_A_GIT_PROVIDER_STEP, CHOOSE_GIT_PROVIDER_QUESTION, HOW_TO_CREATE_EMPTY_REPO, + IMPORT_ARTIFACT_IF_NOT_EMPTY, IS_EMPTY_REPO_QUESTION, I_HAVE_EXISTING_ARTIFACT_REPO, NEED_EMPTY_REPO_MESSAGE, @@ -33,6 +34,9 @@ import { } from "ee/constants/messages"; import log from "loglevel"; import type { ConnectFormDataState } from "./types"; +import history from "utils/history"; +import { useIsMobileDevice } from "utils/hooks/useDeviceDetect"; +import AnalyticsUtil from "ee/utils/AnalyticsUtil"; const WellInnerContainer = styled.div` padding-left: 16px; @@ -49,24 +53,24 @@ export type GitProvider = (typeof GIT_PROVIDERS)[number]; interface ChooseGitProviderProps { artifactType: string; + isCreateArtifactPermitted: boolean; + isImport?: boolean; onChange: (args: Partial) => void; + setImportWorkspaceId: () => void; + toggleConnectModal: (open: boolean) => void; value: Partial; - isImport?: boolean; - // isCreateArtifactPermitted: boolean; - // onImportFromCalloutLinkClick: () => void; } function ChooseGitProvider({ artifactType, + isCreateArtifactPermitted, isImport = false, onChange = noop, + setImportWorkspaceId = noop, + toggleConnectModal = noop, value = {}, - // isCreateArtifactPermitted, - // onImportFromCalloutLinkClick, }: ChooseGitProviderProps) { - // const isMobile = useIsMobileDevice(); - - // const hasCreateNewArtifactPermission = isCreateArtifactPermitted && !isMobile; + const isMobile = useIsMobileDevice(); const onGitProviderChange = useCallback( (value: string) => { @@ -93,11 +97,19 @@ function ChooseGitProvider({ [onChange], ); - // const importCalloutLinks = useMemo(() => { - // return hasCreateNewArtifactPermission - // ? [{ children: "Import via git", onClick: onImportFromCalloutLinkClick }] - // : []; - // }, [hasCreateNewArtifactPermission, onImportFromCalloutLinkClick]); + const handleClickOnImport = useCallback(() => { + toggleConnectModal(false); + history.push("/applications"); + setImportWorkspaceId(); + toggleConnectModal(true); + AnalyticsUtil.logEvent("GS_IMPORT_VIA_GIT_DURING_GC"); + }, [setImportWorkspaceId, toggleConnectModal]); + + const importCalloutLinks = useMemo(() => { + return !isMobile && isCreateArtifactPermitted + ? [{ children: "Import via git", onClick: handleClickOnImport }] + : []; + }, [handleClickOnImport, isCreateArtifactPermitted, isMobile]); return ( <> @@ -196,11 +208,11 @@ function ChooseGitProvider({ )} - {/* {!isImport && value?.gitEmptyRepoExists === "no" ? ( + {!isImport && value?.gitEmptyRepoExists === "no" ? ( {createMessage(IMPORT_ARTIFACT_IF_NOT_EMPTY, artifactType)} - ) : null} */} + ) : null} {isImport && ( void; gitImport: (params: GitImportRequestParams) => void; isConnectLoading: boolean; + isCreateArtifactPermitted: boolean; isFetchSSHKeyLoading: boolean; isGenerateSSHKeyLoading: boolean; isGitImportLoading: boolean; isImport: boolean; + setImportWorkspaceId: () => void; sshPublicKey: string | null; + toggleConnectModal: (open: boolean) => void; } function ConnectInitialize({ @@ -94,13 +97,14 @@ function ConnectInitialize({ generateSSHKey = noop, gitImport = noop, isConnectLoading = false, + isCreateArtifactPermitted = false, isFetchSSHKeyLoading = false, isGenerateSSHKeyLoading = false, isGitImportLoading = false, isImport = false, + setImportWorkspaceId = noop, sshPublicKey = null, - // isCreateArtifactPermitted = false, - // onImportFromCalloutLinkClick, + toggleConnectModal = noop, }: ConnectModalViewProps) { const nextStepText = { [GIT_CONNECT_STEPS.CHOOSE_PROVIDER]: createMessage(CONFIGURE_GIT), @@ -232,11 +236,12 @@ function ConnectInitialize({ {activeStep === GIT_CONNECT_STEPS.CHOOSE_PROVIDER && ( )} {activeStep === GIT_CONNECT_STEPS.GENERATE_SSH_KEY && ( diff --git a/app/client/src/git/components/ConnectModal/ConnectModalView.tsx b/app/client/src/git/components/ConnectModal/ConnectModalView.tsx index bd5b8b68172f..0146a5cf9237 100644 --- a/app/client/src/git/components/ConnectModal/ConnectModalView.tsx +++ b/app/client/src/git/components/ConnectModal/ConnectModalView.tsx @@ -44,6 +44,8 @@ interface ConnectModalViewProps { ) => void; defaultBranch: string | null; repoName: string | null; + setImportWorkspaceId: () => void; + isCreateArtifactPermitted: boolean; } function ConnectModalView({ @@ -86,7 +88,10 @@ function ConnectModalView({ toggleSettingsModal={toggleSettingsModal} /> ) : ( - + )} ) : null} diff --git a/app/client/src/git/components/ConnectModal/index.tsx b/app/client/src/git/components/ConnectModal/index.tsx index 0e1cc31894ab..a8f268132d95 100644 --- a/app/client/src/git/components/ConnectModal/index.tsx +++ b/app/client/src/git/components/ConnectModal/index.tsx @@ -10,7 +10,8 @@ interface ConnectModalProps { } function ConnectModal({ isImport = false }: ConnectModalProps) { - const { artifactDef } = useGitContext(); + const { artifactDef, isCreateArtifactPermitted, setImportWorkspaceId } = + useGitContext(); const { connect, connectError, @@ -47,6 +48,7 @@ function ConnectModal({ isImport = false }: ConnectModalProps) { gitImport={gitImport} isConnectLoading={isConnectLoading} isConnectModalOpen={isConnectModalOpen} + isCreateArtifactPermitted={isCreateArtifactPermitted} isFetchSSHKeyLoading={isFetchSSHKeyLoading} isGenerateSSHKeyLoading={isGenerateSSHKeyLoading} isGitConnected={isGitConnected} @@ -56,6 +58,7 @@ function ConnectModal({ isImport = false }: ConnectModalProps) { repoName={repoName} resetFetchSSHKey={resetFetchSSHKey} resetGenerateSSHKey={resetGenerateSSHKey} + setImportWorkspaceId={setImportWorkspaceId} sshPublicKey={sshPublicKey} toggleConnectModal={toggleConnectModal} toggleSettingsModal={toggleSettingsModal} diff --git a/app/client/src/git/components/GitContextProvider/hooks/useGitContextValue.ts b/app/client/src/git/components/GitContextProvider/hooks/useGitContextValue.ts deleted file mode 100644 index 35decfce1662..000000000000 --- a/app/client/src/git/components/GitContextProvider/hooks/useGitContextValue.ts +++ /dev/null @@ -1,56 +0,0 @@ -import type { GitArtifactType } from "git/constants/enums"; -import type { UseGitOpsReturnValue } from "./useGitOps"; -import useGitOps from "./useGitOps"; -import { useMemo } from "react"; - -// internal dependencies -import type { ApplicationPayload } from "entities/Application"; -import type { FetchStatusResponseData } from "git/requests/fetchStatusRequest.types"; -import type { StatusTreeStruct } from "git/components/StatusChanges/StatusTree"; - -export interface UseGitContextValueParams { - artifactType: keyof typeof GitArtifactType; - baseArtifactId: string; - artifact: ApplicationPayload | null; - statusTransformer: ( - status: FetchStatusResponseData, - ) => StatusTreeStruct[] | null; -} - -export interface GitContextValue extends UseGitOpsReturnValue { - artifactType: keyof typeof GitArtifactType; - baseArtifactId: string; - artifactDef: { - artifactType: keyof typeof GitArtifactType; - baseArtifactId: string; - }; - artifact: ApplicationPayload | null; - statusTransformer: ( - status: FetchStatusResponseData, - ) => StatusTreeStruct[] | null; -} - -export default function useGitContextValue({ - artifact, - artifactType, - baseArtifactId = "", - statusTransformer, -}: UseGitContextValueParams): GitContextValue { - const artifactDef = useMemo( - () => ({ artifactType, baseArtifactId }), - [artifactType, baseArtifactId], - ); - const useGitOpsReturnValue = useGitOps({ - ...artifactDef, - artifactId: artifact?.id ?? null, - }); - - return { - artifactType, - baseArtifactId, - artifactDef, - statusTransformer, - artifact, - ...useGitOpsReturnValue, - }; -} diff --git a/app/client/src/git/components/GitContextProvider/hooks/useGitOps.ts b/app/client/src/git/components/GitContextProvider/hooks/useGitOps.ts deleted file mode 100644 index 97b224f33717..000000000000 --- a/app/client/src/git/components/GitContextProvider/hooks/useGitOps.ts +++ /dev/null @@ -1,225 +0,0 @@ -import { GitOpsTab, type GitArtifactType } from "git/constants/enums"; -import type { FetchMergeStatusResponseData } from "git/requests/fetchMergeStatusRequest.types"; -import type { FetchStatusResponseData } from "git/requests/fetchStatusRequest.types"; -import { gitArtifactActions } from "git/store/gitArtifactSlice"; -import { - selectCommit, - selectConflictErrorModalOpen, - selectDiscard, - selectMerge, - selectMergeStatus, - selectOpsModalOpen, - selectOpsModalTab, - selectPull, - selectStatus, -} from "git/store/selectors/gitSingleArtifactSelectors"; -import type { GitApiError, GitRootState } from "git/store/types"; -import { useCallback, useMemo } from "react"; -import { useDispatch, useSelector } from "react-redux"; - -interface UseGitOpsParams { - artifactType: keyof typeof GitArtifactType; - baseArtifactId: string; - artifactId: string | null; -} - -export interface UseGitOpsReturnValue { - commitLoading: boolean; - commitError: GitApiError | null; - commit: (commitMessage: string) => void; - clearCommitError: () => void; - discardLoading: boolean; - discardError: GitApiError | null; - discard: () => void; - clearDiscardError: () => void; - status: FetchStatusResponseData | null; - fetchStatusLoading: boolean; - fetchStatusError: GitApiError | null; - fetchStatus: () => void; - mergeLoading: boolean; - mergeError: GitApiError | null; - merge: () => void; - mergeStatus: FetchMergeStatusResponseData | null; - fetchMergeStatusLoading: boolean; - fetchMergeStatusError: GitApiError | null; - fetchMergeStatus: (sourceBranch: string, destinationBranch: string) => void; - clearMergeStatus: () => void; - pullLoading: boolean; - pullError: GitApiError | null; - pull: () => void; - opsModalTab: keyof typeof GitOpsTab; - opsModalOpen: boolean; - toggleOpsModal: (open: boolean, tab?: keyof typeof GitOpsTab) => void; - conflictErrorModalOpen: boolean; - toggleConflictErrorModal: (open: boolean) => void; -} - -export default function useGitOps({ - artifactId, - artifactType, - baseArtifactId, -}: UseGitOpsParams): UseGitOpsReturnValue { - const dispatch = useDispatch(); - const basePayload = useMemo( - () => ({ artifactType, baseArtifactId }), - [artifactType, baseArtifactId], - ); - - // commit - const commitState = useSelector((state: GitRootState) => - selectCommit(state, basePayload), - ); - - const commit = useCallback( - (commitMessage: string) => { - dispatch( - gitArtifactActions.commitInit({ - ...basePayload, - commitMessage, - doPush: true, - }), - ); - }, - [basePayload, dispatch], - ); - - const clearCommitError = useCallback(() => { - dispatch(gitArtifactActions.clearCommitError(basePayload)); - }, [basePayload, dispatch]); - - // discard - const discardState = useSelector((state: GitRootState) => - selectDiscard(state, basePayload), - ); - - const discard = useCallback(() => { - dispatch(gitArtifactActions.discardInit(basePayload)); - }, [basePayload, dispatch]); - - const clearDiscardError = useCallback(() => { - dispatch(gitArtifactActions.clearDiscardError(basePayload)); - }, [basePayload, dispatch]); - - // status - const statusState = useSelector((state: GitRootState) => - selectStatus(state, basePayload), - ); - - const fetchStatus = useCallback(() => { - dispatch( - gitArtifactActions.fetchStatusInit({ - ...basePayload, - compareRemote: true, - }), - ); - }, [basePayload, dispatch]); - - // merge - const mergeState = useSelector((state: GitRootState) => - selectMerge(state, basePayload), - ); - - const merge = useCallback(() => { - dispatch(gitArtifactActions.mergeInit(basePayload)); - }, [basePayload, dispatch]); - - // merge status - const mergeStatusState = useSelector((state: GitRootState) => - selectMergeStatus(state, basePayload), - ); - - const fetchMergeStatus = useCallback( - (sourceBranch: string, destinationBranch: string) => { - dispatch( - gitArtifactActions.fetchMergeStatusInit({ - ...basePayload, - artifactId: artifactId ?? "", - sourceBranch, - destinationBranch, - }), - ); - }, - [artifactId, basePayload, dispatch], - ); - - const clearMergeStatus = useCallback(() => { - dispatch(gitArtifactActions.clearMergeStatus(basePayload)); - }, [basePayload, dispatch]); - - // pull - const pullState = useSelector((state: GitRootState) => - selectPull(state, basePayload), - ); - - const pull = useCallback(() => { - dispatch( - gitArtifactActions.pullInit({ - ...basePayload, - artifactId: artifactId ?? "", - }), - ); - }, [basePayload, artifactId, dispatch]); - - // ops modal - const opsModalOpen = useSelector((state: GitRootState) => - selectOpsModalOpen(state, basePayload), - ); - - const opsModalTab = useSelector((state: GitRootState) => - selectOpsModalTab(state, basePayload), - ); - - const toggleOpsModal = useCallback( - (open: boolean, tab: keyof typeof GitOpsTab = GitOpsTab.Deploy) => { - dispatch( - gitArtifactActions.toggleOpsModal({ ...basePayload, open, tab }), - ); - }, - [basePayload, dispatch], - ); - - // conflict error modal - const conflictErrorModalOpen = useSelector((state: GitRootState) => - selectConflictErrorModalOpen(state, basePayload), - ); - - const toggleConflictErrorModal = useCallback( - (open: boolean) => { - dispatch( - gitArtifactActions.toggleConflictErrorModal({ ...basePayload, open }), - ); - }, - [basePayload, dispatch], - ); - - return { - commitLoading: commitState?.loading ?? false, - commitError: commitState?.error, - commit, - clearCommitError, - discardLoading: discardState?.loading ?? false, - discardError: discardState?.error, - discard, - clearDiscardError, - status: statusState?.value, - fetchStatusLoading: statusState?.loading ?? false, - fetchStatusError: statusState?.error, - fetchStatus, - mergeLoading: mergeState?.loading ?? false, - mergeError: mergeState?.error, - merge, - mergeStatus: mergeStatusState?.value, - fetchMergeStatusLoading: mergeStatusState?.loading ?? false, - fetchMergeStatusError: mergeStatusState?.error, - fetchMergeStatus, - clearMergeStatus, - pullLoading: pullState?.loading ?? false, - pullError: pullState?.error, - pull, - opsModalTab, - opsModalOpen, - toggleOpsModal, - conflictErrorModalOpen, - toggleConflictErrorModal, - }; -} diff --git a/app/client/src/git/components/GitContextProvider/index.tsx b/app/client/src/git/components/GitContextProvider/index.tsx index 671f3b66a605..4d4b88b4f6ad 100644 --- a/app/client/src/git/components/GitContextProvider/index.tsx +++ b/app/client/src/git/components/GitContextProvider/index.tsx @@ -1,7 +1,22 @@ -import React, { createContext, useContext } from "react"; -import useGitContextValue from "./hooks/useGitContextValue"; -import type { UseGitContextValueParams } from "./hooks/useGitContextValue"; -import type { GitContextValue } from "./hooks/useGitContextValue"; +import React, { createContext, useCallback, useContext, useMemo } from "react"; +import type { GitArtifactType } from "git/constants/enums"; +import type { ApplicationPayload } from "entities/Application"; +import type { FetchStatusResponseData } from "git/requests/fetchStatusRequest.types"; +import type { StatusTreeStruct } from "../StatusChanges/StatusTree"; +import { useDispatch } from "react-redux"; + +export interface GitContextValue { + artifactDef: { + artifactType: keyof typeof GitArtifactType; + baseArtifactId: string; + }; + artifact: ApplicationPayload | null; + statusTransformer: ( + status: FetchStatusResponseData, + ) => StatusTreeStruct[] | null; + setImportWorkspaceId: () => void; + isCreateArtifactPermitted: boolean; +} const gitContextInitialValue = {} as GitContextValue; @@ -11,15 +26,65 @@ export const useGitContext = () => { return useContext(GitContext); }; -interface GitContextProviderProps extends UseGitContextValueParams { +interface GitContextProviderProps { + artifactType: keyof typeof GitArtifactType; + baseArtifactId: string; + artifact: ApplicationPayload | null; + isCreateArtifactPermitted: boolean; + setWorkspaceIdForImport: (params: { + workspaceId: string; + editorId: string; + }) => void; + statusTransformer: ( + status: FetchStatusResponseData, + ) => StatusTreeStruct[] | null; children: React.ReactNode; } export default function GitContextProvider({ + artifact = null, + artifactType, + baseArtifactId, children, - ...useContextValueParams + isCreateArtifactPermitted, + setWorkspaceIdForImport, + statusTransformer, }: GitContextProviderProps) { - const contextValue = useGitContextValue(useContextValueParams); + const artifactDef = useMemo( + () => ({ artifactType, baseArtifactId }), + [artifactType, baseArtifactId], + ); + + const dispatch = useDispatch(); + + const { id: artifactId, workspaceId } = artifact ?? {}; + const setImportWorkspaceId = useCallback(() => { + if (workspaceId) { + dispatch( + setWorkspaceIdForImport({ + workspaceId: workspaceId ?? "", + editorId: artifactId ?? "", + }), + ); + } + }, [artifactId, dispatch, setWorkspaceIdForImport, workspaceId]); + + const contextValue: GitContextValue = useMemo( + () => ({ + artifactDef, + artifact, + statusTransformer, + isCreateArtifactPermitted, + setImportWorkspaceId, + }), + [ + artifactDef, + artifact, + statusTransformer, + isCreateArtifactPermitted, + setImportWorkspaceId, + ], + ); return ( {children} diff --git a/app/client/src/git/components/OpsModal/TabDeploy/index.tsx b/app/client/src/git/components/OpsModal/TabDeploy/index.tsx index 5c7fcf774aac..44bd8ee91cd2 100644 --- a/app/client/src/git/components/OpsModal/TabDeploy/index.tsx +++ b/app/client/src/git/components/OpsModal/TabDeploy/index.tsx @@ -3,24 +3,21 @@ import TabDeployView from "./TabDeployView"; import { useGitContext } from "git/components/GitContextProvider"; import useMetadata from "git/hooks/useMetadata"; import useBranches from "git/hooks/useBranches"; +import useCommit from "git/hooks/useCommit"; +import useDiscard from "git/hooks/useDiscard"; +import usePull from "git/hooks/usePull"; +import useStatus from "git/hooks/useStatus"; export default function TabDeploy() { - const { - artifact, - clearCommitError, - clearDiscardError, - commit, - commitError, - commitLoading, - discard, - discardError, - discardLoading, - fetchStatusLoading, - pull, - pullError, - pullLoading, - status, - } = useGitContext(); + const { artifact } = useGitContext(); + const { clearCommitError, commit, commitError, isCommitLoading } = + useCommit(); + + const { clearDiscardError, discard, discardError, isDiscardLoading } = + useDiscard(); + + const { isPullLoading, pull, pullError } = usePull(); + const { isFetchStatusLoading, status } = useStatus(); const { currentBranch } = useBranches(); const { metadata } = useMetadata(); @@ -39,11 +36,11 @@ export default function TabDeploy() { currentBranch={currentBranch} discard={discard} discardError={discardError} - isCommitLoading={commitLoading} - isDiscardLoading={discardLoading} - isFetchStatusLoading={fetchStatusLoading} + isCommitLoading={isCommitLoading} + isDiscardLoading={isDiscardLoading} + isFetchStatusLoading={isFetchStatusLoading} isPullFailing={isPullFailing} - isPullLoading={pullLoading} + isPullLoading={isPullLoading} lastDeployedAt={lastDeployedAt} pull={pull} remoteUrl={remoteUrl} diff --git a/app/client/src/git/components/OpsModal/TabMerge/index.tsx b/app/client/src/git/components/OpsModal/TabMerge/index.tsx index 47350adc597d..370ab874727e 100644 --- a/app/client/src/git/components/OpsModal/TabMerge/index.tsx +++ b/app/client/src/git/components/OpsModal/TabMerge/index.tsx @@ -1,21 +1,21 @@ import React from "react"; import TabMergeView from "./TabMergeView"; -import { useGitContext } from "git/components/GitContextProvider"; import useProtectedBranches from "git/hooks/useProtectedBranches"; import useBranches from "git/hooks/useBranches"; +import useMerge from "git/hooks/useMerge"; +import useStatus from "git/hooks/useStatus"; export default function TabMerge() { const { clearMergeStatus, fetchMergeStatus, - fetchMergeStatusLoading, - fetchStatusLoading, + isFetchMergeStatusLoading, + isMergeLoading, merge, mergeError, - mergeLoading, mergeStatus, - status, - } = useGitContext(); + } = useMerge(); + const { isFetchStatusLoading, status } = useStatus(); const { branches, currentBranch, fetchBranches, fetchBranchesLoading } = useBranches(); const { protectedBranches } = useProtectedBranches(); @@ -30,9 +30,9 @@ export default function TabMerge() { fetchBranches={fetchBranches} fetchMergeStatus={fetchMergeStatus} isFetchBranchesLoading={fetchBranchesLoading} - isFetchMergeStatusLoading={fetchMergeStatusLoading} - isFetchStatusLoading={fetchStatusLoading} - isMergeLoading={mergeLoading} + isFetchMergeStatusLoading={isFetchMergeStatusLoading} + isFetchStatusLoading={isFetchStatusLoading} + isMergeLoading={isMergeLoading} isStatusClean={isStatusClean} merge={merge} mergeError={mergeError} diff --git a/app/client/src/git/components/OpsModal/index.tsx b/app/client/src/git/components/OpsModal/index.tsx index 1450d74cf7e8..114439c29902 100644 --- a/app/client/src/git/components/OpsModal/index.tsx +++ b/app/client/src/git/components/OpsModal/index.tsx @@ -1,12 +1,13 @@ import React from "react"; import OpsModalView from "./OpsModalView"; -import { useGitContext } from "../GitContextProvider"; import useProtectedBranches from "git/hooks/useProtectedBranches"; import useMetadata from "git/hooks/useMetadata"; +import useStatus from "git/hooks/useStatus"; +import useOps from "git/hooks/useOps"; export default function OpsModal() { - const { fetchStatus, opsModalOpen, opsModalTab, toggleOpsModal } = - useGitContext(); + const { opsModalOpen, opsModalTab, toggleOpsModal } = useOps(); + const { fetchStatus } = useStatus(); const { isProtectedMode } = useProtectedBranches(); const { metadata } = useMetadata(); diff --git a/app/client/src/git/components/QuickActions/index.tsx b/app/client/src/git/components/QuickActions/index.tsx index be617d5e8af4..cb4b6a5624d1 100644 --- a/app/client/src/git/components/QuickActions/index.tsx +++ b/app/client/src/git/components/QuickActions/index.tsx @@ -1,6 +1,5 @@ import React from "react"; import QuickActionsView from "./QuickActionsView"; -import { useGitContext } from "../GitContextProvider"; import useStatusChangeCount from "./hooks/useStatusChangeCount"; import useProtectedBranches from "git/hooks/useProtectedBranches"; import useGitPermissions from "git/hooks/useGitPermissions"; @@ -8,18 +7,16 @@ import useAutocommit from "git/hooks/useAutocommit"; import useSettings from "git/hooks/useSettings"; import useMetadata from "git/hooks/useMetadata"; import useConnect from "git/hooks/useConnect"; +import useDiscard from "git/hooks/useDiscard"; +import usePull from "git/hooks/usePull"; +import useStatus from "git/hooks/useStatus"; +import useOps from "git/hooks/useOps"; function QuickActions() { - const { - discard, - discardLoading, - fetchStatusLoading, - pull, - pullError, - pullLoading, - status, - toggleOpsModal, - } = useGitContext(); + const { toggleOpsModal } = useOps(); + const { isFetchStatusLoading, status } = useStatus(); + const { isPullLoading, pull, pullError } = usePull(); + const { discard, isDiscardLoading } = useDiscard(); const { isGitConnected } = useMetadata(); const { isProtectedMode } = useProtectedBranches(); const { isConnectPermitted } = useGitPermissions(); @@ -38,12 +35,12 @@ function QuickActions() { isAutocommitEnabled={isAutocommitEnabled} isAutocommitPolling={isAutocommitPolling} isConnectPermitted={isConnectPermitted} - isDiscardLoading={discardLoading} - isFetchStatusLoading={fetchStatusLoading} + isDiscardLoading={isDiscardLoading} + isFetchStatusLoading={isFetchStatusLoading} isGitConnected={isGitConnected} isProtectedMode={isProtectedMode} isPullFailing={isPullFailing} - isPullLoading={pullLoading} + isPullLoading={isPullLoading} isStatusClean={isStatusClean} pull={pull} statusBehindCount={statusBehindCount} diff --git a/app/client/src/git/components/StatusChanges/index.tsx b/app/client/src/git/components/StatusChanges/index.tsx index 05b8e280189b..fc39867932f8 100644 --- a/app/client/src/git/components/StatusChanges/index.tsx +++ b/app/client/src/git/components/StatusChanges/index.tsx @@ -1,13 +1,15 @@ import React from "react"; import { useGitContext } from "../GitContextProvider"; import StatusChangesView from "./StatusChangesView"; +import useStatus from "git/hooks/useStatus"; function StatusChanges() { - const { fetchStatusLoading, status, statusTransformer } = useGitContext(); + const { statusTransformer } = useGitContext(); + const { isFetchStatusLoading, status } = useStatus(); return ( diff --git a/app/client/src/git/hooks/useCommit.ts b/app/client/src/git/hooks/useCommit.ts new file mode 100644 index 000000000000..56f78cc11bcd --- /dev/null +++ b/app/client/src/git/hooks/useCommit.ts @@ -0,0 +1,39 @@ +import { useGitContext } from "git/components/GitContextProvider"; +import { gitArtifactActions } from "git/store/gitArtifactSlice"; +import { selectCommitState } from "git/store/selectors/gitSingleArtifactSelectors"; +import type { GitRootState } from "git/store/types"; +import { useCallback } from "react"; +import { useDispatch, useSelector } from "react-redux"; + +export default function useCommit() { + const { artifactDef } = useGitContext(); + const dispatch = useDispatch(); + + const commitState = useSelector((state: GitRootState) => + selectCommitState(state, artifactDef), + ); + + const commit = useCallback( + (commitMessage: string) => { + dispatch( + gitArtifactActions.commitInit({ + ...artifactDef, + commitMessage, + doPush: true, + }), + ); + }, + [artifactDef, dispatch], + ); + + const clearCommitError = useCallback(() => { + dispatch(gitArtifactActions.clearCommitError(artifactDef)); + }, [artifactDef, dispatch]); + + return { + isCommitLoading: commitState?.loading ?? false, + commitError: commitState?.error, + commit, + clearCommitError, + }; +} diff --git a/app/client/src/git/hooks/useDiscard.ts b/app/client/src/git/hooks/useDiscard.ts new file mode 100644 index 000000000000..2f71c11608f9 --- /dev/null +++ b/app/client/src/git/hooks/useDiscard.ts @@ -0,0 +1,30 @@ +import { useGitContext } from "git/components/GitContextProvider"; +import { gitArtifactActions } from "git/store/gitArtifactSlice"; +import { selectDiscardState } from "git/store/selectors/gitSingleArtifactSelectors"; +import type { GitRootState } from "git/store/types"; +import { useCallback } from "react"; +import { useDispatch, useSelector } from "react-redux"; + +export default function useDiscard() { + const { artifactDef } = useGitContext(); + const dispatch = useDispatch(); + + const discardState = useSelector((state: GitRootState) => + selectDiscardState(state, artifactDef), + ); + + const discard = useCallback(() => { + dispatch(gitArtifactActions.discardInit(artifactDef)); + }, [artifactDef, dispatch]); + + const clearDiscardError = useCallback(() => { + dispatch(gitArtifactActions.clearDiscardError(artifactDef)); + }, [artifactDef, dispatch]); + + return { + isDiscardLoading: discardState?.loading ?? false, + discardError: discardState?.error ?? null, + discard, + clearDiscardError, + }; +} diff --git a/app/client/src/git/hooks/useMerge.ts b/app/client/src/git/hooks/useMerge.ts new file mode 100644 index 000000000000..f7394601b191 --- /dev/null +++ b/app/client/src/git/hooks/useMerge.ts @@ -0,0 +1,58 @@ +import { useGitContext } from "git/components/GitContextProvider"; +import { gitArtifactActions } from "git/store/gitArtifactSlice"; +import { + selectMergeState, + selectMergeStatusState, +} from "git/store/selectors/gitSingleArtifactSelectors"; +import type { GitRootState } from "git/store/types"; +import { useCallback } from "react"; +import { useDispatch, useSelector } from "react-redux"; + +export default function useMerge() { + const { artifact, artifactDef } = useGitContext(); + const artifactId = artifact?.id; + const dispatch = useDispatch(); + + // merge + const mergeState = useSelector((state: GitRootState) => + selectMergeState(state, artifactDef), + ); + + const merge = useCallback(() => { + dispatch(gitArtifactActions.mergeInit(artifactDef)); + }, [artifactDef, dispatch]); + + // merge status + const mergeStatusState = useSelector((state: GitRootState) => + selectMergeStatusState(state, artifactDef), + ); + + const fetchMergeStatus = useCallback( + (sourceBranch: string, destinationBranch: string) => { + dispatch( + gitArtifactActions.fetchMergeStatusInit({ + ...artifactDef, + artifactId: artifactId ?? "", + sourceBranch, + destinationBranch, + }), + ); + }, + [artifactId, artifactDef, dispatch], + ); + + const clearMergeStatus = useCallback(() => { + dispatch(gitArtifactActions.clearMergeStatus(artifactDef)); + }, [artifactDef, dispatch]); + + return { + isMergeLoading: mergeState?.loading ?? false, + mergeError: mergeState?.error, + merge, + mergeStatus: mergeStatusState?.value, + isFetchMergeStatusLoading: mergeStatusState?.loading ?? false, + fetchMergeStatusError: mergeStatusState?.error, + fetchMergeStatus, + clearMergeStatus, + }; +} diff --git a/app/client/src/git/hooks/useMetadata.ts b/app/client/src/git/hooks/useMetadata.ts index 15ed4346dea3..9bd5356ad763 100644 --- a/app/client/src/git/hooks/useMetadata.ts +++ b/app/client/src/git/hooks/useMetadata.ts @@ -18,9 +18,9 @@ export default function useMetadata() { ); return { - metadata: metadataState.value ?? null, - isFetchMetadataLoading: metadataState.loading ?? false, - fetchMetadataError: metadataState.error ?? null, + metadata: metadataState?.value ?? null, + isFetchMetadataLoading: metadataState?.loading ?? false, + fetchMetadataError: metadataState?.error ?? null, isGitConnected, }; } diff --git a/app/client/src/git/hooks/useOps.ts b/app/client/src/git/hooks/useOps.ts new file mode 100644 index 000000000000..32eec997cf25 --- /dev/null +++ b/app/client/src/git/hooks/useOps.ts @@ -0,0 +1,57 @@ +import { useGitContext } from "git/components/GitContextProvider"; +import { GitOpsTab } from "git/constants/enums"; +import { gitArtifactActions } from "git/store/gitArtifactSlice"; +import { + selectConflictErrorModalOpen, + selectOpsModalOpen, + selectOpsModalTab, +} from "git/store/selectors/gitSingleArtifactSelectors"; +import type { GitRootState } from "git/store/types"; +import { useCallback } from "react"; +import { useDispatch, useSelector } from "react-redux"; + +export default function useOps() { + const { artifactDef } = useGitContext(); + + const dispatch = useDispatch(); + + // ops modal + const opsModalOpen = useSelector((state: GitRootState) => + selectOpsModalOpen(state, artifactDef), + ); + + const opsModalTab = useSelector((state: GitRootState) => + selectOpsModalTab(state, artifactDef), + ); + + const toggleOpsModal = useCallback( + (open: boolean, tab: keyof typeof GitOpsTab = GitOpsTab.Deploy) => { + dispatch( + gitArtifactActions.toggleOpsModal({ ...artifactDef, open, tab }), + ); + }, + [artifactDef, dispatch], + ); + + // conflict error modal + const conflictErrorModalOpen = useSelector((state: GitRootState) => + selectConflictErrorModalOpen(state, artifactDef), + ); + + const toggleConflictErrorModal = useCallback( + (open: boolean) => { + dispatch( + gitArtifactActions.toggleConflictErrorModal({ ...artifactDef, open }), + ); + }, + [artifactDef, dispatch], + ); + + return { + opsModalTab, + opsModalOpen, + toggleOpsModal, + conflictErrorModalOpen, + toggleConflictErrorModal, + }; +} diff --git a/app/client/src/git/hooks/usePull.ts b/app/client/src/git/hooks/usePull.ts new file mode 100644 index 000000000000..992866f2c277 --- /dev/null +++ b/app/client/src/git/hooks/usePull.ts @@ -0,0 +1,31 @@ +import { useGitContext } from "git/components/GitContextProvider"; +import { gitArtifactActions } from "git/store/gitArtifactSlice"; +import { selectPullState } from "git/store/selectors/gitSingleArtifactSelectors"; +import type { GitRootState } from "git/store/types"; +import { useCallback } from "react"; +import { useDispatch, useSelector } from "react-redux"; + +export default function usePull() { + const { artifact, artifactDef } = useGitContext(); + const artifactId = artifact?.id; + const dispatch = useDispatch(); + + const pullState = useSelector((state: GitRootState) => + selectPullState(state, artifactDef), + ); + + const pull = useCallback(() => { + dispatch( + gitArtifactActions.pullInit({ + ...artifactDef, + artifactId: artifactId ?? "", + }), + ); + }, [artifactDef, artifactId, dispatch]); + + return { + isPullLoading: pullState?.loading ?? false, + pullError: pullState?.error, + pull, + }; +} diff --git a/app/client/src/git/hooks/useStatus.ts b/app/client/src/git/hooks/useStatus.ts new file mode 100644 index 000000000000..97b09b57498a --- /dev/null +++ b/app/client/src/git/hooks/useStatus.ts @@ -0,0 +1,31 @@ +import { useGitContext } from "git/components/GitContextProvider"; +import { gitArtifactActions } from "git/store/gitArtifactSlice"; +import { selectStatusState } from "git/store/selectors/gitSingleArtifactSelectors"; +import type { GitRootState } from "git/store/types"; +import { useCallback } from "react"; +import { useDispatch, useSelector } from "react-redux"; + +export default function useStatus() { + const { artifactDef } = useGitContext(); + const dispatch = useDispatch(); + + const statusState = useSelector((state: GitRootState) => + selectStatusState(state, artifactDef), + ); + + const fetchStatus = useCallback(() => { + dispatch( + gitArtifactActions.fetchStatusInit({ + ...artifactDef, + compareRemote: true, + }), + ); + }, [artifactDef, dispatch]); + + return { + status: statusState?.value, + isFetchStatusLoading: statusState?.loading ?? false, + fetchStatusError: statusState?.error, + fetchStatus, + }; +} diff --git a/app/client/src/git/store/selectors/gitSingleArtifactSelectors.ts b/app/client/src/git/store/selectors/gitSingleArtifactSelectors.ts index 5ee245f7b49e..1bdbcf310ac1 100644 --- a/app/client/src/git/store/selectors/gitSingleArtifactSelectors.ts +++ b/app/client/src/git/store/selectors/gitSingleArtifactSelectors.ts @@ -68,31 +68,35 @@ export const selectDisconnectArtifactName = ( ) => selectGitArtifact(state, artifactDef)?.ui.disconnectArtifactName; // git ops -export const selectCommit = ( +export const selectCommitState = ( state: GitRootState, artifactDef: GitArtifactDef, ) => selectGitArtifact(state, artifactDef)?.apiResponses?.commit; -export const selectDiscard = ( +export const selectDiscardState = ( state: GitRootState, artifactDef: GitArtifactDef, ) => selectGitArtifact(state, artifactDef)?.apiResponses?.discard; -export const selectStatus = ( +export const selectStatusState = ( state: GitRootState, artifactDef: GitArtifactDef, ) => selectGitArtifact(state, artifactDef)?.apiResponses?.status; -export const selectMerge = (state: GitRootState, artifactDef: GitArtifactDef) => - selectGitArtifact(state, artifactDef)?.apiResponses?.merge; +export const selectMergeState = ( + state: GitRootState, + artifactDef: GitArtifactDef, +) => selectGitArtifact(state, artifactDef)?.apiResponses?.merge; -export const selectMergeStatus = ( +export const selectMergeStatusState = ( state: GitRootState, artifactDef: GitArtifactDef, ) => selectGitArtifact(state, artifactDef)?.apiResponses?.mergeStatus; -export const selectPull = (state: GitRootState, artifactDef: GitArtifactDef) => - selectGitArtifact(state, artifactDef)?.apiResponses?.pull; +export const selectPullState = ( + state: GitRootState, + artifactDef: GitArtifactDef, +) => selectGitArtifact(state, artifactDef)?.apiResponses?.pull; export const selectOpsModalOpen = ( state: GitRootState, From 5e40b1091282f2ed461fc94ed907450a0dd5337a Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Mon, 16 Dec 2024 01:50:10 +0800 Subject: [PATCH 068/143] chore: review comment fix --- .../LocalProfile/LocalProfileView.tsx | 2 +- .../TabContinuousDelivery/index.tsx | 4 ++-- .../src/git/hooks/useProtectedBranches.ts | 24 +++++++++++-------- 3 files changed, 17 insertions(+), 13 deletions(-) diff --git a/app/client/src/git/components/LocalProfile/LocalProfileView.tsx b/app/client/src/git/components/LocalProfile/LocalProfileView.tsx index beefbb66b29f..03c027824cb3 100644 --- a/app/client/src/git/components/LocalProfile/LocalProfileView.tsx +++ b/app/client/src/git/components/LocalProfile/LocalProfileView.tsx @@ -277,7 +277,7 @@ function LocalProfileView({ {...register("authorName", { required: createMessage(AUTHOR_NAME_CANNOT_BE_EMPTY), })} - onChange={handleInputChange("authorEmail")} + onChange={handleInputChange("authorName")} /> ) : ( diff --git a/app/client/src/git/components/SettingsModal/TabContinuousDelivery/index.tsx b/app/client/src/git/components/SettingsModal/TabContinuousDelivery/index.tsx index ebfa3f6d17b9..b57d6690e9b7 100644 --- a/app/client/src/git/components/SettingsModal/TabContinuousDelivery/index.tsx +++ b/app/client/src/git/components/SettingsModal/TabContinuousDelivery/index.tsx @@ -1,8 +1,8 @@ import React from "react"; import ContinuousDelivery from "git/components/ContinuousDelivery"; -function TabContinuosDelivery() { +function TabContinuousDelivery() { return ; } -export default TabContinuosDelivery; +export default TabContinuousDelivery; diff --git a/app/client/src/git/hooks/useProtectedBranches.ts b/app/client/src/git/hooks/useProtectedBranches.ts index 3d26df24066e..fa3b2ef89307 100644 --- a/app/client/src/git/hooks/useProtectedBranches.ts +++ b/app/client/src/git/hooks/useProtectedBranches.ts @@ -6,6 +6,7 @@ import { selectUpdateProtectedBranchesState, } from "git/store/selectors/gitSingleArtifactSelectors"; import type { GitRootState } from "git/store/types"; +import { useCallback } from "react"; import { useDispatch, useSelector } from "react-redux"; function useProtectedBranches() { @@ -17,22 +18,25 @@ function useProtectedBranches() { selectFetchProtectedBranchesState(state, artifactDef), ); - const fetchProtectedBranches = () => { + const fetchProtectedBranches = useCallback(() => { dispatch(gitArtifactActions.fetchProtectedBranchesInit(artifactDef)); - }; + }, [dispatch, artifactDef]); const updateProtectedBranchesState = useSelector((state: GitRootState) => selectUpdateProtectedBranchesState(state, artifactDef), ); - const updateProtectedBranches = (branches: string[]) => { - dispatch( - gitArtifactActions.updateProtectedBranchesInit({ - ...artifactDef, - branchNames: branches, - }), - ); - }; + const updateProtectedBranches = useCallback( + (branches: string[]) => { + dispatch( + gitArtifactActions.updateProtectedBranchesInit({ + ...artifactDef, + branchNames: branches, + }), + ); + }, + [dispatch, artifactDef], + ); const isProtectedMode = useSelector((state: GitRootState) => selectProtectedMode(state, artifactDef), From 3921112cddaafa2add14a46124fec9307fd77002 Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Mon, 16 Dec 2024 05:08:05 +0800 Subject: [PATCH 069/143] chore: adding branch popup --- .../BranchList/BranchListHotKeys.tsx | 86 ++++ .../BranchList/BranchListItemContainer.tsx | 37 ++ .../components/BranchList/BranchListView.tsx | 427 ++++++++++++++++++ .../components/BranchList/BranchMoreMenu.tsx | 132 ++++++ .../components/BranchList/LocalBranchList.tsx | 75 +++ .../BranchList/LocalBranchListItem.tsx | 135 ++++++ .../BranchList/RemoteBranchList.tsx | 47 ++ .../BranchList/RemoteBranchListItem.tsx | 74 +++ .../BranchList/hooks/useActiveHoverIndex.ts | 43 ++ .../BranchList/hooks/useFilteredBranches.ts | 29 ++ .../components/BranchList/hooks/useHover.ts | 24 + .../src/git/components/BranchList/index.tsx | 49 ++ .../components/OpsModal/TabMerge/index.tsx | 4 +- .../index.tsx => BranchButton.tsx} | 51 +-- .../QuickActions/BranchButton/BranchList.tsx | 5 - .../QuickActions/QuickActionsView.test.tsx | 4 + .../QuickActions/QuickActionsView.tsx | 22 +- .../src/git/components/QuickActions/index.tsx | 12 +- app/client/src/git/constants/enums.ts | 12 - app/client/src/git/hooks/useAutocommit.ts | 7 + app/client/src/git/hooks/useBranches.ts | 65 ++- .../src/git/sagas/checkoutBranchSaga.ts | 2 +- app/client/src/git/sagas/createBranchSaga.ts | 6 + app/client/src/git/sagas/index.ts | 6 + .../store/actions/checkoutBranchActions.ts | 6 +- .../actions/repoLimitErrorModalActions.ts | 2 +- app/client/src/git/store/actions/uiActions.ts | 10 +- app/client/src/git/store/gitArtifactSlice.ts | 4 +- .../helpers/gitSingleArtifactInitialState.ts | 19 +- .../selectors/gitSingleArtifactSelectors.ts | 23 +- app/client/src/git/store/types.ts | 14 +- 31 files changed, 1318 insertions(+), 114 deletions(-) create mode 100644 app/client/src/git/components/BranchList/BranchListHotKeys.tsx create mode 100644 app/client/src/git/components/BranchList/BranchListItemContainer.tsx create mode 100644 app/client/src/git/components/BranchList/BranchListView.tsx create mode 100644 app/client/src/git/components/BranchList/BranchMoreMenu.tsx create mode 100644 app/client/src/git/components/BranchList/LocalBranchList.tsx create mode 100644 app/client/src/git/components/BranchList/LocalBranchListItem.tsx create mode 100644 app/client/src/git/components/BranchList/RemoteBranchList.tsx create mode 100644 app/client/src/git/components/BranchList/RemoteBranchListItem.tsx create mode 100644 app/client/src/git/components/BranchList/hooks/useActiveHoverIndex.ts create mode 100644 app/client/src/git/components/BranchList/hooks/useFilteredBranches.ts create mode 100644 app/client/src/git/components/BranchList/hooks/useHover.ts create mode 100644 app/client/src/git/components/BranchList/index.tsx rename app/client/src/git/components/QuickActions/{BranchButton/index.tsx => BranchButton.tsx} (75%) delete mode 100644 app/client/src/git/components/QuickActions/BranchButton/BranchList.tsx diff --git a/app/client/src/git/components/BranchList/BranchListHotKeys.tsx b/app/client/src/git/components/BranchList/BranchListHotKeys.tsx new file mode 100644 index 000000000000..65055ebf3265 --- /dev/null +++ b/app/client/src/git/components/BranchList/BranchListHotKeys.tsx @@ -0,0 +1,86 @@ +import React from "react"; +import { Hotkey, Hotkeys, HotkeysTarget } from "@blueprintjs/core"; + +interface Props { + handleUpKey: () => void; + handleDownKey: () => void; + handleSubmitKey: () => void; + handleEscKey: () => void; + children: React.ReactNode; +} + +@HotkeysTarget +class GlobalSearchHotKeys extends React.Component { + get hotKeysConfig() { + return [ + { + combo: "up", + onKeyDown: () => { + this.props.handleUpKey(); + }, + allowInInput: true, + group: "Branches", + label: "Move up the list", + }, + { + combo: "down", + onKeyDown: this.props.handleDownKey, + allowInInput: true, + group: "Branches", + label: "Move down the list", + }, + { + combo: "return", + onKeyDown: this.props.handleSubmitKey, + allowInInput: true, + group: "Branches", + label: "Submit", + }, + { + combo: "ESC", + onKeyDown: this.props.handleEscKey, + allowInInput: true, + group: "Branches", + label: "ESC", + }, + ]; + } + + renderHotkeys() { + return ( + + {this.hotKeysConfig.map( + ({ allowInInput, combo, group, label, onKeyDown }, index) => ( + + ), + )} + + ); + } + + render() { + return ( +
+ {this.props.children} +
+ ); + } +} + +export default GlobalSearchHotKeys; diff --git a/app/client/src/git/components/BranchList/BranchListItemContainer.tsx b/app/client/src/git/components/BranchList/BranchListItemContainer.tsx new file mode 100644 index 000000000000..510e834e7bb7 --- /dev/null +++ b/app/client/src/git/components/BranchList/BranchListItemContainer.tsx @@ -0,0 +1,37 @@ +import styled from "styled-components"; + +const BranchListItemContainer = styled.div<{ + isSelected?: boolean; + isActive?: boolean; + isDefault?: boolean; +}>` + padding: ${(props) => `${props.theme.spaces[4]}px`}; + margin: ${(props) => `${props.theme.spaces[1]}px 0`}; + color: var(--ads-v2-color-fg-emphasis); + cursor: pointer; + width: 100%; + height: 36px; + border-radius: var(--ads-v2-border-radius); + background-color: ${(props) => + props.isSelected || props.isActive ? "var(--ads-v2-color-bg-muted)" : ""}; + ${(props) => + !props.isActive && + `&:hover { + background-color: var(--ads-v2-color-bg-subtle); + }`} + + display: flex; + align-items: center; + + .branch-list-item-text { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + display: flex; + align-items: center; + gap: 4px; + flex: 1; + } +`; + +export default BranchListItemContainer; diff --git a/app/client/src/git/components/BranchList/BranchListView.tsx b/app/client/src/git/components/BranchList/BranchListView.tsx new file mode 100644 index 000000000000..53064528888d --- /dev/null +++ b/app/client/src/git/components/BranchList/BranchListView.tsx @@ -0,0 +1,427 @@ +import React, { useCallback, useEffect, useMemo, useState } from "react"; +import { getTypographyByKey } from "@appsmith/ads-old"; +import styled, { useTheme } from "styled-components"; +import Skeleton from "components/utils/Skeleton"; +import scrollIntoView from "scroll-into-view-if-needed"; +import BranchListHotkeys from "./BranchListHotKeys"; +import { + createMessage, + FIND_OR_CREATE_A_BRANCH, + SWITCH_BRANCHES, + SYNC_BRANCHES, +} from "ee/constants/messages"; +import { + Icon, + Spinner, + Tooltip, + Button, + SearchInput, + Text, +} from "@appsmith/ads"; +import get from "lodash/get"; +import noop from "lodash/noop"; +import { + isLocalBranch, + isRemoteBranch, + removeSpecialChars, +} from "pages/Editor/gitSync/utils"; +import AnalyticsUtil from "ee/utils/AnalyticsUtil"; +import RemoteBranchList from "./RemoteBranchList"; +import type { Theme } from "constants/DefaultTheme"; +import BranchListItemContainer from "./BranchListItemContainer"; +import LocalBranchList from "./LocalBranchList"; +import { useFilteredBranches } from "./hooks/useFilteredBranches"; +import useActiveHoverIndex from "./hooks/useActiveHoverIndex"; +import { Space } from "pages/Editor/gitSync/components/StyledComponents"; +import type { FetchBranchesResponseData } from "git/requests/fetchBranchesRequest.types"; +import type { FetchProtectedBranchesResponseData } from "git/requests/fetchProtectedBranchesRequest.types"; + +const ListContainer = styled.div` + flex: 1; + overflow: auto; + width: calc(300px + 5px); + margin-right: -5px; + position: relative; +`; + +const BranchDropdownContainer = styled.div` + height: 45vh; + display: flex; + flex-direction: column; + + padding: ${(props) => props.theme.spaces[5]}px; + min-height: 0; +`; + +// used for skeletons +const textInputHeight = 38; +const textHeight = 18; + +const CreateNewBranchContainer = styled.div` + display: -webkit-box; + -webkit-line-clamp: 3; + -webkit-box-orient: vertical; + overflow: hidden; + margin-right: 4px; + + & div { + margin-left: ${(props) => props.theme.spaces[4]}px; + display: block; + word-break: break-all; + } + + & .large-text { + ${getTypographyByKey("p1")}; + color: var(--ads-v2-color-fg); + } + + & .small-text { + ${getTypographyByKey("p3")}; + color: var(--ads-v2-color-fg-muted); + } +`; + +const SpinnerContainer = styled.div<{ isCreateBranchLoading: boolean }>` + align-self: center; + width: 12px; + visibility: ${(props) => + props.isCreateBranchLoading ? "visible" : "hidden"}; +`; + +interface CreateNewBranchProps { + branch: string; + className: string; + currentBranch: string | null; + hovered: boolean; + isCreateBranchLoading: boolean; + onClick: () => void; + shouldScrollIntoView: boolean; +} + +function CreateNewBranch({ + branch, + className, + currentBranch, + hovered, + isCreateBranchLoading, + onClick, + shouldScrollIntoView, +}: CreateNewBranchProps) { + useEffect( + function onInitEffect() { + if (itemRef.current && shouldScrollIntoView) + scrollIntoView(itemRef.current, { + scrollMode: "if-needed", + block: "nearest", + inline: "nearest", + }); + }, + [shouldScrollIntoView], + ); + const itemRef = React.useRef(null); + const theme = useTheme() as Theme; + + return ( +
+
+ + +
{`Create branch: ${branch} `}
+
{`from '${currentBranch}'`}
+
+
+ + + + +
+ ); +} + +export function LoadingRow() { + return ( + +
+ +
+
+ ); +} + +export function BranchesLoading() { + return ( + <> + + + + + ); +} + +interface BranchListHeaderProps { + onClickClose: () => void; + onClickRefresh: () => void; +} + +export function Header({ + onClickClose = noop, + onClickRefresh = noop, +}: BranchListHeaderProps) { + const title = createMessage(SWITCH_BRANCHES); + const theme = useTheme() as Theme; + + return ( +
+
+ + {title} + + + +
+
+ ); +} + +interface BranchListViewProps { + branches: FetchBranchesResponseData | null; + checkoutBranch: (branch: string) => void; + checkoutDestBranch: string | null; + createBranch: (branch: string) => void; + currentBranch: string | null; + defaultBranch: string | null; + deleteBranch: (branch: string) => void; + fetchBranches: () => void; + fetchProtectedBranches: () => void; + isCreateBranchLoading: boolean; + isCheckoutBranchLoading: boolean; + isFetchBranchesLoading: boolean; + isFetchProtectedBranchesLoading: boolean; + protectedBranches: FetchProtectedBranchesResponseData | null; + toggleBranchPopup: (isOpen: boolean) => void; +} + +export default function BranchListView({ + branches = null, + checkoutBranch = noop, + checkoutDestBranch = null, + createBranch = noop, + currentBranch = null, + defaultBranch = null, + deleteBranch = noop, + fetchBranches = noop, + fetchProtectedBranches = noop, + isCheckoutBranchLoading = false, + isCreateBranchLoading = false, + isFetchBranchesLoading = false, + isFetchProtectedBranchesLoading = false, + protectedBranches = null, + toggleBranchPopup = noop, +}: BranchListViewProps) { + const [searchText, changeSearchTextInState] = useState(""); + const changeSearchText = useCallback((text: string) => { + changeSearchTextInState(removeSpecialChars(text)); + }, []); + const branchNames = useMemo( + () => branches?.map((branch) => branch.branchName), + [branches], + ); + + const isCreateNewBranchInputValid = useMemo( + () => + !!( + searchText && + branchNames && + !branchNames.find((branch: string) => branch === searchText) + ), + [searchText, branchNames], + ); + + const filteredBranches = useFilteredBranches(branches ?? [], searchText); + + const localBranches = filteredBranches.filter((b: string) => + isLocalBranch(b), + ); + const remoteBranches = filteredBranches.filter((b: string) => + isRemoteBranch(b), + ); + const { activeHoverIndex, setActiveHoverIndex } = useActiveHoverIndex( + currentBranch ?? "", + filteredBranches, + isCreateNewBranchInputValid, + ); + + const handleClickOnRefresh = useCallback(() => { + AnalyticsUtil.logEvent("GS_SYNC_BRANCHES", { + source: "BRANCH_LIST_POPUP_FROM_BOTTOM_BAR", + }); + fetchBranches(); + fetchProtectedBranches(); + }, [fetchBranches, fetchProtectedBranches]); + + const handleCreateNewBranch = useCallback(() => { + if (isCreateBranchLoading) return; + + AnalyticsUtil.logEvent("GS_CREATE_NEW_BRANCH", { + source: "BRANCH_LIST_POPUP_FROM_BOTTOM_BAR", + }); + const branch = searchText; + + createBranch(branch); + }, [createBranch, isCreateBranchLoading, searchText]); + + const handleUpKey = useCallback( + () => setActiveHoverIndex(activeHoverIndex - 1), + [activeHoverIndex, setActiveHoverIndex], + ); + + const handleDownKey = useCallback( + () => setActiveHoverIndex(activeHoverIndex + 1), + [activeHoverIndex, setActiveHoverIndex], + ); + + const handleSubmitKey = useCallback(() => { + if (isCreateNewBranchInputValid) { + handleCreateNewBranch(); + } else { + checkoutBranch(filteredBranches[activeHoverIndex]); + AnalyticsUtil.logEvent("GS_SWITCH_BRANCH", { + source: "BRANCH_LIST_POPUP_FROM_BOTTOM_BAR", + }); + } + }, [ + activeHoverIndex, + filteredBranches, + handleCreateNewBranch, + isCreateNewBranchInputValid, + checkoutBranch, + ]); + + const handleEscKey = useCallback(() => { + toggleBranchPopup(false); + }, [toggleBranchPopup]); + + const handleClickOnClose = useCallback(() => { + toggleBranchPopup(false); + }, [toggleBranchPopup]); + + const isLoading = isFetchBranchesLoading || isFetchProtectedBranchesLoading; + + return ( + + +
+ +
+ {isLoading && ( +
+ +
+ )} + {!isLoading && ( + + )} +
+ + + {isLoading && } + {!isLoading && ( + + + {isCreateNewBranchInputValid && ( + + )} + + + + + )} + + + ); +} diff --git a/app/client/src/git/components/BranchList/BranchMoreMenu.tsx b/app/client/src/git/components/BranchList/BranchMoreMenu.tsx new file mode 100644 index 000000000000..d035549526a4 --- /dev/null +++ b/app/client/src/git/components/BranchList/BranchMoreMenu.tsx @@ -0,0 +1,132 @@ +import React, { useCallback } from "react"; +import AnalyticsUtil from "ee/utils/AnalyticsUtil"; +import { + createMessage, + DELETE, + DELETE_BRANCH_WARNING_CHECKED_OUT, + DELETE_BRANCH_WARNING_DEFAULT, +} from "ee/constants/messages"; +import { + Button, + Menu, + MenuContent, + MenuItem, + MenuTrigger, + toast, +} from "@appsmith/ads"; +import noop from "lodash/noop"; + +interface DeleteButtonProps { + branch: string | null; + currentBranch: string | null; + defaultBranch: string | null; + deleteBranch: (branch: string) => void; +} + +function DeleteButton({ + branch = null, + currentBranch = null, + defaultBranch = null, + deleteBranch = noop, +}: DeleteButtonProps) { + const saneDelete = useCallback(() => { + if (branch) { + if (defaultBranch === branch) { + toast.show(createMessage(DELETE_BRANCH_WARNING_DEFAULT, branch), { + kind: "error", + }); + } else if (currentBranch === branch) { + toast.show(createMessage(DELETE_BRANCH_WARNING_CHECKED_OUT, branch), { + kind: "error", + }); + } else { + deleteBranch(branch); + } + } + }, [branch, currentBranch, defaultBranch, deleteBranch]); + + const handleClick = useCallback( + (e) => { + e.stopPropagation(); + saneDelete(); + }, + [saneDelete], + ); + + return ( + + {createMessage(DELETE)} + + ); +} + +interface BranchMoreMenuProps { + branch: string | null; + currentBranch: string | null; + defaultBranch: string | null; + deleteBranch: (branch: string) => void; + open: boolean; + setOpen: (open: boolean) => void; +} + +export default function BranchMoreMenu({ + branch = null, + currentBranch = null, + defaultBranch = null, + deleteBranch = noop, + open, + setOpen, +}: BranchMoreMenuProps) { + const buttons = [ + , + ]; + + const handleMenuClose = useCallback(() => { + setOpen(false); + }, [setOpen]); + + const handleClickOnMenu = useCallback( + (e) => { + e.stopPropagation(); + setOpen(true); + AnalyticsUtil.logEvent("GS_BRANCH_MORE_MENU_OPEN", { + source: "GS_OPEN_BRANCH_LIST_POPUP", + }); + }, + [setOpen], + ); + + return ( + + + + ); +} diff --git a/app/client/src/git/components/BranchList/LocalBranchList.tsx b/app/client/src/git/components/BranchList/LocalBranchList.tsx new file mode 100644 index 000000000000..7fa293b236e7 --- /dev/null +++ b/app/client/src/git/components/BranchList/LocalBranchList.tsx @@ -0,0 +1,75 @@ +import LocalBranchListItem from "./LocalBranchListItem"; +import React from "react"; +import { createMessage, LOCAL_BRANCHES } from "ee/constants/messages"; +import { Text } from "@appsmith/ads"; +import type { FetchProtectedBranchesResponseData } from "git/requests/fetchProtectedBranchesRequest.types"; +import noop from "lodash/noop"; +import styled from "styled-components"; + +const Heading = styled(Text)` + font-weight: 600; +`; + +interface LocalBranchListProps { + activeHoverIndex: number; + checkoutBranch: (branch: string) => void; + checkoutDestBranch: string | null; + currentBranch: string | null; + defaultBranch: string | null; + deleteBranch: (branch: string) => void; + isCreateNewBranchInputValid: boolean; + isCheckoutBranchLoading: boolean; + localBranches: string[]; + protectedBranches: FetchProtectedBranchesResponseData | null; +} + +export default function LocalBranchList({ + activeHoverIndex = 0, + checkoutBranch = noop, + checkoutDestBranch = null, + currentBranch = null, + defaultBranch = null, + deleteBranch = noop, + isCheckoutBranchLoading = false, + isCreateNewBranchInputValid = false, + localBranches = [], + protectedBranches = null, +}: LocalBranchListProps) { + return ( +
+ {localBranches?.length > 0 && ( + + {createMessage(LOCAL_BRANCHES)} + + )} + {localBranches.map((branch: string, index: number) => { + const isActive = + (isCreateNewBranchInputValid + ? activeHoverIndex - 1 + : activeHoverIndex) === index; + + return ( + + ); + })} +
+ ); +} diff --git a/app/client/src/git/components/BranchList/LocalBranchListItem.tsx b/app/client/src/git/components/BranchList/LocalBranchListItem.tsx new file mode 100644 index 000000000000..c1bcd0937937 --- /dev/null +++ b/app/client/src/git/components/BranchList/LocalBranchListItem.tsx @@ -0,0 +1,135 @@ +import React, { useCallback, useEffect } from "react"; +import scrollIntoView from "scroll-into-view-if-needed"; +import BranchListItemContainer from "./BranchListItemContainer"; +import useHover from "./hooks/useHover"; +import BranchMoreMenu from "./BranchMoreMenu"; +import { Tooltip, Text, Spinner, Tag, Icon } from "@appsmith/ads"; +import { isEllipsisActive } from "utils/helpers"; +import styled from "styled-components"; +import noop from "lodash/noop"; +import AnalyticsUtil from "ee/utils/AnalyticsUtil"; + +const StyledIcon = styled(Icon)` + margin-right: 8px; + width: 14px; + height: 14px; + margin-top: 1px; +`; + +const OptionsContainer = styled.div` + display: flex; + align-items: center; + justify-content: flex-end; + height: 100%; +`; + +const BranchText = styled(Text)` + width: 100%; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +`; + +interface LocalBranchListItemProps { + branch: string; + checkoutBranch: (branch: string) => void; + checkoutDestBranch: string | null; + className?: string; + currentBranch: string | null; + defaultBranch: string | null; + deleteBranch: (branch: string) => void; + isActive: boolean; + isCheckoutBranchLoading: boolean; + isDefault: boolean; + isProtected: boolean; + isSelected: boolean; + shouldScrollIntoView: boolean; +} + +export default function LocalBranchListItem({ + branch, + checkoutBranch = noop, + checkoutDestBranch = null, + className, + currentBranch = null, + defaultBranch = null, + deleteBranch = noop, + isActive = false, + isCheckoutBranchLoading = false, + isDefault = false, + isProtected = false, + isSelected = false, + shouldScrollIntoView = false, +}: LocalBranchListItemProps) { + const itemRef = React.useRef(null); + const [hover] = useHover(itemRef); + const textRef = React.useRef(null); + const [isMoreMenuOpen, setIsMoreMenuOpen] = React.useState(false); + + useEffect( + function scrollIntoViewOnInitEffect() { + if (itemRef.current && shouldScrollIntoView) { + scrollIntoView(itemRef.current, { + scrollMode: "if-needed", + block: "nearest", + inline: "nearest", + }); + } + }, + [shouldScrollIntoView], + ); + + const handleClickOnBranch = useCallback(() => { + checkoutBranch(branch); + AnalyticsUtil.logEvent("GS_SWITCH_BRANCH", { + source: "BRANCH_LIST_POPUP_FROM_BOTTOM_BAR", + }); + }, [branch, checkoutBranch]); + + return ( + + {isProtected && } + + + + {branch} + + {isDefault && ( + + Default + + )} + + + + {checkoutDestBranch === branch && isCheckoutBranchLoading && ( + + )} + {(hover || isMoreMenuOpen) && ( + + )} + + + ); +} diff --git a/app/client/src/git/components/BranchList/RemoteBranchList.tsx b/app/client/src/git/components/BranchList/RemoteBranchList.tsx new file mode 100644 index 000000000000..1d8b7ab865bd --- /dev/null +++ b/app/client/src/git/components/BranchList/RemoteBranchList.tsx @@ -0,0 +1,47 @@ +import RemoteBranchListItem from "./RemoteBranchListItem"; +import React from "react"; +import { createMessage, REMOTE_BRANCHES } from "ee/constants/messages"; +import { Text } from "@appsmith/ads"; +import styled from "styled-components"; +import noop from "lodash/noop"; + +const Heading = styled(Text)` + font-weight: 600; +`; + +interface RemoteBranchListProps { + remoteBranches: string[]; + checkoutBranch: (branch: string) => void; + checkoutDestBranch: string | null; + isCheckoutBranchLoading: boolean; +} + +export default function RemoteBranchList({ + checkoutBranch = noop, + checkoutDestBranch = null, + isCheckoutBranchLoading = false, + remoteBranches = [], +}: RemoteBranchListProps) { + return ( +
+ {remoteBranches?.length > 0 && ( + + {createMessage(REMOTE_BRANCHES)} + + )} + {remoteBranches.map((branch: string) => ( + + ))} +
+ ); +} diff --git a/app/client/src/git/components/BranchList/RemoteBranchListItem.tsx b/app/client/src/git/components/BranchList/RemoteBranchListItem.tsx new file mode 100644 index 000000000000..10546a7b97a1 --- /dev/null +++ b/app/client/src/git/components/BranchList/RemoteBranchListItem.tsx @@ -0,0 +1,74 @@ +import React, { useCallback } from "react"; +import { Spinner, Tooltip } from "@appsmith/ads"; +import { isEllipsisActive } from "utils/helpers"; +import { Text, TextType } from "@appsmith/ads-old"; +import BranchListItemContainer from "./BranchListItemContainer"; +import styled from "styled-components"; +import AnalyticsUtil from "ee/utils/AnalyticsUtil"; +import noop from "lodash/noop"; + +const OptionsContainer = styled.div` + display: flex; + align-items: center; + justify-content: flex-end; + height: 100%; +`; + +const BranchText = styled(Text)` + width: 100%; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +`; + +interface RemoteBranchListItemProps { + branch: string; + checkoutBranch: (branch: string) => void; + checkoutDestBranch: string | null; + className?: string; + isCheckoutBranchLoading: boolean; +} + +export default function RemoteBranchListItem({ + branch, + checkoutBranch = noop, + checkoutDestBranch = null, + className, + isCheckoutBranchLoading = false, +}: RemoteBranchListItemProps) { + const textRef = React.useRef(null); + + const handleClickOnBranch = useCallback(() => { + checkoutBranch(branch); + AnalyticsUtil.logEvent("GS_SWITCH_BRANCH", { + source: "BRANCH_LIST_POPUP_FROM_BOTTOM_BAR", + }); + }, [branch, checkoutBranch]); + + return ( + + + + {branch} + + + + {checkoutDestBranch === branch && isCheckoutBranchLoading && ( + + )} + + + ); +} diff --git a/app/client/src/git/components/BranchList/hooks/useActiveHoverIndex.ts b/app/client/src/git/components/BranchList/hooks/useActiveHoverIndex.ts new file mode 100644 index 000000000000..96244af0dabb --- /dev/null +++ b/app/client/src/git/components/BranchList/hooks/useActiveHoverIndex.ts @@ -0,0 +1,43 @@ +import { useCallback, useEffect, useState } from "react"; + +export default function useActiveHoverIndex( + currentBranch: string | undefined, + filteredBranches: Array, + isCreateNewBranchInputValid: boolean, +) { + const effectiveLength = isCreateNewBranchInputValid + ? filteredBranches.length + : filteredBranches.length - 1; + + const [activeHoverIndex, setActiveHoverIndexInState] = useState(0); + const setActiveHoverIndex = useCallback( + (index: number) => { + if (index < 0) setActiveHoverIndexInState(effectiveLength); + else if (index > effectiveLength) setActiveHoverIndexInState(0); + else setActiveHoverIndexInState(index); + }, + [effectiveLength], + ); + + useEffect( + function activeHoverIndexEffect() { + const activeBranchIdx = filteredBranches.indexOf(currentBranch || ""); + + if (activeBranchIdx !== -1) { + setActiveHoverIndex( + isCreateNewBranchInputValid ? activeBranchIdx + 1 : activeBranchIdx, + ); + } else { + setActiveHoverIndex(0); + } + }, + [ + currentBranch, + filteredBranches, + isCreateNewBranchInputValid, + setActiveHoverIndex, + ], + ); + + return { activeHoverIndex, setActiveHoverIndex }; +} diff --git a/app/client/src/git/components/BranchList/hooks/useFilteredBranches.ts b/app/client/src/git/components/BranchList/hooks/useFilteredBranches.ts new file mode 100644 index 000000000000..0674ad81bdef --- /dev/null +++ b/app/client/src/git/components/BranchList/hooks/useFilteredBranches.ts @@ -0,0 +1,29 @@ +import type { Branch } from "entities/GitSync"; +import { useEffect, useState } from "react"; + +export function useFilteredBranches( + branches: Array, + searchText: string, +) { + const lowercaseSearchText = searchText.toLowerCase(); + const [filteredBranches, setFilteredBranches] = useState>([]); + + useEffect( + function setFilteredBranchesEffect() { + const matched = branches.filter((b: Branch) => + lowercaseSearchText + ? b.branchName.toLowerCase().includes(lowercaseSearchText) + : true, + ); + const branchNames = [ + ...matched.filter((b: Branch) => b.default), + ...matched.filter((b: Branch) => !b.default), + ].map((b: Branch) => b.branchName); + + setFilteredBranches(branchNames); + }, + [branches, lowercaseSearchText], + ); + + return filteredBranches; +} diff --git a/app/client/src/git/components/BranchList/hooks/useHover.ts b/app/client/src/git/components/BranchList/hooks/useHover.ts new file mode 100644 index 000000000000..bcd6475f152c --- /dev/null +++ b/app/client/src/git/components/BranchList/hooks/useHover.ts @@ -0,0 +1,24 @@ +import { useEffect, useState } from "react"; + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export default function useHover(ref: any) { + const [hover, setHover] = useState(false); + const onMouseEnter = () => setHover(true); + const onMouseLeave = () => setHover(false); + + useEffect(function onInitEffect() { + const target = ref.current; + + if (target) { + target.addEventListener("mouseenter", onMouseEnter); + target.addEventListener("mouseleave", onMouseLeave); + + return () => { + target.removeEventListener("mouseenter", onMouseEnter); + target.removeEventListener("mouseleave", onMouseLeave); + }; + } + }); + + return [hover]; +} diff --git a/app/client/src/git/components/BranchList/index.tsx b/app/client/src/git/components/BranchList/index.tsx new file mode 100644 index 000000000000..4df8c84927a1 --- /dev/null +++ b/app/client/src/git/components/BranchList/index.tsx @@ -0,0 +1,49 @@ +import React from "react"; +import BranchListView from "./BranchListView"; +import useBranches from "git/hooks/useBranches"; +import useDefaultBranch from "git/hooks/useDefaultBranch"; +import useProtectedBranches from "git/hooks/useProtectedBranches"; + +function BranchList() { + const { + branches, + checkoutBranch, + checkoutDestBranch, + createBranch, + currentBranch, + deleteBranch, + fetchBranches, + isCheckoutBranchLoading, + isCreateBranchLoading, + isFetchBranchesLoading, + toggleBranchPopup, + } = useBranches(); + const { defaultBranch } = useDefaultBranch(); + const { + fetchProtectedBranches, + isFetchProtectedBranchesLoading, + protectedBranches, + } = useProtectedBranches(); + + return ( + + ); +} + +export default BranchList; diff --git a/app/client/src/git/components/OpsModal/TabMerge/index.tsx b/app/client/src/git/components/OpsModal/TabMerge/index.tsx index 370ab874727e..a192d93dfcda 100644 --- a/app/client/src/git/components/OpsModal/TabMerge/index.tsx +++ b/app/client/src/git/components/OpsModal/TabMerge/index.tsx @@ -16,7 +16,7 @@ export default function TabMerge() { mergeStatus, } = useMerge(); const { isFetchStatusLoading, status } = useStatus(); - const { branches, currentBranch, fetchBranches, fetchBranchesLoading } = + const { branches, currentBranch, fetchBranches, isFetchBranchesLoading } = useBranches(); const { protectedBranches } = useProtectedBranches(); @@ -29,7 +29,7 @@ export default function TabMerge() { currentBranch={currentBranch} fetchBranches={fetchBranches} fetchMergeStatus={fetchMergeStatus} - isFetchBranchesLoading={fetchBranchesLoading} + isFetchBranchesLoading={isFetchBranchesLoading} isFetchMergeStatusLoading={isFetchMergeStatusLoading} isFetchStatusLoading={isFetchStatusLoading} isMergeLoading={isMergeLoading} diff --git a/app/client/src/git/components/QuickActions/BranchButton/index.tsx b/app/client/src/git/components/QuickActions/BranchButton.tsx similarity index 75% rename from app/client/src/git/components/QuickActions/BranchButton/index.tsx rename to app/client/src/git/components/QuickActions/BranchButton.tsx index d73cba35e40e..0f220d97feb4 100644 --- a/app/client/src/git/components/QuickActions/BranchButton/index.tsx +++ b/app/client/src/git/components/QuickActions/BranchButton.tsx @@ -1,23 +1,14 @@ import { Button, Icon, Tooltip } from "@appsmith/ads"; -import React, { useCallback, useEffect, useState } from "react"; +import React, { useCallback, useMemo } from "react"; import styled from "styled-components"; import noop from "lodash/noop"; -import BranchList from "./BranchList"; +import BranchList from "../BranchList"; import { Popover2 } from "@blueprintjs/popover2"; // internal dependencies import { isEllipsisActive } from "utils/helpers"; import AnalyticsUtil from "ee/utils/AnalyticsUtil"; -interface BranchButtonProps { - currentBranch?: string; - isOpen?: boolean; - setIsOpen?: (isOpen: boolean) => void; - isDisabled?: boolean; - isProtectedMode?: boolean; - isStatusClean?: boolean; -} - const ButtonContainer = styled(Button)` display: flex; align-items: center; @@ -45,20 +36,32 @@ const popoverModifiers: { offset: Record } = { offset: { enabled: true, options: { offset: [7, 10] } }, }; +interface BranchButtonProps { + currentBranch: string | null; + isAutocommitPolling: boolean; + isBranchPopupOpen: boolean; + isProtectedMode: boolean; + isStatusClean: boolean; + isTriggerAutocommitLoading: boolean; + toggleBranchPopup: (open: boolean) => void; +} + export default function BranchButton({ - currentBranch = "", - isDisabled = false, - isOpen = false, + currentBranch = null, + isAutocommitPolling = false, + isBranchPopupOpen = false, isProtectedMode = false, isStatusClean = false, - setIsOpen = noop, + isTriggerAutocommitLoading = false, + toggleBranchPopup = noop, }: BranchButtonProps) { - const [isEllipsis, setIsEllipsis] = useState(false); const labelTarget = React.useRef(null); + const isDisabled = isTriggerAutocommitLoading || isAutocommitPolling; + const onPopoverInteraction = useCallback( (nextState: boolean) => { - setIsOpen(nextState); + toggleBranchPopup(nextState); if (nextState) { AnalyticsUtil.logEvent("GS_OPEN_BRANCH_LIST_POPUP", { @@ -66,24 +69,20 @@ export default function BranchButton({ }); } }, - [setIsOpen], + [toggleBranchPopup], ); - useEffect(function ellipsisCheck() { - setIsEllipsis(isEllipsisActive(labelTarget.current) ?? false); - }, []); - - const renderContent = useCallback(() => { + const content = useMemo(() => { return ; }, []); return ( Test; -} diff --git a/app/client/src/git/components/QuickActions/QuickActionsView.test.tsx b/app/client/src/git/components/QuickActions/QuickActionsView.test.tsx index a1d595b923c8..6e696ddffe55 100644 --- a/app/client/src/git/components/QuickActions/QuickActionsView.test.tsx +++ b/app/client/src/git/components/QuickActions/QuickActionsView.test.tsx @@ -21,9 +21,11 @@ jest.mock("./../Statusbar", () => () => ( describe("QuickActionsView Component", () => { const defaultProps = { + currentBranch: "main", discard: jest.fn(), isAutocommitEnabled: false, isAutocommitPolling: false, + isBranchPopupOpen: false, isConnectPermitted: true, isDiscardLoading: false, isFetchStatusLoading: false, @@ -32,12 +34,14 @@ describe("QuickActionsView Component", () => { isPullFailing: false, isPullLoading: false, isStatusClean: true, + isTriggerAutocommitLoading: false, pull: jest.fn(), statusBehindCount: 0, statusChangeCount: 0, toggleConnectModal: jest.fn(), toggleOpsModal: jest.fn(), toggleSettingsModal: jest.fn(), + toggleBranchPopup: jest.fn(), }; afterEach(() => { diff --git a/app/client/src/git/components/QuickActions/QuickActionsView.tsx b/app/client/src/git/components/QuickActions/QuickActionsView.tsx index eedb67bf3787..396984788015 100644 --- a/app/client/src/git/components/QuickActions/QuickActionsView.tsx +++ b/app/client/src/git/components/QuickActions/QuickActionsView.tsx @@ -16,6 +16,7 @@ import QuickActionButton from "./QuickActionButton"; import AutocommitStatusbar from "../Statusbar"; import getPullBtnStatus from "./helpers/getPullButtonStatus"; import noop from "lodash/noop"; +import BranchButton from "./BranchButton"; const Container = styled.div` height: 100%; @@ -24,9 +25,11 @@ const Container = styled.div` `; interface QuickActionsViewProps { + currentBranch: string | null; discard: () => void; isAutocommitEnabled: boolean; isAutocommitPolling: boolean; + isBranchPopupOpen: boolean; isConnectPermitted: boolean; isDiscardLoading: boolean; isFetchStatusLoading: boolean; @@ -35,6 +38,7 @@ interface QuickActionsViewProps { isPullFailing: boolean; isPullLoading: boolean; isStatusClean: boolean; + isTriggerAutocommitLoading: boolean; pull: () => void; statusBehindCount: number; statusChangeCount: number; @@ -44,12 +48,15 @@ interface QuickActionsViewProps { open: boolean, tab: keyof typeof GitSettingsTab, ) => void; + toggleBranchPopup: (open: boolean) => void; } function QuickActionsView({ + currentBranch = null, discard = noop, isAutocommitEnabled = false, isAutocommitPolling = false, + isBranchPopupOpen = false, isConnectPermitted = false, isDiscardLoading = false, isFetchStatusLoading = false, @@ -58,9 +65,11 @@ function QuickActionsView({ isPullFailing = false, isPullLoading = false, isStatusClean = false, + isTriggerAutocommitLoading = false, pull = noop, statusBehindCount = 0, statusChangeCount = 0, + toggleBranchPopup = noop, toggleConnectModal = noop, toggleOpsModal = noop, toggleSettingsModal = noop, @@ -95,8 +104,6 @@ function QuickActionsView({ if (isProtectedMode) { discard(); } else { - // ! case: why is triggeredFromBottomBar this needed? - // pull({ triggeredFromBottomBar: true }); pull(); } } @@ -126,7 +133,16 @@ function QuickActionsView({ return isGitConnected ? ( - {/* */} + + {isAutocommitEnabled && isAutocommitPolling ? ( ) : ( diff --git a/app/client/src/git/components/QuickActions/index.tsx b/app/client/src/git/components/QuickActions/index.tsx index cb4b6a5624d1..2b03ee8bdd1d 100644 --- a/app/client/src/git/components/QuickActions/index.tsx +++ b/app/client/src/git/components/QuickActions/index.tsx @@ -11,6 +11,7 @@ import useDiscard from "git/hooks/useDiscard"; import usePull from "git/hooks/usePull"; import useStatus from "git/hooks/useStatus"; import useOps from "git/hooks/useOps"; +import useBranches from "git/hooks/useBranches"; function QuickActions() { const { toggleOpsModal } = useOps(); @@ -20,9 +21,14 @@ function QuickActions() { const { isGitConnected } = useMetadata(); const { isProtectedMode } = useProtectedBranches(); const { isConnectPermitted } = useGitPermissions(); - const { isAutocommitEnabled, isAutocommitPolling } = useAutocommit(); + const { + isAutocommitEnabled, + isAutocommitPolling, + isTriggerAutocommitLoading, + } = useAutocommit(); const { toggleSettingsModal } = useSettings(); const { toggleConnectModal } = useConnect(); + const { currentBranch, isBranchPopupOpen, toggleBranchPopup } = useBranches(); const isPullFailing = !!pullError; const isStatusClean = status?.isClean ?? false; @@ -31,9 +37,11 @@ function QuickActions() { return ( + selectTriggerAutocommitState(state, artifactDef), + ); + const toggleAutocommit = useCallback(() => { dispatch(gitArtifactActions.toggleAutocommitInit(artifactDef)); }, [artifactDef, dispatch]); @@ -50,6 +55,8 @@ export default function useAutocommit() { isToggleAutocommitLoading: toggleAutocommitState?.loading ?? false, toggleAutocommitError: toggleAutocommitState?.error ?? null, toggleAutocommit, + isTriggerAutocommitLoading: triggerAutocommitState?.loading ?? false, + triggerAutocommitError: triggerAutocommitState?.error ?? null, isAutocommitDisableModalOpen, toggleAutocommitDisableModal, isAutocommitEnabled, diff --git a/app/client/src/git/hooks/useBranches.ts b/app/client/src/git/hooks/useBranches.ts index 8785f0563a7b..4a0ecead44d7 100644 --- a/app/client/src/git/hooks/useBranches.ts +++ b/app/client/src/git/hooks/useBranches.ts @@ -1,11 +1,13 @@ import { useGitContext } from "git/components/GitContextProvider"; import { gitArtifactActions } from "git/store/gitArtifactSlice"; import { - selectBranches, - selectCheckoutBranch, - selectCreateBranch, + selectFetchBranchesState, + selectBranchPopupOpen, + selectCheckoutBranchState, + selectCheckoutDestBranch, + selectCreateBranchState, + selectDeleteBranchState, selectCurrentBranch, - selectDeleteBranch, } from "git/store/selectors/gitSingleArtifactSelectors"; import type { GitRootState } from "git/store/types"; import { useCallback } from "react"; @@ -18,7 +20,7 @@ export default function useBranches() { // fetch branches const branchesState = useSelector((state: GitRootState) => - selectBranches(state, artifactDef), + selectFetchBranchesState(state, artifactDef), ); const fetchBranches = useCallback(() => { dispatch( @@ -31,7 +33,7 @@ export default function useBranches() { // create branch const createBranchState = useSelector((state: GitRootState) => - selectCreateBranch(state, artifactDef), + selectCreateBranchState(state, artifactDef), ); const createBranch = useCallback( (branchName: string) => { @@ -46,7 +48,7 @@ export default function useBranches() { ); // delete branch const deleteBranchState = useSelector((state: GitRootState) => - selectDeleteBranch(state, artifactDef), + selectDeleteBranchState(state, artifactDef), ); const deleteBranch = useCallback( (branchName: string) => { @@ -61,7 +63,7 @@ export default function useBranches() { ); // checkout branch const checkoutBranchState = useSelector((state: GitRootState) => - selectCheckoutBranch(state, artifactDef), + selectCheckoutBranchState(state, artifactDef), ); const checkoutBranch = useCallback( (branchName: string) => { @@ -75,36 +77,49 @@ export default function useBranches() { [artifactDef, dispatch], ); + const checkoutDestBranch = useSelector((state: GitRootState) => + selectCheckoutDestBranch(state, artifactDef), + ); + // derived const currentBranch = useSelector((state: GitRootState) => selectCurrentBranch(state, artifactDef), ); // git branch list popup - const toggleBranchListPopup = (open: boolean) => { - dispatch( - gitArtifactActions.toggleBranchListPopup({ - ...artifactDef, - open, - }), - ); - }; + const isBranchPopupOpen = useSelector((state: GitRootState) => + selectBranchPopupOpen(state, artifactDef), + ); + + const toggleBranchPopup = useCallback( + (open: boolean) => { + dispatch( + gitArtifactActions.toggleBranchPopup({ + ...artifactDef, + open, + }), + ); + }, + [artifactDef, dispatch], + ); return { branches: branchesState?.value, - fetchBranchesLoading: branchesState?.loading ?? false, - fetchBranchesError: branchesState?.error, + isFetchBranchesLoading: branchesState?.loading ?? false, + fetchBranchesError: branchesState?.error ?? null, fetchBranches, - createBranchLoading: createBranchState?.loading ?? false, - createBranchError: createBranchState?.error, + isCreateBranchLoading: createBranchState?.loading ?? false, + createBranchError: createBranchState?.error ?? null, createBranch, - deleteBranchLoading: deleteBranchState?.loading ?? false, - deleteBranchError: deleteBranchState?.error, + isDeleteBranchLoading: deleteBranchState?.loading ?? false, + deleteBranchError: deleteBranchState?.error ?? null, deleteBranch, - checkoutBranchLoading: checkoutBranchState?.loading ?? false, - checkoutBranchError: checkoutBranchState?.error, + isCheckoutBranchLoading: checkoutBranchState?.loading ?? false, + checkoutBranchError: checkoutBranchState?.error ?? null, checkoutBranch, + checkoutDestBranch, currentBranch: currentBranch ?? null, - toggleBranchListPopup, + isBranchPopupOpen, + toggleBranchPopup, }; } diff --git a/app/client/src/git/sagas/checkoutBranchSaga.ts b/app/client/src/git/sagas/checkoutBranchSaga.ts index 18eaea3532ab..34e48434626c 100644 --- a/app/client/src/git/sagas/checkoutBranchSaga.ts +++ b/app/client/src/git/sagas/checkoutBranchSaga.ts @@ -48,7 +48,7 @@ export default function* checkoutBranchSaga( ); yield put( - gitArtifactActions.toggleBranchListPopup({ + gitArtifactActions.toggleBranchPopup({ ...basePayload, open: false, }), diff --git a/app/client/src/git/sagas/createBranchSaga.ts b/app/client/src/git/sagas/createBranchSaga.ts index 99604bd86602..7796f43d74bd 100644 --- a/app/client/src/git/sagas/createBranchSaga.ts +++ b/app/client/src/git/sagas/createBranchSaga.ts @@ -30,6 +30,12 @@ export default function* createBranchSaga( if (isValidResponse) { yield put(gitArtifactActions.createBranchSuccess(basePayload)); + yield put( + gitArtifactActions.toggleBranchPopup({ + ...basePayload, + open: false, + }), + ); yield put( gitArtifactActions.fetchBranchesInit({ ...basePayload, diff --git a/app/client/src/git/sagas/index.ts b/app/client/src/git/sagas/index.ts index 0bd96a008b3a..b593eac7f575 100644 --- a/app/client/src/git/sagas/index.ts +++ b/app/client/src/git/sagas/index.ts @@ -33,6 +33,9 @@ import toggleAutocommitSaga from "./toggleAutocommitSaga"; import disconnectSaga from "./disconnectSaga"; import { fetchSSHKeySaga } from "./fetchSSHKeySaga"; import { generateSSHKeySaga } from "./generateSSHKeySaga"; +import createBranchSaga from "./createBranchSaga"; +import deleteBranchSaga from "./deleteBranchSaga"; +import checkoutBranchSaga from "./checkoutBranchSaga"; const gitRequestBlockingActions: Record< string, @@ -54,6 +57,9 @@ const gitRequestBlockingActions: Record< // branches [gitArtifactActions.fetchBranchesInit.type]: fetchBranchesSaga, + [gitArtifactActions.createBranchInit.type]: createBranchSaga, + [gitArtifactActions.deleteBranchInit.type]: deleteBranchSaga, + [gitArtifactActions.checkoutBranchInit.type]: checkoutBranchSaga, // user profiles [gitArtifactActions.fetchLocalProfileInit.type]: fetchLocalProfileSaga, diff --git a/app/client/src/git/store/actions/checkoutBranchActions.ts b/app/client/src/git/store/actions/checkoutBranchActions.ts index c46edf84baff..c771d1887e34 100644 --- a/app/client/src/git/store/actions/checkoutBranchActions.ts +++ b/app/client/src/git/store/actions/checkoutBranchActions.ts @@ -6,9 +6,10 @@ export interface CheckoutBranchInitPayload extends CheckoutBranchRequestParams {} export const checkoutBranchInitAction = - createSingleArtifactAction((state) => { + createSingleArtifactAction((state, action) => { state.apiResponses.checkoutBranch.loading = true; state.apiResponses.checkoutBranch.error = null; + state.ui.checkoutDestBranch = action.payload.branchName; return state; }); @@ -16,6 +17,8 @@ export const checkoutBranchInitAction = export const checkoutBranchSuccessAction = createSingleArtifactAction( (state) => { state.apiResponses.checkoutBranch.loading = false; + state.apiResponses.checkoutBranch.error = null; + state.ui.checkoutDestBranch = null; return state; }, @@ -27,6 +30,7 @@ export const checkoutBranchErrorAction = state.apiResponses.checkoutBranch.loading = false; state.apiResponses.checkoutBranch.error = error; + state.ui.checkoutDestBranch = null; return state; }); diff --git a/app/client/src/git/store/actions/repoLimitErrorModalActions.ts b/app/client/src/git/store/actions/repoLimitErrorModalActions.ts index d79b29d61d15..b1867c1d5926 100644 --- a/app/client/src/git/store/actions/repoLimitErrorModalActions.ts +++ b/app/client/src/git/store/actions/repoLimitErrorModalActions.ts @@ -9,7 +9,7 @@ export const toggleRepoLimitErrorModalAction = (state, action) => { const { open } = action.payload; - state.ui.repoLimitErrorModal.open = open; + state.ui.repoLimitErrorModalOpen = open; return state; }, diff --git a/app/client/src/git/store/actions/uiActions.ts b/app/client/src/git/store/actions/uiActions.ts index fe861358d5ac..577d1dfa3d10 100644 --- a/app/client/src/git/store/actions/uiActions.ts +++ b/app/client/src/git/store/actions/uiActions.ts @@ -87,15 +87,15 @@ export const toggleAutocommitDisableModalAction = ); // branch popup -interface BranchListPopupPayload { +interface BranchPopupPayload { open: boolean; } -export const toggleBranchListPopupAction = - createSingleArtifactAction((state, action) => { +export const toggleBranchPopupAction = + createSingleArtifactAction((state, action) => { const { open } = action.payload; - state.ui.branchListPopup.open = open; + state.ui.branchPopupOpen = open; return state; }); @@ -109,7 +109,7 @@ export const toggleRepoLimitErrorModalAction = createSingleArtifactAction((state, action) => { const { open } = action.payload; - state.ui.repoLimitErrorModal.open = open; + state.ui.repoLimitErrorModalOpen = open; return state; }); diff --git a/app/client/src/git/store/gitArtifactSlice.ts b/app/client/src/git/store/gitArtifactSlice.ts index f5bb5bc6b9eb..a33b85e85146 100644 --- a/app/client/src/git/store/gitArtifactSlice.ts +++ b/app/client/src/git/store/gitArtifactSlice.ts @@ -53,7 +53,7 @@ import { deleteBranchSuccessAction, } from "./actions/deleteBranchActions"; import { - toggleBranchListPopupAction, + toggleBranchPopupAction, toggleConnectModalAction, toggleOpsModalAction, toggleSettingsModalAction, @@ -213,7 +213,7 @@ export const gitArtifactSlice = createSlice({ checkoutBranchInit: checkoutBranchInitAction, checkoutBranchSuccess: checkoutBranchSuccessAction, checkoutBranchError: checkoutBranchErrorAction, - toggleBranchListPopup: toggleBranchListPopupAction, + toggleBranchPopup: toggleBranchPopupAction, // settings toggleSettingsModal: toggleSettingsModalAction, diff --git a/app/client/src/git/store/helpers/gitSingleArtifactInitialState.ts b/app/client/src/git/store/helpers/gitSingleArtifactInitialState.ts index 8acf140bb2b0..b9db8e3c9efb 100644 --- a/app/client/src/git/store/helpers/gitSingleArtifactInitialState.ts +++ b/app/client/src/git/store/helpers/gitSingleArtifactInitialState.ts @@ -2,11 +2,7 @@ import { gitSingleArtifactInitialAPIResponsesEE, gitSingleArtifactInitialUIStateEE, } from "ee/git/store/helpers/gitSingleArtifactInitialState"; -import { - GitImportStep, - GitOpsTab, - GitSettingsTab, -} from "../../constants/enums"; +import { GitOpsTab, GitSettingsTab } from "../../constants/enums"; import type { GitSingleArtifactAPIResponsesReduxState, GitSingleArtifactUIReduxState, @@ -17,13 +13,8 @@ const gitSingleArtifactInitialUIState: GitSingleArtifactUIReduxState = { connectModalOpen: false, disconnectBaseArtifactId: null, disconnectArtifactName: null, - importModal: { - open: false, - step: GitImportStep.Provider, - }, - branchListPopup: { - open: false, - }, + branchPopupOpen: false, + checkoutDestBranch: null, opsModalOpen: false, opsModalTab: GitOpsTab.Deploy, settingsModalOpen: false, @@ -31,9 +22,7 @@ const gitSingleArtifactInitialUIState: GitSingleArtifactUIReduxState = { autocommitDisableModalOpen: false, autocommitPolling: false, conflictErrorModalOpen: false, - repoLimitErrorModal: { - open: false, - }, + repoLimitErrorModalOpen: false, // EE ...gitSingleArtifactInitialUIStateEE, }; diff --git a/app/client/src/git/store/selectors/gitSingleArtifactSelectors.ts b/app/client/src/git/store/selectors/gitSingleArtifactSelectors.ts index 1bdbcf310ac1..845a2cfe41fe 100644 --- a/app/client/src/git/store/selectors/gitSingleArtifactSelectors.ts +++ b/app/client/src/git/store/selectors/gitSingleArtifactSelectors.ts @@ -124,26 +124,36 @@ export const selectCurrentBranch = ( return gitMetadataState?.branchName; }; -export const selectBranches = ( +export const selectFetchBranchesState = ( state: GitRootState, artifactDef: GitArtifactDef, ) => selectGitArtifact(state, artifactDef)?.apiResponses?.branches; -export const selectCreateBranch = ( +export const selectCreateBranchState = ( state: GitRootState, artifactDef: GitArtifactDef, ) => selectGitArtifact(state, artifactDef)?.apiResponses?.createBranch; -export const selectDeleteBranch = ( +export const selectDeleteBranchState = ( state: GitRootState, artifactDef: GitArtifactDef, ) => selectGitArtifact(state, artifactDef)?.apiResponses?.deleteBranch; -export const selectCheckoutBranch = ( +export const selectCheckoutBranchState = ( state: GitRootState, artifactDef: GitArtifactDef, ) => selectGitArtifact(state, artifactDef)?.apiResponses.checkoutBranch; +export const selectCheckoutDestBranch = ( + state: GitRootState, + artifactDef: GitArtifactDef, +) => selectGitArtifact(state, artifactDef)?.ui.checkoutDestBranch; + +export const selectBranchPopupOpen = ( + state: GitRootState, + artifactDef: GitArtifactDef, +) => selectGitArtifact(state, artifactDef)?.ui.branchPopupOpen; + // SETTINGS // local profile @@ -163,6 +173,11 @@ export const selectToggleAutocommitState = ( artifactDef: GitArtifactDef, ) => selectGitArtifact(state, artifactDef)?.apiResponses.toggleAutocommit; +export const selectTriggerAutocommitState = ( + state: GitRootState, + artifactDef: GitArtifactDef, +) => selectGitArtifact(state, artifactDef)?.apiResponses.triggerAutocommit; + export const selectAutocommitDisableModalOpen = ( state: GitRootState, artifactDef: GitArtifactDef, diff --git a/app/client/src/git/store/types.ts b/app/client/src/git/store/types.ts index c9957a965444..3c6901baae69 100644 --- a/app/client/src/git/store/types.ts +++ b/app/client/src/git/store/types.ts @@ -1,7 +1,6 @@ import type { PayloadAction } from "@reduxjs/toolkit"; import type { GitArtifactType, - GitImportStep, GitOpsTab, GitSettingsTab, } from "../constants/enums"; @@ -66,13 +65,8 @@ export interface GitSingleArtifactUIReduxState connectModalOpen: boolean; disconnectBaseArtifactId: string | null; disconnectArtifactName: string | null; - importModal: { - open: boolean; - step: keyof typeof GitImportStep; - }; - branchListPopup: { - open: boolean; - }; + branchPopupOpen: boolean; + checkoutDestBranch: string | null; opsModalOpen: boolean; opsModalTab: keyof typeof GitOpsTab; settingsModalOpen: boolean; @@ -80,9 +74,7 @@ export interface GitSingleArtifactUIReduxState autocommitDisableModalOpen: boolean; autocommitPolling: boolean; conflictErrorModalOpen: boolean; - repoLimitErrorModal: { - open: boolean; - }; + repoLimitErrorModalOpen: boolean; } export interface GitSingleArtifactReduxState { ui: GitSingleArtifactUIReduxState; From 9071d0e9e47f1185abe5d15f630402121a12acb6 Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Mon, 16 Dec 2024 16:45:42 +0800 Subject: [PATCH 070/143] chore: wip ce-ee split --- .../components/ContinuousDelivery/index.tsx} | 4 +-- .../DefaultBranch/DefaultBranchView.tsx | 0 .../components/DefaultBranch/index.tsx} | 4 +-- .../src/git/ce/components/GitModals/index.tsx | 20 +++++++++++++++ .../git/{ => ce}/hooks/useDefaultBranch.ts | 4 --- app/client/src/git/ce/sagas/index.ts | 13 ++++++++++ app/client/src/git/ce/store/actions/index.ts | 3 +++ .../src/git/ce/store/helpers/initialState.ts | 9 +++++++ app/client/src/git/ce/store/types.ts | 3 +++ .../components/ContinuousDelivery/index.tsx | 16 ------------ .../git/components/DefaultBranch/index.tsx | 16 ------------ .../git/components/GitModals/GitModalsCE.tsx | 20 --------------- .../src/git/components/GitModals/index.tsx | 14 ----------- .../components/ProtectedBranches/index.tsx | 2 +- .../SettingsModal/TabBranch/index.tsx | 2 +- .../TabContinuousDelivery/index.tsx | 2 +- app/client/src/git/components/index.tsx | 2 +- .../components/ContinuousDelivery/index.tsx | 1 + .../git/ee/components/DefaultBranch/index.tsx | 1 + .../src/git/ee/components/GitModals/index.tsx | 1 + .../src/git/ee/hooks/useDefaultBranch.tsx | 1 + app/client/src/git/ee/sagas/index.ts | 1 + app/client/src/git/ee/store/actions/index.ts | 4 +++ .../src/git/ee/store/helpers/initialState.ts | 4 +++ app/client/src/git/ee/store/types.ts | 4 +++ app/client/src/git/sagas/index.ts | 25 ++++++++++--------- app/client/src/git/store/gitArtifactSlice.ts | 5 ++-- .../helpers/gitSingleArtifactInitialState.ts | 10 ++++---- app/client/src/git/store/types.ts | 10 ++++---- 29 files changed, 98 insertions(+), 103 deletions(-) rename app/client/src/git/{components/ContinuousDelivery/ContinuousDeliveryCE.tsx => ce/components/ContinuousDelivery/index.tsx} (94%) rename app/client/src/git/{ => ce}/components/DefaultBranch/DefaultBranchView.tsx (100%) rename app/client/src/git/{components/DefaultBranch/DefaultBranchCE.tsx => ce/components/DefaultBranch/index.tsx} (68%) create mode 100644 app/client/src/git/ce/components/GitModals/index.tsx rename app/client/src/git/{ => ce}/hooks/useDefaultBranch.ts (76%) create mode 100644 app/client/src/git/ce/sagas/index.ts create mode 100644 app/client/src/git/ce/store/actions/index.ts create mode 100644 app/client/src/git/ce/store/helpers/initialState.ts create mode 100644 app/client/src/git/ce/store/types.ts delete mode 100644 app/client/src/git/components/ContinuousDelivery/index.tsx delete mode 100644 app/client/src/git/components/DefaultBranch/index.tsx delete mode 100644 app/client/src/git/components/GitModals/GitModalsCE.tsx delete mode 100644 app/client/src/git/components/GitModals/index.tsx create mode 100644 app/client/src/git/ee/components/ContinuousDelivery/index.tsx create mode 100644 app/client/src/git/ee/components/DefaultBranch/index.tsx create mode 100644 app/client/src/git/ee/components/GitModals/index.tsx create mode 100644 app/client/src/git/ee/hooks/useDefaultBranch.tsx create mode 100644 app/client/src/git/ee/sagas/index.ts create mode 100644 app/client/src/git/ee/store/actions/index.ts create mode 100644 app/client/src/git/ee/store/helpers/initialState.ts create mode 100644 app/client/src/git/ee/store/types.ts diff --git a/app/client/src/git/components/ContinuousDelivery/ContinuousDeliveryCE.tsx b/app/client/src/git/ce/components/ContinuousDelivery/index.tsx similarity index 94% rename from app/client/src/git/components/ContinuousDelivery/ContinuousDeliveryCE.tsx rename to app/client/src/git/ce/components/ContinuousDelivery/index.tsx index 67d139b9e237..932f248a4447 100644 --- a/app/client/src/git/components/ContinuousDelivery/ContinuousDeliveryCE.tsx +++ b/app/client/src/git/ce/components/ContinuousDelivery/index.tsx @@ -29,7 +29,7 @@ export const StyledButton = styled(Button)` display: inline-block; `; -function ContinuousDeliveryCE() { +function ContinuousDelivery() { const enterprisePricingLink = useAppsmithEnterpriseLink( "git_continuous_delivery", ); @@ -55,4 +55,4 @@ function ContinuousDeliveryCE() { ); } -export default ContinuousDeliveryCE; +export default ContinuousDelivery; diff --git a/app/client/src/git/components/DefaultBranch/DefaultBranchView.tsx b/app/client/src/git/ce/components/DefaultBranch/DefaultBranchView.tsx similarity index 100% rename from app/client/src/git/components/DefaultBranch/DefaultBranchView.tsx rename to app/client/src/git/ce/components/DefaultBranch/DefaultBranchView.tsx diff --git a/app/client/src/git/components/DefaultBranch/DefaultBranchCE.tsx b/app/client/src/git/ce/components/DefaultBranch/index.tsx similarity index 68% rename from app/client/src/git/components/DefaultBranch/DefaultBranchCE.tsx rename to app/client/src/git/ce/components/DefaultBranch/index.tsx index e305972ba61e..1c18109e64fb 100644 --- a/app/client/src/git/components/DefaultBranch/DefaultBranchCE.tsx +++ b/app/client/src/git/ce/components/DefaultBranch/index.tsx @@ -1,8 +1,8 @@ import React from "react"; +import { useGitContext } from "git/components/GitContextProvider"; import DefaultBranchView from "./DefaultBranchView"; -import { useGitContext } from "../GitContextProvider"; -export default function DefaultBranchCE() { +export default function DefaultBranch() { const { branches } = useGitContext(); return ( diff --git a/app/client/src/git/ce/components/GitModals/index.tsx b/app/client/src/git/ce/components/GitModals/index.tsx new file mode 100644 index 000000000000..edf15092c4bd --- /dev/null +++ b/app/client/src/git/ce/components/GitModals/index.tsx @@ -0,0 +1,20 @@ +import ConflictErrorModal from "git/components/ConflictErrorModal"; +import DisableAutocommitModal from "git/components/DisableAutocommitModal"; +import DisconnectModal from "git/components/DisconnectModal"; +import OpsModal from "git/components/OpsModal"; +import SettingsModal from "git/components/SettingsModal"; +import React from "react"; + +function GitModals() { + return ( + <> + + + + + + + ); +} + +export default GitModals; diff --git a/app/client/src/git/hooks/useDefaultBranch.ts b/app/client/src/git/ce/hooks/useDefaultBranch.ts similarity index 76% rename from app/client/src/git/hooks/useDefaultBranch.ts rename to app/client/src/git/ce/hooks/useDefaultBranch.ts index f9a145229f5a..6bc27c1c08c0 100644 --- a/app/client/src/git/hooks/useDefaultBranch.ts +++ b/app/client/src/git/ce/hooks/useDefaultBranch.ts @@ -1,4 +1,3 @@ -import useDefaultBranchEE from "ee/git/hooks/useDefaultBranch"; import { useGitContext } from "git/components/GitContextProvider"; import { selectDefaultBranch } from "git/store/selectors/gitSingleArtifactSelectors"; import type { GitRootState } from "git/store/types"; @@ -11,11 +10,8 @@ function useDefaultBranch() { selectDefaultBranch(state, artifactDef), ); - const useDefaultBranchEEValues = useDefaultBranchEE(); - return { defaultBranch, - ...useDefaultBranchEEValues, }; } diff --git a/app/client/src/git/ce/sagas/index.ts b/app/client/src/git/ce/sagas/index.ts new file mode 100644 index 000000000000..091b8e1af65d --- /dev/null +++ b/app/client/src/git/ce/sagas/index.ts @@ -0,0 +1,13 @@ +import type { PayloadAction } from "@reduxjs/toolkit"; + +export const blockingActionSagas: Record< + string, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (action: PayloadAction) => Generator +> = {}; + +export const nonBlockingActionSagas: Record< + string, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (action: PayloadAction) => Generator +> = {}; diff --git a/app/client/src/git/ce/store/actions/index.ts b/app/client/src/git/ce/store/actions/index.ts new file mode 100644 index 000000000000..f2b34095bf1a --- /dev/null +++ b/app/client/src/git/ce/store/actions/index.ts @@ -0,0 +1,3 @@ +export const gitArtifactCaseReducers = {}; + +export const gitConfigCaseReducers = {}; diff --git a/app/client/src/git/ce/store/helpers/initialState.ts b/app/client/src/git/ce/store/helpers/initialState.ts new file mode 100644 index 000000000000..1cff0306011b --- /dev/null +++ b/app/client/src/git/ce/store/helpers/initialState.ts @@ -0,0 +1,9 @@ +import type { + GitArtifactAPIResponsesReduxState, + GitArtifactUIReduxState, +} from "../types"; + +export const gitArtifactUIInitialState: GitArtifactUIReduxState = {}; + +export const gitArtifactAPIResponsesInitialState: GitArtifactAPIResponsesReduxState = + {}; diff --git a/app/client/src/git/ce/store/types.ts b/app/client/src/git/ce/store/types.ts new file mode 100644 index 000000000000..27d2c4e2d710 --- /dev/null +++ b/app/client/src/git/ce/store/types.ts @@ -0,0 +1,3 @@ +export interface GitArtifactAPIResponsesReduxState {} + +export interface GitArtifactUIReduxState {} diff --git a/app/client/src/git/components/ContinuousDelivery/index.tsx b/app/client/src/git/components/ContinuousDelivery/index.tsx deleted file mode 100644 index 33bbf4f092df..000000000000 --- a/app/client/src/git/components/ContinuousDelivery/index.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import useGitFeatureFlags from "git/hooks/useGitFeatureFlags"; -import React from "react"; -import ContinuousDeliveryCE from "./ContinuousDeliveryCE"; -import { ContinuousDeliveryEE } from "ee/git/components/ContinuousDelivery/ContinuousDeliveryEE"; - -function ContinuousDelivery() { - const { license_git_continuous_delivery_enabled } = useGitFeatureFlags(); - - if (license_git_continuous_delivery_enabled) { - return ; - } - - return ; -} - -export default ContinuousDelivery; diff --git a/app/client/src/git/components/DefaultBranch/index.tsx b/app/client/src/git/components/DefaultBranch/index.tsx deleted file mode 100644 index 234e15c9bcf9..000000000000 --- a/app/client/src/git/components/DefaultBranch/index.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import React from "react"; -import useGitFeatureFlags from "git/hooks/useGitFeatureFlags"; -import DefaultBranchCE from "./DefaultBranchCE"; -import DefaultBranchEE from "ee/git/components/DefaultBranch/DefaultBranchEE"; - -function DefaultBranch() { - const { license_git_branch_protection_enabled } = useGitFeatureFlags(); - - if (license_git_branch_protection_enabled) { - return ; - } - - return ; -} - -export default DefaultBranch; diff --git a/app/client/src/git/components/GitModals/GitModalsCE.tsx b/app/client/src/git/components/GitModals/GitModalsCE.tsx deleted file mode 100644 index 194bfe792097..000000000000 --- a/app/client/src/git/components/GitModals/GitModalsCE.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import React from "react"; -import ConflictErrorModal from "../ConflictErrorModal"; -import SettingsModal from "../SettingsModal"; -import OpsModal from "../OpsModal"; -import DisconnectModal from "../DisconnectModal"; -import DisableAutocommitModal from "../DisableAutocommitModal"; - -function GitModalsCE() { - return ( - <> - - - - - - - ); -} - -export default GitModalsCE; diff --git a/app/client/src/git/components/GitModals/index.tsx b/app/client/src/git/components/GitModals/index.tsx deleted file mode 100644 index c27f0b4707a8..000000000000 --- a/app/client/src/git/components/GitModals/index.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import React from "react"; -import GitModalsCE from "./GitModalsCE"; -import GitModalsEE from "ee/git/components/GitModals/GitModalsEE"; - -function GitModals() { - return ( - <> - - - - ); -} - -export default GitModals; diff --git a/app/client/src/git/components/ProtectedBranches/index.tsx b/app/client/src/git/components/ProtectedBranches/index.tsx index 8f1381ca67c9..7da03a947e51 100644 --- a/app/client/src/git/components/ProtectedBranches/index.tsx +++ b/app/client/src/git/components/ProtectedBranches/index.tsx @@ -1,9 +1,9 @@ import React from "react"; import ProtectedBranchesView from "./ProtectedBranchesView"; import { useGitContext } from "../GitContextProvider"; -import useDefaultBranch from "git/hooks/useDefaultBranch"; import useProtectedBranches from "git/hooks/useProtectedBranches"; import useGitFeatureFlags from "git/hooks/useGitFeatureFlags"; +import useDefaultBranch from "git/ee/hooks/useDefaultBranch"; function ProtectedBranches() { const { branches } = useGitContext(); diff --git a/app/client/src/git/components/SettingsModal/TabBranch/index.tsx b/app/client/src/git/components/SettingsModal/TabBranch/index.tsx index 5c35b4ada436..559685801b09 100644 --- a/app/client/src/git/components/SettingsModal/TabBranch/index.tsx +++ b/app/client/src/git/components/SettingsModal/TabBranch/index.tsx @@ -1,7 +1,7 @@ import React from "react"; import styled from "styled-components"; -import DefaultBranch from "../../DefaultBranch"; import ProtectedBranches from "../../ProtectedBranches"; +import DefaultBranch from "git/ee/components/DefaultBranch"; const Container = styled.div` overflow: auto; diff --git a/app/client/src/git/components/SettingsModal/TabContinuousDelivery/index.tsx b/app/client/src/git/components/SettingsModal/TabContinuousDelivery/index.tsx index ebfa3f6d17b9..f42a4bb11412 100644 --- a/app/client/src/git/components/SettingsModal/TabContinuousDelivery/index.tsx +++ b/app/client/src/git/components/SettingsModal/TabContinuousDelivery/index.tsx @@ -1,5 +1,5 @@ import React from "react"; -import ContinuousDelivery from "git/components/ContinuousDelivery"; +import ContinuousDelivery from "git/ee/components/ContinuousDelivery"; function TabContinuosDelivery() { return ; diff --git a/app/client/src/git/components/index.tsx b/app/client/src/git/components/index.tsx index ec1d504d030a..1de56f66d1e0 100644 --- a/app/client/src/git/components/index.tsx +++ b/app/client/src/git/components/index.tsx @@ -1,2 +1,2 @@ -export { default as GitModals } from "./GitModals"; +export { default as GitModals } from "git/ee/components/GitModals"; export { default as GitQuickActions } from "./QuickActions"; diff --git a/app/client/src/git/ee/components/ContinuousDelivery/index.tsx b/app/client/src/git/ee/components/ContinuousDelivery/index.tsx new file mode 100644 index 000000000000..db73f3553add --- /dev/null +++ b/app/client/src/git/ee/components/ContinuousDelivery/index.tsx @@ -0,0 +1 @@ +export { default } from "git/ce/components/ContinuousDelivery"; diff --git a/app/client/src/git/ee/components/DefaultBranch/index.tsx b/app/client/src/git/ee/components/DefaultBranch/index.tsx new file mode 100644 index 000000000000..8f607db275ed --- /dev/null +++ b/app/client/src/git/ee/components/DefaultBranch/index.tsx @@ -0,0 +1 @@ +export { default } from "git/ce/components/DefaultBranch"; diff --git a/app/client/src/git/ee/components/GitModals/index.tsx b/app/client/src/git/ee/components/GitModals/index.tsx new file mode 100644 index 000000000000..3c70bddffe10 --- /dev/null +++ b/app/client/src/git/ee/components/GitModals/index.tsx @@ -0,0 +1 @@ +export { default } from "git/ce/components/GitModals"; diff --git a/app/client/src/git/ee/hooks/useDefaultBranch.tsx b/app/client/src/git/ee/hooks/useDefaultBranch.tsx new file mode 100644 index 000000000000..0337ec9f6600 --- /dev/null +++ b/app/client/src/git/ee/hooks/useDefaultBranch.tsx @@ -0,0 +1 @@ +export { default } from "git/ce/hooks/useDefaultBranch"; diff --git a/app/client/src/git/ee/sagas/index.ts b/app/client/src/git/ee/sagas/index.ts new file mode 100644 index 000000000000..8f425bc876c5 --- /dev/null +++ b/app/client/src/git/ee/sagas/index.ts @@ -0,0 +1 @@ +export { blockingActionSagas, nonBlockingActionSagas } from "git/ce/sagas"; diff --git a/app/client/src/git/ee/store/actions/index.ts b/app/client/src/git/ee/store/actions/index.ts new file mode 100644 index 000000000000..8b8930f67568 --- /dev/null +++ b/app/client/src/git/ee/store/actions/index.ts @@ -0,0 +1,4 @@ +export { + gitArtifactCaseReducers, + gitConfigCaseReducers, +} from "git/ce/store/actions"; diff --git a/app/client/src/git/ee/store/helpers/initialState.ts b/app/client/src/git/ee/store/helpers/initialState.ts new file mode 100644 index 000000000000..3890d5ec8c4b --- /dev/null +++ b/app/client/src/git/ee/store/helpers/initialState.ts @@ -0,0 +1,4 @@ +export { + gitArtifactAPIResponsesInitialState, + gitArtifactUIInitialState, +} from "git/ce/store/helpers/initialState"; diff --git a/app/client/src/git/ee/store/types.ts b/app/client/src/git/ee/store/types.ts new file mode 100644 index 000000000000..29e7ca3aa59c --- /dev/null +++ b/app/client/src/git/ee/store/types.ts @@ -0,0 +1,4 @@ +export type { + GitArtifactAPIResponsesReduxState, + GitArtifactUIReduxState, +} from "git/ce/store/types"; diff --git a/app/client/src/git/sagas/index.ts b/app/client/src/git/sagas/index.ts index 0d933a34ff81..4b2ca0720b0d 100644 --- a/app/client/src/git/sagas/index.ts +++ b/app/client/src/git/sagas/index.ts @@ -23,16 +23,17 @@ import fetchStatusSaga from "./fetchStatusSaga"; import fetchProtectedBranchesSaga from "./fetchProtectedBranchesSaga"; import pullSaga from "./pullSaga"; import fetchMergeStatusSaga from "./fetchMergeStatusSaga"; -import { - gitRequestBlockingActionsEE, - gitRequestNonBlockingActionsEE, -} from "ee/git/sagas"; import updateProtectedBranchesSaga from "./updateProtectedBranchesSaga"; import fetchMetadataSaga from "./fetchMetadataSaga"; import toggleAutocommitSaga from "./toggleAutocommitSaga"; import disconnectSaga from "./disconnectSaga"; -const gitRequestBlockingActions: Record< +import { + blockingActionSagas as blockingActionSagasExtended, + nonBlockingActionSagas as nonBlockingActionSagasExtended, +} from "git/ee/sagas"; + +const blockingActionSagas: Record< string, // eslint-disable-next-line @typescript-eslint/no-explicit-any (action: PayloadAction) => Generator @@ -69,10 +70,10 @@ const gitRequestBlockingActions: Record< [gitArtifactActions.triggerAutocommitInit.type]: triggerAutocommitSaga, // EE - ...gitRequestBlockingActionsEE, + ...blockingActionSagasExtended, }; -const gitRequestNonBlockingActions: Record< +const nonBlockingActionSagas: Record< string, // eslint-disable-next-line @typescript-eslint/no-explicit-any (action: PayloadAction) => Generator @@ -82,7 +83,7 @@ const gitRequestNonBlockingActions: Record< [gitArtifactActions.toggleAutocommitInit.type]: toggleAutocommitSaga, // EE - ...gitRequestNonBlockingActionsEE, + ...nonBlockingActionSagasExtended, }; /** @@ -96,21 +97,21 @@ const gitRequestNonBlockingActions: Record< * */ function* watchGitBlockingRequests() { const gitActionChannel: TakeableChannel = yield actionChannel( - objectKeys(gitRequestBlockingActions), + objectKeys(blockingActionSagas), ); while (true) { const action: PayloadAction = yield take(gitActionChannel); - yield call(gitRequestBlockingActions[action.type], action); + yield call(blockingActionSagas[action.type], action); } } function* watchGitNonBlockingRequests() { - const keys = objectKeys(gitRequestNonBlockingActions); + const keys = objectKeys(nonBlockingActionSagas); for (const actionType of keys) { - yield takeLatest(actionType, gitRequestNonBlockingActions[actionType]); + yield takeLatest(actionType, nonBlockingActionSagas[actionType]); } } diff --git a/app/client/src/git/store/gitArtifactSlice.ts b/app/client/src/git/store/gitArtifactSlice.ts index 8a8ffd686f83..75c3e64403b1 100644 --- a/app/client/src/git/store/gitArtifactSlice.ts +++ b/app/client/src/git/store/gitArtifactSlice.ts @@ -113,7 +113,7 @@ import { fetchAutocommitProgressInitAction, fetchAutocommitProgressSuccessAction, } from "./actions/fetchAutocommitProgressActions"; -import gitArtifactCaseReducersEE from "ee/git/store/actions"; +import { gitArtifactCaseReducers } from "git/ee/store/actions"; import { disconnectErrorAction, disconnectInitAction, @@ -216,8 +216,7 @@ export const gitArtifactSlice = createSlice({ pollAutocommitProgressStop: pollAutocommitProgressStopAction, toggleAutocommitDisableModal: toggleAutocommitDisableModalAction, - // EE - ...gitArtifactCaseReducersEE, + ...gitArtifactCaseReducers, }, }); diff --git a/app/client/src/git/store/helpers/gitSingleArtifactInitialState.ts b/app/client/src/git/store/helpers/gitSingleArtifactInitialState.ts index 13d0ec975cf4..605ed2748668 100644 --- a/app/client/src/git/store/helpers/gitSingleArtifactInitialState.ts +++ b/app/client/src/git/store/helpers/gitSingleArtifactInitialState.ts @@ -1,7 +1,7 @@ import { - gitSingleArtifactInitialAPIResponsesEE, - gitSingleArtifactInitialUIStateEE, -} from "ee/git/store/helpers/gitSingleArtifactInitialState"; + gitArtifactAPIResponsesInitialState as gitArtifactAPIResponsesInitialStateExtended, + gitArtifactUIInitialState as gitArtifactUIInitialStateExtended, +} from "git/ee/store/helpers/initialState"; import { GitConnectStep, GitImportStep, @@ -39,7 +39,7 @@ const gitSingleArtifactInitialUIState: GitSingleArtifactUIReduxState = { open: false, }, // EE - ...gitSingleArtifactInitialUIStateEE, + ...gitArtifactUIInitialStateExtended, }; const gitSingleArtifactInitialAPIResponses: GitSingleArtifactAPIResponsesReduxState = @@ -140,7 +140,7 @@ const gitSingleArtifactInitialAPIResponses: GitSingleArtifactAPIResponsesReduxSt error: null, }, // EE - ...gitSingleArtifactInitialAPIResponsesEE, + ...gitArtifactAPIResponsesInitialStateExtended, }; export const gitSingleArtifactInitialState: GitSingleArtifactReduxState = { diff --git a/app/client/src/git/store/types.ts b/app/client/src/git/store/types.ts index 9f931992f5d3..3c439ac128c7 100644 --- a/app/client/src/git/store/types.ts +++ b/app/client/src/git/store/types.ts @@ -15,9 +15,9 @@ import type { FetchMetadataResponseData } from "git/requests/fetchMetadataReques import type { FetchProtectedBranchesResponseData } from "git/requests/fetchProtectedBranchesRequest.types"; import type { ApiResponseError } from "api/types"; import type { - GitSingleArtifactAPIResponsesReduxStateEE, - GitSingleArtifactUIReduxStateEE, -} from "ee/git/store/types"; + GitArtifactAPIResponsesReduxState as GitArtifactAPIResponsesReduxStateExtended, + GitArtifactUIReduxState as GitArtifactUIReduxStateExtended, +} from "git/ee/store/types"; export type GitSSHKey = Record; @@ -37,7 +37,7 @@ export interface GitAsyncStateWithoutValue { error: GitApiError | null; } export interface GitSingleArtifactAPIResponsesReduxState - extends GitSingleArtifactAPIResponsesReduxStateEE { + extends GitArtifactAPIResponsesReduxStateExtended { metadata: GitAsyncState; connect: GitAsyncStateWithoutValue; status: GitAsyncState; @@ -63,7 +63,7 @@ export interface GitSingleArtifactAPIResponsesReduxState } export interface GitSingleArtifactUIReduxState - extends GitSingleArtifactUIReduxStateEE { + extends GitArtifactUIReduxStateExtended { connectModal: { open: boolean; step: keyof typeof GitConnectStep; From 6314fe2c576dfb60f73f1213b088f8fee36b1eb7 Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Mon, 16 Dec 2024 17:07:56 +0800 Subject: [PATCH 071/143] chore: additional ee files --- app/client/src/git/ce/store/selectors/gitArtifactSelectors.ts | 1 + .../git/ee/hooks/{useDefaultBranch.tsx => useDefaultBranch.ts} | 0 app/client/src/git/ee/store/selectors/gitArtifactSelectors.ts | 1 + 3 files changed, 2 insertions(+) create mode 100644 app/client/src/git/ce/store/selectors/gitArtifactSelectors.ts rename app/client/src/git/ee/hooks/{useDefaultBranch.tsx => useDefaultBranch.ts} (100%) create mode 100644 app/client/src/git/ee/store/selectors/gitArtifactSelectors.ts diff --git a/app/client/src/git/ce/store/selectors/gitArtifactSelectors.ts b/app/client/src/git/ce/store/selectors/gitArtifactSelectors.ts new file mode 100644 index 000000000000..ff8b4c56321a --- /dev/null +++ b/app/client/src/git/ce/store/selectors/gitArtifactSelectors.ts @@ -0,0 +1 @@ +export default {}; diff --git a/app/client/src/git/ee/hooks/useDefaultBranch.tsx b/app/client/src/git/ee/hooks/useDefaultBranch.ts similarity index 100% rename from app/client/src/git/ee/hooks/useDefaultBranch.tsx rename to app/client/src/git/ee/hooks/useDefaultBranch.ts diff --git a/app/client/src/git/ee/store/selectors/gitArtifactSelectors.ts b/app/client/src/git/ee/store/selectors/gitArtifactSelectors.ts new file mode 100644 index 000000000000..b8d74236d065 --- /dev/null +++ b/app/client/src/git/ee/store/selectors/gitArtifactSelectors.ts @@ -0,0 +1 @@ +export * from "git/ce/store/selectors/gitArtifactSelectors"; From 8d077c863e75b4981bfb483cd04a6b255f86b582 Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Mon, 16 Dec 2024 17:14:58 +0800 Subject: [PATCH 072/143] chore: wip more ce-ee split --- app/client/src/git/ee/sagas/index.ts | 2 +- app/client/src/git/ee/store/actions/index.ts | 5 +---- app/client/src/git/ee/store/helpers/initialState.ts | 5 +---- app/client/src/git/ee/store/types.ts | 5 +---- 4 files changed, 4 insertions(+), 13 deletions(-) diff --git a/app/client/src/git/ee/sagas/index.ts b/app/client/src/git/ee/sagas/index.ts index 8f425bc876c5..e2e51a6c89fd 100644 --- a/app/client/src/git/ee/sagas/index.ts +++ b/app/client/src/git/ee/sagas/index.ts @@ -1 +1 @@ -export { blockingActionSagas, nonBlockingActionSagas } from "git/ce/sagas"; +export * from "git/ce/sagas"; diff --git a/app/client/src/git/ee/store/actions/index.ts b/app/client/src/git/ee/store/actions/index.ts index 8b8930f67568..f668b546032a 100644 --- a/app/client/src/git/ee/store/actions/index.ts +++ b/app/client/src/git/ee/store/actions/index.ts @@ -1,4 +1 @@ -export { - gitArtifactCaseReducers, - gitConfigCaseReducers, -} from "git/ce/store/actions"; +export * from "git/ce/store/actions"; diff --git a/app/client/src/git/ee/store/helpers/initialState.ts b/app/client/src/git/ee/store/helpers/initialState.ts index 3890d5ec8c4b..56d5d4e5f0cc 100644 --- a/app/client/src/git/ee/store/helpers/initialState.ts +++ b/app/client/src/git/ee/store/helpers/initialState.ts @@ -1,4 +1 @@ -export { - gitArtifactAPIResponsesInitialState, - gitArtifactUIInitialState, -} from "git/ce/store/helpers/initialState"; +export * from "git/ce/store/helpers/initialState"; diff --git a/app/client/src/git/ee/store/types.ts b/app/client/src/git/ee/store/types.ts index 29e7ca3aa59c..67f9996d0639 100644 --- a/app/client/src/git/ee/store/types.ts +++ b/app/client/src/git/ee/store/types.ts @@ -1,4 +1 @@ -export type { - GitArtifactAPIResponsesReduxState, - GitArtifactUIReduxState, -} from "git/ce/store/types"; +export type * from "git/ce/store/types"; From 56f05cfb76fb3afd20b3db185821a7d837745678 Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Mon, 16 Dec 2024 17:31:09 +0800 Subject: [PATCH 073/143] chore: removing old ee folder --- .../ContinuousDelivery/ContinuousDeliveryEE.tsx | 1 - .../components/DefaultBranch/DefaultBranchEE.tsx | 3 --- .../ee/git/components/GitModals/GitModalsEE.tsx | 5 ----- app/client/src/ee/git/hooks/useDefaultBranch.ts | 3 --- app/client/src/ee/git/sagas/index.ts | 14 -------------- app/client/src/ee/git/store/actions/index.ts | 3 --- .../store/helpers/gitSingleArtifactInitialState.ts | 10 ---------- app/client/src/ee/git/store/types.ts | 3 --- 8 files changed, 42 deletions(-) delete mode 100644 app/client/src/ee/git/components/ContinuousDelivery/ContinuousDeliveryEE.tsx delete mode 100644 app/client/src/ee/git/components/DefaultBranch/DefaultBranchEE.tsx delete mode 100644 app/client/src/ee/git/components/GitModals/GitModalsEE.tsx delete mode 100644 app/client/src/ee/git/hooks/useDefaultBranch.ts delete mode 100644 app/client/src/ee/git/sagas/index.ts delete mode 100644 app/client/src/ee/git/store/actions/index.ts delete mode 100644 app/client/src/ee/git/store/helpers/gitSingleArtifactInitialState.ts delete mode 100644 app/client/src/ee/git/store/types.ts diff --git a/app/client/src/ee/git/components/ContinuousDelivery/ContinuousDeliveryEE.tsx b/app/client/src/ee/git/components/ContinuousDelivery/ContinuousDeliveryEE.tsx deleted file mode 100644 index 48921820773b..000000000000 --- a/app/client/src/ee/git/components/ContinuousDelivery/ContinuousDeliveryEE.tsx +++ /dev/null @@ -1 +0,0 @@ -export { default as ContinuousDeliveryEE } from "git/components/DefaultBranch/DefaultBranchCE"; diff --git a/app/client/src/ee/git/components/DefaultBranch/DefaultBranchEE.tsx b/app/client/src/ee/git/components/DefaultBranch/DefaultBranchEE.tsx deleted file mode 100644 index a44d2c38a025..000000000000 --- a/app/client/src/ee/git/components/DefaultBranch/DefaultBranchEE.tsx +++ /dev/null @@ -1,3 +0,0 @@ -import { default as DefaultBranchEE } from "git/components/DefaultBranch/DefaultBranchCE"; - -export default DefaultBranchEE; diff --git a/app/client/src/ee/git/components/GitModals/GitModalsEE.tsx b/app/client/src/ee/git/components/GitModals/GitModalsEE.tsx deleted file mode 100644 index 8cb6784cc12b..000000000000 --- a/app/client/src/ee/git/components/GitModals/GitModalsEE.tsx +++ /dev/null @@ -1,5 +0,0 @@ -function GitModalsEE() { - return null; -} - -export default GitModalsEE; diff --git a/app/client/src/ee/git/hooks/useDefaultBranch.ts b/app/client/src/ee/git/hooks/useDefaultBranch.ts deleted file mode 100644 index d41f26fe1cc4..000000000000 --- a/app/client/src/ee/git/hooks/useDefaultBranch.ts +++ /dev/null @@ -1,3 +0,0 @@ -export default function useDefaultBranchEE() { - return {}; -} diff --git a/app/client/src/ee/git/sagas/index.ts b/app/client/src/ee/git/sagas/index.ts deleted file mode 100644 index c6e962bdcace..000000000000 --- a/app/client/src/ee/git/sagas/index.ts +++ /dev/null @@ -1,14 +0,0 @@ -import type { PayloadAction } from "@reduxjs/toolkit"; - -// ! case: can we rethink the types -export const gitRequestBlockingActionsEE: Record< - string, - // eslint-disable-next-line @typescript-eslint/no-explicit-any - (action: PayloadAction) => Generator -> = {}; - -export const gitRequestNonBlockingActionsEE: Record< - string, - // eslint-disable-next-line @typescript-eslint/no-explicit-any - (action: PayloadAction) => Generator -> = {}; diff --git a/app/client/src/ee/git/store/actions/index.ts b/app/client/src/ee/git/store/actions/index.ts deleted file mode 100644 index e697f353cd27..000000000000 --- a/app/client/src/ee/git/store/actions/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -const gitArtifactCaseReducersEE = {}; - -export default gitArtifactCaseReducersEE; diff --git a/app/client/src/ee/git/store/helpers/gitSingleArtifactInitialState.ts b/app/client/src/ee/git/store/helpers/gitSingleArtifactInitialState.ts deleted file mode 100644 index 6fb4200fd3eb..000000000000 --- a/app/client/src/ee/git/store/helpers/gitSingleArtifactInitialState.ts +++ /dev/null @@ -1,10 +0,0 @@ -import type { - GitSingleArtifactAPIResponsesReduxStateEE, - GitSingleArtifactUIReduxStateEE, -} from "../types"; - -export const gitSingleArtifactInitialUIStateEE: GitSingleArtifactUIReduxStateEE = - {}; - -export const gitSingleArtifactInitialAPIResponsesEE: GitSingleArtifactAPIResponsesReduxStateEE = - {}; diff --git a/app/client/src/ee/git/store/types.ts b/app/client/src/ee/git/store/types.ts deleted file mode 100644 index 77fa321f9154..000000000000 --- a/app/client/src/ee/git/store/types.ts +++ /dev/null @@ -1,3 +0,0 @@ -export interface GitSingleArtifactAPIResponsesReduxStateEE {} - -export interface GitSingleArtifactUIReduxStateEE {} From 546fd66855c95cee1d061388378e9fcddedebfcd Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Mon, 16 Dec 2024 19:23:58 +0800 Subject: [PATCH 074/143] chore: conflict errors --- app/client/src/git/ce/components/GitModals/index.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/client/src/git/ce/components/GitModals/index.tsx b/app/client/src/git/ce/components/GitModals/index.tsx index edf15092c4bd..a5fcb8c7be36 100644 --- a/app/client/src/git/ce/components/GitModals/index.tsx +++ b/app/client/src/git/ce/components/GitModals/index.tsx @@ -1,4 +1,5 @@ import ConflictErrorModal from "git/components/ConflictErrorModal"; +import ConnectModal from "git/components/ConnectModal"; import DisableAutocommitModal from "git/components/DisableAutocommitModal"; import DisconnectModal from "git/components/DisconnectModal"; import OpsModal from "git/components/OpsModal"; @@ -8,6 +9,7 @@ import React from "react"; function GitModals() { return ( <> + From bbbee85f716c454efd1b7d56814c03b31bc8729f Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Mon, 16 Dec 2024 19:33:05 +0800 Subject: [PATCH 075/143] chore: fix branch list --- app/client/src/git/components/BranchList/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/client/src/git/components/BranchList/index.tsx b/app/client/src/git/components/BranchList/index.tsx index 4df8c84927a1..ee81302ee097 100644 --- a/app/client/src/git/components/BranchList/index.tsx +++ b/app/client/src/git/components/BranchList/index.tsx @@ -1,7 +1,7 @@ import React from "react"; import BranchListView from "./BranchListView"; import useBranches from "git/hooks/useBranches"; -import useDefaultBranch from "git/hooks/useDefaultBranch"; +import useDefaultBranch from "git/ee/hooks/useDefaultBranch"; import useProtectedBranches from "git/hooks/useProtectedBranches"; function BranchList() { From 52b5c4ff17a768bb450eee5b71665ab3619c69c5 Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Tue, 17 Dec 2024 01:59:28 +0800 Subject: [PATCH 076/143] chore: adding ff --- .../ContinuousDelivery/CDUnLicensed/index.tsx | 58 +++++++++++++++++++ .../components/ContinuousDelivery/index.tsx | 54 +---------------- 2 files changed, 60 insertions(+), 52 deletions(-) create mode 100644 app/client/src/git/ce/components/ContinuousDelivery/CDUnLicensed/index.tsx diff --git a/app/client/src/git/ce/components/ContinuousDelivery/CDUnLicensed/index.tsx b/app/client/src/git/ce/components/ContinuousDelivery/CDUnLicensed/index.tsx new file mode 100644 index 000000000000..b76e6d9d5528 --- /dev/null +++ b/app/client/src/git/ce/components/ContinuousDelivery/CDUnLicensed/index.tsx @@ -0,0 +1,58 @@ +import { + CONFIGURE_CD_DESC, + CONFIGURE_CD_TITLE, + TRY_APPSMITH_ENTERPRISE, + createMessage, +} from "ee/constants/messages"; +import { Button, Text } from "@appsmith/ads"; +import { useAppsmithEnterpriseLink } from "pages/Editor/gitSync/GitSettingsModal/TabBranch/hooks"; +import React from "react"; +import styled from "styled-components"; + +export const Container = styled.div` + padding-top: 8px; + padding-bottom: 16px; + overflow: auto; + min-height: calc(360px + 52px); +`; + +export const SectionTitle = styled(Text)` + font-weight: 600; + margin-bottom: 4px; +`; + +export const SectionDesc = styled(Text)` + margin-bottom: 12px; +`; + +export const StyledButton = styled(Button)` + display: inline-block; +`; + +function CDUnLicnesed() { + const enterprisePricingLink = useAppsmithEnterpriseLink( + "git_continuous_delivery", + ); + + return ( + + + {createMessage(CONFIGURE_CD_TITLE)} + + + {createMessage(CONFIGURE_CD_DESC)} + + + {createMessage(TRY_APPSMITH_ENTERPRISE)} + + + ); +} + +export default CDUnLicnesed; diff --git a/app/client/src/git/ce/components/ContinuousDelivery/index.tsx b/app/client/src/git/ce/components/ContinuousDelivery/index.tsx index 932f248a4447..90e2fd68c1a1 100644 --- a/app/client/src/git/ce/components/ContinuousDelivery/index.tsx +++ b/app/client/src/git/ce/components/ContinuousDelivery/index.tsx @@ -1,58 +1,8 @@ -import { - CONFIGURE_CD_DESC, - CONFIGURE_CD_TITLE, - TRY_APPSMITH_ENTERPRISE, - createMessage, -} from "ee/constants/messages"; -import { Button, Text } from "@appsmith/ads"; -import { useAppsmithEnterpriseLink } from "pages/Editor/gitSync/GitSettingsModal/TabBranch/hooks"; import React from "react"; -import styled from "styled-components"; - -export const Container = styled.div` - padding-top: 8px; - padding-bottom: 16px; - overflow: auto; - min-height: calc(360px + 52px); -`; - -export const SectionTitle = styled(Text)` - font-weight: 600; - margin-bottom: 4px; -`; - -export const SectionDesc = styled(Text)` - margin-bottom: 12px; -`; - -export const StyledButton = styled(Button)` - display: inline-block; -`; +import CDUnLicnesed from "./CDUnLicensed"; function ContinuousDelivery() { - const enterprisePricingLink = useAppsmithEnterpriseLink( - "git_continuous_delivery", - ); - - return ( - - - {createMessage(CONFIGURE_CD_TITLE)} - - - {createMessage(CONFIGURE_CD_DESC)} - - - {createMessage(TRY_APPSMITH_ENTERPRISE)} - - - ); + return ; } export default ContinuousDelivery; From f789c5af928e45a86dc54e972c3a3f2f1db2fc36 Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Tue, 17 Dec 2024 02:14:18 +0800 Subject: [PATCH 077/143] chore: unlicensed cd --- .../ce/components/ContinuousDelivery/CDUnLicensed/index.tsx | 4 ++-- .../ee/components/ContinuousDelivery/CDUnLicensed/index.tsx | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 app/client/src/git/ee/components/ContinuousDelivery/CDUnLicensed/index.tsx diff --git a/app/client/src/git/ce/components/ContinuousDelivery/CDUnLicensed/index.tsx b/app/client/src/git/ce/components/ContinuousDelivery/CDUnLicensed/index.tsx index b76e6d9d5528..a3eb5e0ac988 100644 --- a/app/client/src/git/ce/components/ContinuousDelivery/CDUnLicensed/index.tsx +++ b/app/client/src/git/ce/components/ContinuousDelivery/CDUnLicensed/index.tsx @@ -29,7 +29,7 @@ export const StyledButton = styled(Button)` display: inline-block; `; -function CDUnLicnesed() { +function CDUnLicensed() { const enterprisePricingLink = useAppsmithEnterpriseLink( "git_continuous_delivery", ); @@ -55,4 +55,4 @@ function CDUnLicnesed() { ); } -export default CDUnLicnesed; +export default CDUnLicensed; diff --git a/app/client/src/git/ee/components/ContinuousDelivery/CDUnLicensed/index.tsx b/app/client/src/git/ee/components/ContinuousDelivery/CDUnLicensed/index.tsx new file mode 100644 index 000000000000..4cd038c19dfe --- /dev/null +++ b/app/client/src/git/ee/components/ContinuousDelivery/CDUnLicensed/index.tsx @@ -0,0 +1 @@ +export { default } from "git/ce/components/ContinuousDelivery/CDUnLicensed"; From 34d96b492e20118aa5d82bfa10b9f09315b2bc60 Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Tue, 17 Dec 2024 23:59:15 +0800 Subject: [PATCH 078/143] chore: fixing typo --- app/client/src/git/ce/components/ContinuousDelivery/index.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/client/src/git/ce/components/ContinuousDelivery/index.tsx b/app/client/src/git/ce/components/ContinuousDelivery/index.tsx index 90e2fd68c1a1..0246dbc180ce 100644 --- a/app/client/src/git/ce/components/ContinuousDelivery/index.tsx +++ b/app/client/src/git/ce/components/ContinuousDelivery/index.tsx @@ -1,8 +1,8 @@ import React from "react"; -import CDUnLicnesed from "./CDUnLicensed"; +import CDUnLicensed from "./CDUnLicensed"; function ContinuousDelivery() { - return ; + return ; } export default ContinuousDelivery; From 48314348a9aa80a0c64b51de0f92d4c1795f5262 Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Wed, 18 Dec 2024 02:07:31 +0800 Subject: [PATCH 079/143] chore: adding integration behind feature flag --- app/client/src/ce/entities/FeatureFlag.ts | 2 + .../src/ce/pages/Applications/index.tsx | 16 +++- app/client/src/ce/reducers/index.tsx | 4 + app/client/src/ce/sagas/index.tsx | 4 + app/client/src/components/BottomBar/index.tsx | 24 ++++-- .../GitApplicationContextProvider.tsx | 37 +++++++++ .../src/entities/Engine/AppEditorEngine.ts | 75 ++++++++++++------- .../src/git/components/ImportModal/index.tsx | 7 +- app/client/src/pages/Editor/index.tsx | 69 ++++++++++------- app/client/src/selectors/gitSyncSelectors.tsx | 6 ++ 10 files changed, 179 insertions(+), 65 deletions(-) create mode 100644 app/client/src/components/gitContexts/GitApplicationContextProvider.tsx diff --git a/app/client/src/ce/entities/FeatureFlag.ts b/app/client/src/ce/entities/FeatureFlag.ts index de41ab80134d..e1584bbef430 100644 --- a/app/client/src/ce/entities/FeatureFlag.ts +++ b/app/client/src/ce/entities/FeatureFlag.ts @@ -48,6 +48,7 @@ export const FEATURE_FLAG = { "release_table_html_column_type_enabled", release_gs_all_sheets_options_enabled: "release_gs_all_sheets_options_enabled", + release_git_modularisation_enabled: "release_git_modularisation_enabled", } as const; export type FeatureFlag = keyof typeof FEATURE_FLAG; @@ -89,6 +90,7 @@ export const DEFAULT_FEATURE_FLAG_VALUE: FeatureFlags = { release_evaluation_scope_cache: false, release_table_html_column_type_enabled: false, release_gs_all_sheets_options_enabled: false, + release_git_modularisation_enabled: false, }; export const AB_TESTING_EVENT_KEYS = { diff --git a/app/client/src/ce/pages/Applications/index.tsx b/app/client/src/ce/pages/Applications/index.tsx index edd2b60af280..e761eb007a4a 100644 --- a/app/client/src/ce/pages/Applications/index.tsx +++ b/app/client/src/ce/pages/Applications/index.tsx @@ -122,7 +122,6 @@ import { MOBILE_MAX_WIDTH } from "constants/AppConstants"; import { Indices } from "constants/Layers"; import ImportModal from "pages/common/ImportModal"; import SharedUserList from "pages/common/SharedUserList"; -import GitSyncModal from "pages/Editor/gitSync/GitSyncModal"; import ReconnectDatasourceModal from "pages/Editor/gitSync/ReconnectDatasourceModal"; import RepoLimitExceededErrorModal from "pages/Editor/gitSync/RepoLimitExceededErrorModal"; import AnalyticsUtil from "ee/utils/AnalyticsUtil"; @@ -133,6 +132,15 @@ import { getAssetUrl } from "ee/utils/airgapHelpers"; import { ASSETS_CDN_URL } from "constants/ThirdPartyConstants"; import { LayoutSystemTypes } from "layoutSystems/types"; import { getIsAnvilLayoutEnabled } from "layoutSystems/anvil/integrations/selectors"; +import { isGitModEnabledSelector } from "selectors/gitSyncSelectors"; +import OldGitSyncModal from "pages/Editor/gitSync/GitSyncModal"; +import { GitImportModal as NewGitImportModal } from "git/components"; + +function GitImportModals() { + const isGitModEnabled = useSelector(isGitModEnabledSelector); + + return isGitModEnabled ? : ; +} export const { cloudHosting } = getAppsmithConfigs(); @@ -955,7 +963,11 @@ export function ApplicationsSection(props: any) { isMobile={isMobile} > {workspacesListComponent} - + + {/* + + */} + {/* */} ); diff --git a/app/client/src/ce/reducers/index.tsx b/app/client/src/ce/reducers/index.tsx index 90790e6fe4bf..587ceae513dd 100644 --- a/app/client/src/ce/reducers/index.tsx +++ b/app/client/src/ce/reducers/index.tsx @@ -78,6 +78,7 @@ import type { ActiveField } from "reducers/uiReducers/activeFieldEditorReducer"; import type { SelectedWorkspaceReduxState } from "ee/reducers/uiReducers/selectedWorkspaceReducer"; import type { ConsolidatedPageLoadState } from "reducers/uiReducers/consolidatedPageLoadReducer"; import type { BuildingBlocksReduxState } from "reducers/uiReducers/buildingBlockReducer"; +import { gitReducer } from "git/store"; export const reducerObject = { entities: entityReducer, @@ -87,6 +88,9 @@ export const reducerObject = { settings: SettingsReducer, tenant: tenantReducer, linting: lintErrorReducer, + // not sure what is the best way to integrate git reducer behind a feature flag + // although integrating it directly should be fine as it will not be used unless the feature is enabled + git: gitReducer, }; export interface AppState { diff --git a/app/client/src/ce/sagas/index.tsx b/app/client/src/ce/sagas/index.tsx index 844f9406af82..faf51e80f84b 100644 --- a/app/client/src/ce/sagas/index.tsx +++ b/app/client/src/ce/sagas/index.tsx @@ -49,6 +49,7 @@ import communityTemplateSagas from "sagas/CommunityTemplatesSagas"; import anvilSagas from "layoutSystems/anvil/integrations/sagas"; import ideSagas from "sagas/IDESaga"; import sendSideBySideWidgetHoverAnalyticsEventSaga from "sagas/AnalyticsSaga"; +import gitSagas from "git/sagas"; /* Sagas that are registered by a module that is designed to be independent of the core platform */ import ternSagas from "sagas/TernSaga"; @@ -106,4 +107,7 @@ export const sagas = [ ternSagas, ideSagas, sendSideBySideWidgetHoverAnalyticsEventSaga, + // not sure what is the best way to integrate git sagas behind a feature flag + // although integrating it directly should be fine as it will not be used unless the feature is enabled + gitSagas, ]; diff --git a/app/client/src/components/BottomBar/index.tsx b/app/client/src/components/BottomBar/index.tsx index 565844eacfb4..03ca13d319e4 100644 --- a/app/client/src/components/BottomBar/index.tsx +++ b/app/client/src/components/BottomBar/index.tsx @@ -1,5 +1,4 @@ -import React from "react"; -import QuickGitActions from "pages/Editor/gitSync/QuickGitActions"; +import React, { useCallback } from "react"; import { DebuggerTrigger } from "components/editorComponents/Debugger"; import HelpButton from "pages/Editor/HelpButton"; import ManualUpgrades from "./ManualUpgrades"; @@ -16,19 +15,30 @@ import { softRefreshActions } from "actions/pluginActionActions"; import { START_SWITCH_ENVIRONMENT } from "ee/constants/messages"; import { getIsAnvilEnabledInCurrentApplication } from "layoutSystems/anvil/integrations/selectors"; import PackageUpgradeStatus from "ee/components/BottomBar/PackageUpgradeStatus"; +import OldGitQuickActions from "pages/Editor/gitSync/QuickGitActions"; +import { GitQuickActions } from "git/components"; +import { isGitModEnabledSelector } from "selectors/gitSyncSelectors"; + +function GitActions() { + const isGitModEnabled = useSelector(isGitModEnabledSelector); + + return isGitModEnabled ? : ; +} export default function BottomBar() { const appId = useSelector(getCurrentApplicationId) || ""; - const isPreviewMode = useSelector(previewModeSelector); - const dispatch = useDispatch(); // We check if the current application is an Anvil application. // If it is an Anvil application, we remove the Git features from the bottomBar // as they donot yet work correctly with Anvil. const isAnvilEnabled = useSelector(getIsAnvilEnabledInCurrentApplication); + const isPreviewMode = useSelector(previewModeSelector); + const isGitEnabled = !isAnvilEnabled && !isPreviewMode; + + const dispatch = useDispatch(); - const onChangeEnv = () => { + const onChangeEnv = useCallback(() => { dispatch(softRefreshActions()); - }; + }, [dispatch]); return ( @@ -41,7 +51,7 @@ export default function BottomBar() { viewMode={isPreviewMode} /> )} - {!isPreviewMode && !isAnvilEnabled && } + {isGitEnabled && } {!isPreviewMode && ( diff --git a/app/client/src/components/gitContexts/GitApplicationContextProvider.tsx b/app/client/src/components/gitContexts/GitApplicationContextProvider.tsx new file mode 100644 index 000000000000..cafdc520eb67 --- /dev/null +++ b/app/client/src/components/gitContexts/GitApplicationContextProvider.tsx @@ -0,0 +1,37 @@ +import React from "react"; +import { useSelector } from "react-redux"; +import { getCurrentApplication } from "ee/selectors/applicationSelectors"; +import GitContextProvider from "git/components/GitContextProvider"; +import { GitArtifactType } from "git/constants/enums"; +import applicationStatusTransformer from "git/artifactHelpers/application/statusTransformer"; +import { hasCreateNewAppPermission } from "ee/utils/permissionHelpers"; +import { setWorkspaceIdForImport } from "ee/actions/applicationActions"; +import { getCurrentAppWorkspace } from "ee/selectors/selectedWorkspaceSelectors"; + +interface GitApplicationContextProviderProps { + children: React.ReactNode; +} + +export default function GitApplicationContextProvider({ + children, +}: GitApplicationContextProviderProps) { + const artifactType = GitArtifactType.Application; + const application = useSelector(getCurrentApplication); + const workspace = useSelector(getCurrentAppWorkspace); + const isCreateNewApplicationPermitted = hasCreateNewAppPermission( + workspace.userPermissions, + ); + + return ( + + {children} + + ); +} diff --git a/app/client/src/entities/Engine/AppEditorEngine.ts b/app/client/src/entities/Engine/AppEditorEngine.ts index b69063d05cd1..36db144e28ed 100644 --- a/app/client/src/entities/Engine/AppEditorEngine.ts +++ b/app/client/src/entities/Engine/AppEditorEngine.ts @@ -1,14 +1,4 @@ import { fetchMockDatasources } from "actions/datasourceActions"; -import { - fetchGitProtectedBranchesInit, - fetchGitStatusInit, - remoteUrlInputValue, - resetPullMergeStatus, - fetchBranchesInit, - triggerAutocommitInitAction, - getGitMetadataInitAction, -} from "actions/gitSyncActions"; -import { restoreRecentEntitiesRequest } from "actions/globalSearchActions"; import { resetEditorSuccess } from "actions/initActions"; import { fetchAllPageEntityCompletion, @@ -24,7 +14,6 @@ import { ReduxActionErrorTypes, ReduxActionTypes, } from "ee/constants/ReduxActionConstants"; -import { addBranchParam } from "constants/routes"; import type { APP_MODE } from "entities/App"; import { call, fork, put, select, spawn } from "redux-saga/effects"; import type { EditConsolidatedApi } from "sagas/InitSagas"; @@ -35,10 +24,11 @@ import { } from "sagas/InitSagas"; import { getCurrentGitBranch, + isGitModEnabledSelector, isGitPersistBranchEnabledSelector, } from "selectors/gitSyncSelectors"; import AnalyticsUtil from "ee/utils/AnalyticsUtil"; -import history from "utils/history"; +// import history from "utils/history"; import type { AppEnginePayload } from "."; import AppEngine, { ActionsNotFoundError, @@ -74,6 +64,20 @@ import { endSpan, startNestedSpan } from "UITelemetry/generateTraces"; import { getCurrentUser } from "selectors/usersSelectors"; import type { User } from "constants/userConstants"; import log from "loglevel"; +import { gitArtifactActions } from "git/store/gitArtifactSlice"; +import { GitArtifactType } from "git/constants/enums"; +import { restoreRecentEntitiesRequest } from "actions/globalSearchActions"; +import { + fetchBranchesInit, + fetchGitProtectedBranchesInit, + fetchGitStatusInit, + getGitMetadataInitAction, + remoteUrlInputValue, + resetPullMergeStatus, + triggerAutocommitInitAction, +} from "actions/gitSyncActions"; +import history from "utils/history"; +import { addBranchParam } from "constants/routes"; export default class AppEditorEngine extends AppEngine { constructor(mode: APP_MODE) { @@ -292,6 +296,7 @@ export default class AppEditorEngine extends AppEngine { const currentApplication: ApplicationPayload = yield select( getCurrentApplication, ); + const currentBranch: string = yield select(getCurrentGitBranch); const isGitPersistBranchEnabled: boolean = yield select( isGitPersistBranchEnabledSelector, @@ -299,7 +304,6 @@ export default class AppEditorEngine extends AppEngine { if (isGitPersistBranchEnabled) { const currentUser: User = yield select(getCurrentUser); - const currentBranch: string = yield select(getCurrentGitBranch); if (currentUser?.email && currentApplication?.baseId && currentBranch) { yield setLatestGitBranchInLocal( @@ -328,6 +332,15 @@ export default class AppEditorEngine extends AppEngine { }); } + if (currentApplication?.id) { + yield put( + restoreRecentEntitiesRequest({ + applicationId: currentApplication.id, + branch: currentBranch, + }), + ); + } + if (isFirstTimeUserOnboardingComplete) { yield put({ type: ReduxActionTypes.SET_FIRST_TIME_USER_ONBOARDING_APPLICATION_IDS, @@ -370,22 +383,31 @@ export default class AppEditorEngine extends AppEngine { public *loadGit(applicationId: string, rootSpan: Span) { const loadGitSpan = startNestedSpan("AppEditorEngine.loadGit", rootSpan); + const isGitModEnabled: boolean = yield select(isGitModEnabledSelector); - const branchInStore: string = yield select(getCurrentGitBranch); + if (isGitModEnabled) { + const currentApplication: ApplicationPayload = yield select( + getCurrentApplication, + ); - yield put( - restoreRecentEntitiesRequest({ - applicationId, - branch: branchInStore, - }), - ); - // init of temporary remote url from old application - yield put(remoteUrlInputValue({ tempRemoteUrl: "" })); - // add branch query to path and fetch status + yield put( + gitArtifactActions.initGitForEditor({ + artifactType: GitArtifactType.Application, + baseArtifactId: currentApplication.baseId, + artifact: currentApplication, + }), + ); + } else { + const currentBranch: string = yield select(getCurrentGitBranch); + + // init of temporary remote url from old application + yield put(remoteUrlInputValue({ tempRemoteUrl: "" })); + // add branch query to path and fetch status - if (branchInStore) { - history.replace(addBranchParam(branchInStore)); - yield fork(this.loadGitInBackground); + if (currentBranch) { + history.replace(addBranchParam(currentBranch)); + yield fork(this.loadGitInBackground); + } } endSpan(loadGitSpan); @@ -394,7 +416,6 @@ export default class AppEditorEngine extends AppEngine { private *loadGitInBackground() { yield put(fetchBranchesInit()); yield put(fetchGitProtectedBranchesInit()); - yield put(fetchGitProtectedBranchesInit()); yield put(getGitMetadataInitAction()); yield put(triggerAutocommitInitAction()); yield put(fetchGitStatusInit({ compareRemote: true })); diff --git a/app/client/src/git/components/ImportModal/index.tsx b/app/client/src/git/components/ImportModal/index.tsx index f55a468d702b..a5199e49c355 100644 --- a/app/client/src/git/components/ImportModal/index.tsx +++ b/app/client/src/git/components/ImportModal/index.tsx @@ -1,8 +1,9 @@ -import React from "react"; -import ConnectModal from "../ConnectModal"; +// import React from "react"; +// import ConnectModal from "../ConnectModal"; function ImportModal() { - return ; + // return ; + return null; } export default ImportModal; diff --git a/app/client/src/pages/Editor/index.tsx b/app/client/src/pages/Editor/index.tsx index a7bfff34f2cb..739cf04c3d00 100644 --- a/app/client/src/pages/Editor/index.tsx +++ b/app/client/src/pages/Editor/index.tsx @@ -1,6 +1,6 @@ import React, { Component } from "react"; import { Helmet } from "react-helmet"; -import { connect } from "react-redux"; +import { connect, useSelector } from "react-redux"; import type { RouteComponentProps } from "react-router-dom"; import { withRouter } from "react-router-dom"; import type { BuilderRouteParams } from "constants/routes"; @@ -25,12 +25,9 @@ import { getTheme, ThemeMode } from "selectors/themeSelectors"; import { ThemeProvider } from "styled-components"; import type { Theme } from "constants/DefaultTheme"; import GlobalHotKeys from "./GlobalHotKeys"; -import GitSyncModal from "pages/Editor/gitSync/GitSyncModal"; -import DisconnectGitModal from "pages/Editor/gitSync/DisconnectGitModal"; import { setupPageAction, updateCurrentPage } from "actions/pageActions"; import { getCurrentPageId } from "selectors/editorSelectors"; import { getSearchQuery } from "utils/helpers"; -import RepoLimitExceededErrorModal from "./gitSync/RepoLimitExceededErrorModal"; import ImportedApplicationSuccessModal from "./gitSync/ImportSuccessModal"; import { getIsBranchUpdated } from "../utils"; import { APP_MODE } from "entities/App"; @@ -42,16 +39,40 @@ import SignpostingOverlay from "pages/Editor/FirstTimeUserOnboarding/Overlay"; import { editorInitializer } from "../../utils/editor/EditorUtils"; import { widgetInitialisationSuccess } from "../../actions/widgetActions"; import urlBuilder from "ee/entities/URLRedirect/URLAssembly"; -import DisableAutocommitModal from "./gitSync/DisableAutocommitModal"; -import GitSettingsModal from "./gitSync/GitSettingsModal"; -import ReconfigureCDKeyModal from "ee/components/gitComponents/ReconfigureCDKeyModal"; -import DisableCDModal from "ee/components/gitComponents/DisableCDModal"; import { PartialExportModal } from "components/editorComponents/PartialImportExport/PartialExportModal"; import { PartialImportModal } from "components/editorComponents/PartialImportExport/PartialImportModal"; import type { Page } from "entities/Page"; import { AppCURLImportModal } from "ee/pages/Editor/CurlImport"; import { IDE_HEADER_HEIGHT } from "@appsmith/ads"; import GeneratePageModal from "./GeneratePage"; +import { GitModals as NewGitModals } from "git/components"; +import GitApplicationContextProvider from "components/gitContexts/GitApplicationContextProvider"; +import { isGitModEnabledSelector } from "selectors/gitSyncSelectors"; +import GitSyncModal from "./gitSync/GitSyncModal"; +import GitSettingsModal from "./gitSync/GitSettingsModal"; +import DisconnectGitModal from "./gitSync/DisconnectGitModal"; +import DisableAutocommitModal from "./gitSync/DisableAutocommitModal"; +import ReconfigureCDKeyModal from "ee/components/gitComponents/ReconfigureCDKeyModal"; +import DisableCDModal from "ee/components/gitComponents/DisableCDModal"; +import RepoLimitExceededErrorModal from "./gitSync/RepoLimitExceededErrorModal"; + +function GitModals() { + const isGitModEnabled = useSelector(isGitModEnabledSelector); + + return isGitModEnabled ? ( + + ) : ( + <> + + + + + + + + + ); +} interface EditorProps { currentApplicationId?: string; @@ -195,24 +216,20 @@ class Editor extends Component { {`${this.props.currentApplicationName} | Editor | Appsmith`} - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + diff --git a/app/client/src/selectors/gitSyncSelectors.tsx b/app/client/src/selectors/gitSyncSelectors.tsx index bf3b009667bf..6017c2de282b 100644 --- a/app/client/src/selectors/gitSyncSelectors.tsx +++ b/app/client/src/selectors/gitSyncSelectors.tsx @@ -286,3 +286,9 @@ export const isGitPersistBranchEnabledSelector = createSelector( selectFeatureFlags, (featureFlags) => featureFlags.release_git_persist_branch_enabled ?? false, ); + +export const isGitModEnabledSelector = createSelector( + selectFeatureFlags, + // (featureFlags) => featureFlags.release_git_modularisation_enabled ?? false, + () => true, +); From df628d78f17733356a6f35529c3586d18539f88f Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Wed, 18 Dec 2024 03:44:27 +0800 Subject: [PATCH 080/143] chore: mod flag for components and selectors --- .../FocusStrategy/AppIDEFocusStrategy.ts | 16 +++++-- .../src/ce/pages/Applications/index.tsx | 6 +-- app/client/src/ce/reducers/index.tsx | 10 ++++- app/client/src/ce/sagas/PageSagas.tsx | 10 ++++- app/client/src/ce/sagas/index.tsx | 2 +- app/client/src/components/BottomBar/index.tsx | 6 +-- .../appsmith/header/DeployLinkButton.tsx | 4 +- .../editorComponents/GlobalSearch/HelpBar.tsx | 40 +++++++---------- .../GitApplicationContextProvider.tsx | 5 +-- .../src/entities/Engine/AppEditorEngine.ts | 27 ++++++++---- .../application/applicationArtifact.ts | 11 +++++ .../applicationStatusTransformer.ts} | 0 .../git/artifact-helpers/application/index.ts | 2 + .../ConnectModal/ConnectModalView.tsx | 6 +-- .../src/git/components/ConnectModal/index.tsx | 6 ++- .../src/git/components/OpsModal/index.tsx | 4 +- .../QuickActions/QuickActionsView.test.tsx | 30 ++++++------- .../QuickActions/QuickActionsView.tsx | 6 +-- .../src/git/components/QuickActions/index.tsx | 10 ++--- app/client/src/git/components/index.tsx | 3 -- app/client/src/git/hooks/useConnected.ts | 14 ++++++ app/client/src/git/hooks/useCurrentBranch.ts | 8 ++++ app/client/src/git/hooks/useMetadata.ts | 10 +---- .../src/git/hooks/useProtectedBranches.ts | 6 --- app/client/src/git/hooks/useProtectedMode.ts | 14 ++++++ app/client/src/git/index.ts | 22 ++++++++++ .../selectors/gitSingleArtifactSelectors.ts | 2 +- .../pages/Editor/gitSync/hooks/modHooks.ts | 44 +++++++++++++++++++ app/client/src/pages/Editor/index.tsx | 8 ++-- app/client/src/selectors/gitModSelectors.ts | 27 ++++++++++++ app/client/src/selectors/gitSyncSelectors.tsx | 6 --- 31 files changed, 255 insertions(+), 110 deletions(-) create mode 100644 app/client/src/git/artifact-helpers/application/applicationArtifact.ts rename app/client/src/git/{artifactHelpers/application/statusTransformer.ts => artifact-helpers/application/applicationStatusTransformer.ts} (100%) create mode 100644 app/client/src/git/artifact-helpers/application/index.ts delete mode 100644 app/client/src/git/components/index.tsx create mode 100644 app/client/src/git/hooks/useConnected.ts create mode 100644 app/client/src/git/hooks/useCurrentBranch.ts create mode 100644 app/client/src/git/hooks/useProtectedMode.ts create mode 100644 app/client/src/git/index.ts create mode 100644 app/client/src/pages/Editor/gitSync/hooks/modHooks.ts create mode 100644 app/client/src/selectors/gitModSelectors.ts diff --git a/app/client/src/ce/navigation/FocusStrategy/AppIDEFocusStrategy.ts b/app/client/src/ce/navigation/FocusStrategy/AppIDEFocusStrategy.ts index 5729a7e8c59d..5eaabd59a60e 100644 --- a/app/client/src/ce/navigation/FocusStrategy/AppIDEFocusStrategy.ts +++ b/app/client/src/ce/navigation/FocusStrategy/AppIDEFocusStrategy.ts @@ -2,7 +2,6 @@ import { all, select, take } from "redux-saga/effects"; import type { FocusPath, FocusStrategy } from "sagas/FocusRetentionSaga"; import type { AppsmithLocationState } from "utils/history"; import { NavigationMethod } from "utils/history"; -import { getCurrentGitBranch } from "selectors/gitSyncSelectors"; import type { FocusEntityInfo } from "navigation/FocusEntity"; import { FocusEntity, @@ -18,6 +17,9 @@ import { widgetListURL, } from "ee/RouteBuilder"; import AppIDEFocusElements from "../FocusElements/AppIDE"; +import { getCurrentBaseApplicationId } from "selectors/editorSelectors"; +import { selectGitCurrentBranch } from "selectors/gitModSelectors"; +import { applicationArtifact } from "git/artifact-helpers/application"; function shouldSetState( prevPath: string, @@ -109,7 +111,11 @@ export const AppIDEFocusStrategy: FocusStrategy = { return []; } - const branch: string | undefined = yield select(getCurrentGitBranch); + const baseApplicationId: string = yield select(getCurrentBaseApplicationId); + const branch: string | undefined = yield select( + selectGitCurrentBranch, + applicationArtifact(baseApplicationId), + ); const entities: Array<{ entityInfo: FocusEntityInfo; key: string }> = []; const prevEntityInfo = identifyEntityFromPath(previousPath); const currentEntityInfo = identifyEntityFromPath(currentPath); @@ -136,7 +142,11 @@ export const AppIDEFocusStrategy: FocusStrategy = { return entities; }, *getEntitiesForStore(path: string, currentPath: string) { - const branch: string | undefined = yield select(getCurrentGitBranch); + const baseApplicationId: string = yield select(getCurrentBaseApplicationId); + const branch: string | undefined = yield select( + selectGitCurrentBranch, + applicationArtifact(baseApplicationId), + ); const entities: Array = []; const currentFocusEntityInfo = identifyEntityFromPath(currentPath); const prevFocusEntityInfo = identifyEntityFromPath(path); diff --git a/app/client/src/ce/pages/Applications/index.tsx b/app/client/src/ce/pages/Applications/index.tsx index e761eb007a4a..3f7c476113f0 100644 --- a/app/client/src/ce/pages/Applications/index.tsx +++ b/app/client/src/ce/pages/Applications/index.tsx @@ -132,12 +132,12 @@ import { getAssetUrl } from "ee/utils/airgapHelpers"; import { ASSETS_CDN_URL } from "constants/ThirdPartyConstants"; import { LayoutSystemTypes } from "layoutSystems/types"; import { getIsAnvilLayoutEnabled } from "layoutSystems/anvil/integrations/selectors"; -import { isGitModEnabledSelector } from "selectors/gitSyncSelectors"; import OldGitSyncModal from "pages/Editor/gitSync/GitSyncModal"; -import { GitImportModal as NewGitImportModal } from "git/components"; +import { GitImportModal as NewGitImportModal } from "git"; +import { useGitModEnabled } from "pages/Editor/gitSync/hooks/modHooks"; function GitImportModals() { - const isGitModEnabled = useSelector(isGitModEnabledSelector); + const isGitModEnabled = useGitModEnabled(); return isGitModEnabled ? : ; } diff --git a/app/client/src/ce/reducers/index.tsx b/app/client/src/ce/reducers/index.tsx index 587ceae513dd..188f16fef0a4 100644 --- a/app/client/src/ce/reducers/index.tsx +++ b/app/client/src/ce/reducers/index.tsx @@ -78,7 +78,11 @@ import type { ActiveField } from "reducers/uiReducers/activeFieldEditorReducer"; import type { SelectedWorkspaceReduxState } from "ee/reducers/uiReducers/selectedWorkspaceReducer"; import type { ConsolidatedPageLoadState } from "reducers/uiReducers/consolidatedPageLoadReducer"; import type { BuildingBlocksReduxState } from "reducers/uiReducers/buildingBlockReducer"; -import { gitReducer } from "git/store"; +import { gitReducer } from "git"; +import type { + GitArtifactReduxState, + GitConfigReduxState, +} from "git/store/types"; export const reducerObject = { entities: entityReducer, @@ -182,4 +186,8 @@ export interface AppState { // TODO: Fix this the next time the file is edited // eslint-disable-next-line @typescript-eslint/no-explicit-any tenant: TenantReduxState; + git: { + config: GitConfigReduxState; + artifacts: GitArtifactReduxState; + }; } diff --git a/app/client/src/ce/sagas/PageSagas.tsx b/app/client/src/ce/sagas/PageSagas.tsx index d1c8e1e86837..08a8e1d173d1 100644 --- a/app/client/src/ce/sagas/PageSagas.tsx +++ b/app/client/src/ce/sagas/PageSagas.tsx @@ -77,6 +77,7 @@ import type { ApiResponse } from "api/ApiResponses"; import { combinedPreviewModeSelector, getCurrentApplicationId, + getCurrentBaseApplicationId, getCurrentLayoutId, getCurrentPageId, getCurrentPageName, @@ -128,7 +129,6 @@ import { getPageList } from "ee/selectors/entitiesSelector"; import { setPreviewModeAction } from "actions/editorActions"; import { SelectionRequestType } from "sagas/WidgetSelectUtils"; import { toast } from "@appsmith/ads"; -import { getCurrentGitBranch } from "selectors/gitSyncSelectors"; import type { MainCanvasReduxState } from "reducers/uiReducers/mainCanvasReducer"; import { UserCancelledActionExecutionError } from "sagas/ActionExecution/errorUtils"; import { getInstanceId } from "ee/selectors/tenantSelectors"; @@ -150,6 +150,8 @@ import { getIsAnvilLayout } from "layoutSystems/anvil/integrations/selectors"; import { convertToBasePageIdSelector } from "selectors/pageListSelectors"; import type { Page } from "entities/Page"; import { ConsolidatedPageLoadApi } from "api"; +import { selectGitCurrentBranch } from "selectors/gitModSelectors"; +import { applicationArtifact } from "git/artifact-helpers/application"; export const checkIfMigrationIsNeeded = ( fetchPageResponse?: FetchPageResponse, @@ -172,7 +174,11 @@ export function* refreshTheApp() { const currentPageId: string = yield select(getCurrentPageId); const defaultBasePageId: string = yield select(getDefaultBasePageId); const pagesList: Page[] = yield select(getPageList); - const gitBranch: string = yield select(getCurrentGitBranch); + const baseApplicationId: string = yield select(getCurrentBaseApplicationId); + const gitBranch: string | undefined = yield select( + selectGitCurrentBranch, + applicationArtifact(baseApplicationId), + ); const isCurrentPageIdInList = pagesList.filter((page) => page.pageId === currentPageId).length > 0; diff --git a/app/client/src/ce/sagas/index.tsx b/app/client/src/ce/sagas/index.tsx index faf51e80f84b..1f7f79e90746 100644 --- a/app/client/src/ce/sagas/index.tsx +++ b/app/client/src/ce/sagas/index.tsx @@ -49,7 +49,7 @@ import communityTemplateSagas from "sagas/CommunityTemplatesSagas"; import anvilSagas from "layoutSystems/anvil/integrations/sagas"; import ideSagas from "sagas/IDESaga"; import sendSideBySideWidgetHoverAnalyticsEventSaga from "sagas/AnalyticsSaga"; -import gitSagas from "git/sagas"; +import { gitSagas } from "git"; /* Sagas that are registered by a module that is designed to be independent of the core platform */ import ternSagas from "sagas/TernSaga"; diff --git a/app/client/src/components/BottomBar/index.tsx b/app/client/src/components/BottomBar/index.tsx index 03ca13d319e4..1b7ad839d868 100644 --- a/app/client/src/components/BottomBar/index.tsx +++ b/app/client/src/components/BottomBar/index.tsx @@ -16,11 +16,11 @@ import { START_SWITCH_ENVIRONMENT } from "ee/constants/messages"; import { getIsAnvilEnabledInCurrentApplication } from "layoutSystems/anvil/integrations/selectors"; import PackageUpgradeStatus from "ee/components/BottomBar/PackageUpgradeStatus"; import OldGitQuickActions from "pages/Editor/gitSync/QuickGitActions"; -import { GitQuickActions } from "git/components"; -import { isGitModEnabledSelector } from "selectors/gitSyncSelectors"; +import { GitQuickActions } from "git"; +import { useGitModEnabled } from "pages/Editor/gitSync/hooks/modHooks"; function GitActions() { - const isGitModEnabled = useSelector(isGitModEnabledSelector); + const isGitModEnabled = useGitModEnabled(); return isGitModEnabled ? : ; } diff --git a/app/client/src/components/designSystems/appsmith/header/DeployLinkButton.tsx b/app/client/src/components/designSystems/appsmith/header/DeployLinkButton.tsx index 3257d962223b..4eca6a5eab18 100644 --- a/app/client/src/components/designSystems/appsmith/header/DeployLinkButton.tsx +++ b/app/client/src/components/designSystems/appsmith/header/DeployLinkButton.tsx @@ -2,7 +2,6 @@ import type { ReactNode } from "react"; import React from "react"; import { Menu, MenuItem, MenuContent, MenuTrigger } from "@appsmith/ads"; import { useSelector, useDispatch } from "react-redux"; -import { getIsGitConnected } from "selectors/gitSyncSelectors"; import { setIsGitSyncModalOpen } from "actions/gitSyncActions"; import { GitSyncModalTab } from "entities/GitSync"; import AnalyticsUtil from "ee/utils/AnalyticsUtil"; @@ -14,6 +13,7 @@ import { Button } from "@appsmith/ads"; import { KBEditorMenuItem } from "ee/pages/Editor/KnowledgeBase/KBEditorMenuItem"; import { useHasConnectToGitPermission } from "pages/Editor/gitSync/hooks/gitPermissionHooks"; import { getIsAnvilEnabledInCurrentApplication } from "layoutSystems/anvil/integrations/selectors"; +import { useGitConnected } from "pages/Editor/gitSync/hooks/modHooks"; interface Props { trigger: ReactNode; @@ -22,7 +22,7 @@ interface Props { export const DeployLinkButton = (props: Props) => { const dispatch = useDispatch(); - const isGitConnected = useSelector(getIsGitConnected); + const isGitConnected = useGitConnected(); const isConnectToGitPermitted = useHasConnectToGitPermission(); // We check if the current application is an Anvil application. // If it is an Anvil application, we remove the Git features from the deploy button diff --git a/app/client/src/components/editorComponents/GlobalSearch/HelpBar.tsx b/app/client/src/components/editorComponents/GlobalSearch/HelpBar.tsx index c52eb62c9ef2..0a8fb41ffabe 100644 --- a/app/client/src/components/editorComponents/GlobalSearch/HelpBar.tsx +++ b/app/client/src/components/editorComponents/GlobalSearch/HelpBar.tsx @@ -1,14 +1,13 @@ -import React from "react"; +import React, { useCallback } from "react"; import styled from "styled-components"; -import { connect } from "react-redux"; +import { useDispatch } from "react-redux"; import { getTypographyByKey, Text, TextType } from "@appsmith/ads-old"; import { Icon } from "@appsmith/ads"; import { setGlobalSearchCategory } from "actions/globalSearchActions"; import AnalyticsUtil from "ee/utils/AnalyticsUtil"; import { modText } from "utils/helpers"; import { filterCategories, SEARCH_CATEGORY_ID } from "./utils"; -import { protectedModeSelector } from "selectors/gitSyncSelectors"; -import type { AppState } from "ee/reducers"; +import { useGitProtectedMode } from "pages/Editor/gitSync/hooks/modHooks"; const StyledHelpBar = styled.button` padding: 0 var(--ads-v2-spaces-3); @@ -42,12 +41,18 @@ const StyledHelpBar = styled.button` } `; -interface Props { - toggleShowModal: () => void; - isProtectedMode: boolean; -} +function HelpBar() { + const isProtectedMode = useGitProtectedMode(); + + const dispatch = useDispatch(); + + const toggleShowModal = useCallback(() => { + AnalyticsUtil.logEvent("OPEN_OMNIBAR", { source: "NAVBAR_CLICK" }); + dispatch( + setGlobalSearchCategory(filterCategories[SEARCH_CATEGORY_ID.INIT]), + ); + }, [dispatch]); -function HelpBar({ isProtectedMode, toggleShowModal }: Props) { return ( ({ - isProtectedMode: protectedModeSelector(state), -}); - -// TODO: Fix this the next time the file is edited -// eslint-disable-next-line @typescript-eslint/no-explicit-any -const mapDispatchToProps = (dispatch: any) => ({ - toggleShowModal: () => { - AnalyticsUtil.logEvent("OPEN_OMNIBAR", { source: "NAVBAR_CLICK" }); - dispatch( - setGlobalSearchCategory(filterCategories[SEARCH_CATEGORY_ID.INIT]), - ); - }, -}); - -export default connect(mapStateToProps, mapDispatchToProps)(HelpBar); +export default HelpBar; diff --git a/app/client/src/components/gitContexts/GitApplicationContextProvider.tsx b/app/client/src/components/gitContexts/GitApplicationContextProvider.tsx index cafdc520eb67..728636e2f6dd 100644 --- a/app/client/src/components/gitContexts/GitApplicationContextProvider.tsx +++ b/app/client/src/components/gitContexts/GitApplicationContextProvider.tsx @@ -1,12 +1,11 @@ import React from "react"; import { useSelector } from "react-redux"; +import { GitArtifactType, GitContextProvider } from "git"; import { getCurrentApplication } from "ee/selectors/applicationSelectors"; -import GitContextProvider from "git/components/GitContextProvider"; -import { GitArtifactType } from "git/constants/enums"; -import applicationStatusTransformer from "git/artifactHelpers/application/statusTransformer"; import { hasCreateNewAppPermission } from "ee/utils/permissionHelpers"; import { setWorkspaceIdForImport } from "ee/actions/applicationActions"; import { getCurrentAppWorkspace } from "ee/selectors/selectedWorkspaceSelectors"; +import { applicationStatusTransformer } from "git/artifact-helpers/application"; interface GitApplicationContextProviderProps { children: React.ReactNode; diff --git a/app/client/src/entities/Engine/AppEditorEngine.ts b/app/client/src/entities/Engine/AppEditorEngine.ts index 36db144e28ed..41238aa2bc3d 100644 --- a/app/client/src/entities/Engine/AppEditorEngine.ts +++ b/app/client/src/entities/Engine/AppEditorEngine.ts @@ -22,11 +22,7 @@ import { reportSWStatus, waitForWidgetConfigBuild, } from "sagas/InitSagas"; -import { - getCurrentGitBranch, - isGitModEnabledSelector, - isGitPersistBranchEnabledSelector, -} from "selectors/gitSyncSelectors"; +import { isGitPersistBranchEnabledSelector } from "selectors/gitSyncSelectors"; import AnalyticsUtil from "ee/utils/AnalyticsUtil"; // import history from "utils/history"; import type { AppEnginePayload } from "."; @@ -78,6 +74,12 @@ import { } from "actions/gitSyncActions"; import history from "utils/history"; import { addBranchParam } from "constants/routes"; +import { + selectGitCurrentBranch, + selectGitModEnabled, +} from "selectors/gitModSelectors"; +import { getCurrentBaseApplicationId } from "selectors/editorSelectors"; +import { applicationArtifact } from "git/artifact-helpers/application"; export default class AppEditorEngine extends AppEngine { constructor(mode: APP_MODE) { @@ -296,7 +298,10 @@ export default class AppEditorEngine extends AppEngine { const currentApplication: ApplicationPayload = yield select( getCurrentApplication, ); - const currentBranch: string = yield select(getCurrentGitBranch); + const currentBranch: string | undefined = yield select( + selectGitCurrentBranch, + applicationArtifact(currentApplication.baseId), + ); const isGitPersistBranchEnabled: boolean = yield select( isGitPersistBranchEnabledSelector, @@ -383,7 +388,7 @@ export default class AppEditorEngine extends AppEngine { public *loadGit(applicationId: string, rootSpan: Span) { const loadGitSpan = startNestedSpan("AppEditorEngine.loadGit", rootSpan); - const isGitModEnabled: boolean = yield select(isGitModEnabledSelector); + const isGitModEnabled: boolean = yield select(selectGitModEnabled); if (isGitModEnabled) { const currentApplication: ApplicationPayload = yield select( @@ -398,7 +403,13 @@ export default class AppEditorEngine extends AppEngine { }), ); } else { - const currentBranch: string = yield select(getCurrentGitBranch); + const baseApplicationId: string = yield select( + getCurrentBaseApplicationId, + ); + const currentBranch: string = yield select( + selectGitCurrentBranch, + applicationArtifact(baseApplicationId), + ); // init of temporary remote url from old application yield put(remoteUrlInputValue({ tempRemoteUrl: "" })); diff --git a/app/client/src/git/artifact-helpers/application/applicationArtifact.ts b/app/client/src/git/artifact-helpers/application/applicationArtifact.ts new file mode 100644 index 000000000000..b3c249cf22e6 --- /dev/null +++ b/app/client/src/git/artifact-helpers/application/applicationArtifact.ts @@ -0,0 +1,11 @@ +import { GitArtifactType } from "git/constants/enums"; +import type { GitArtifactDef } from "git/store/selectors/gitSingleArtifactSelectors"; + +export default function applicationArtifact( + baseApplicationId: string, +): GitArtifactDef { + return { + artifactType: GitArtifactType.Application, + baseArtifactId: baseApplicationId, + }; +} diff --git a/app/client/src/git/artifactHelpers/application/statusTransformer.ts b/app/client/src/git/artifact-helpers/application/applicationStatusTransformer.ts similarity index 100% rename from app/client/src/git/artifactHelpers/application/statusTransformer.ts rename to app/client/src/git/artifact-helpers/application/applicationStatusTransformer.ts diff --git a/app/client/src/git/artifact-helpers/application/index.ts b/app/client/src/git/artifact-helpers/application/index.ts new file mode 100644 index 000000000000..579a99c7d975 --- /dev/null +++ b/app/client/src/git/artifact-helpers/application/index.ts @@ -0,0 +1,2 @@ +export { default as applicationArtifact } from "./applicationArtifact"; +export { default as applicationStatusTransformer } from "./applicationStatusTransformer"; diff --git a/app/client/src/git/components/ConnectModal/ConnectModalView.tsx b/app/client/src/git/components/ConnectModal/ConnectModalView.tsx index 0146a5cf9237..92ee42a57e7f 100644 --- a/app/client/src/git/components/ConnectModal/ConnectModalView.tsx +++ b/app/client/src/git/components/ConnectModal/ConnectModalView.tsx @@ -36,7 +36,7 @@ interface ConnectModalViewProps { resetGenerateSSHKey: () => void; sshPublicKey: string | null; toggleConnectModal: (open: boolean) => void; - isGitConnected: boolean; + isConnected: boolean; remoteUrl: string | null; toggleSettingsModal: ( open: boolean, @@ -50,8 +50,8 @@ interface ConnectModalViewProps { function ConnectModalView({ defaultBranch = null, + isConnected = false, isConnectModalOpen = false, - isGitConnected = false, remoteUrl = null, repoName = null, resetFetchSSHKey = noop, @@ -79,7 +79,7 @@ function ConnectModalView({ // need fragment to arrange conditions properly // eslint-disable-next-line react/jsx-no-useless-fragment <> - {isGitConnected ? ( + {isConnected ? ( { isConnectPermitted: true, isDiscardLoading: false, isFetchStatusLoading: false, - isGitConnected: false, + isConnected: false, isProtectedMode: false, isPullFailing: false, isPullLoading: false, @@ -48,7 +48,7 @@ describe("QuickActionsView Component", () => { jest.clearAllMocks(); }); - it("should render ConnectButton when isGitConnected is false", () => { + it("should render ConnectButton when isConnected is false", () => { render( @@ -57,10 +57,10 @@ describe("QuickActionsView Component", () => { expect(screen.getByTestId("connect-button")).toBeInTheDocument(); }); - it("should render QuickActionButtons when isGitConnected is true", () => { + it("should render QuickActionButtons when isConnected is true", () => { const props = { ...defaultProps, - isGitConnected: true, + isConnected: true, }; const { container } = render( @@ -86,7 +86,7 @@ describe("QuickActionsView Component", () => { it("should render Statusbar when isAutocommitEnabled and isPollingAutocommit are true", () => { const props = { ...defaultProps, - isGitConnected: true, + isConnected: true, isAutocommitEnabled: true, isAutocommitPolling: true, }; @@ -106,7 +106,7 @@ describe("QuickActionsView Component", () => { it("should call onCommitClick when commit button is clicked", () => { const props = { ...defaultProps, - isGitConnected: true, + isConnected: true, }; const { container } = render( @@ -131,7 +131,7 @@ describe("QuickActionsView Component", () => { it("should call onPullClick when pull button is clicked", () => { const props = { ...defaultProps, - isGitConnected: true, + isConnected: true, isDiscardLoading: false, isPullLoading: false, isFetchStatusLoading: false, @@ -159,7 +159,7 @@ describe("QuickActionsView Component", () => { it("should call onMerge when merge button is clicked", () => { const props = { ...defaultProps, - isGitConnected: true, + isConnected: true, }; const { container } = render( @@ -184,7 +184,7 @@ describe("QuickActionsView Component", () => { it("should call onSettingsClick when settings button is clicked", () => { const props = { ...defaultProps, - isGitConnected: true, + isConnected: true, }; const { container } = render( @@ -209,7 +209,7 @@ describe("QuickActionsView Component", () => { it("should disable commit button when isProtectedMode is true", () => { const props = { ...defaultProps, - isGitConnected: true, + isConnected: true, isProtectedMode: true, }; @@ -228,7 +228,7 @@ describe("QuickActionsView Component", () => { it("should show loading state on pull button when showPullLoadingState is true", () => { const props = { ...defaultProps, - isGitConnected: true, + isConnected: true, isPullLoading: true, }; @@ -250,7 +250,7 @@ describe("QuickActionsView Component", () => { it("should display changesToCommit count on commit button", () => { const props = { ...defaultProps, - isGitConnected: true, + isConnected: true, statusChangeCount: 5, }; @@ -267,7 +267,7 @@ describe("QuickActionsView Component", () => { it("should not display count on commit button when isProtectedMode is true", () => { const props = { ...defaultProps, - isGitConnected: true, + isConnected: true, isProtectedMode: true, statusChangeCount: 5, }; @@ -292,7 +292,7 @@ describe("QuickActionsView Component", () => { const props = { ...defaultProps, - isGitConnected: true, + isConnected: true, }; const { container } = render( @@ -310,7 +310,7 @@ describe("QuickActionsView Component", () => { it("should show behindCount on pull button", () => { const props = { ...defaultProps, - isGitConnected: true, + isConnected: true, statusBehindCount: 3, statusIsClean: true, }; diff --git a/app/client/src/git/components/QuickActions/QuickActionsView.tsx b/app/client/src/git/components/QuickActions/QuickActionsView.tsx index 396984788015..274dd00f3dba 100644 --- a/app/client/src/git/components/QuickActions/QuickActionsView.tsx +++ b/app/client/src/git/components/QuickActions/QuickActionsView.tsx @@ -33,7 +33,7 @@ interface QuickActionsViewProps { isConnectPermitted: boolean; isDiscardLoading: boolean; isFetchStatusLoading: boolean; - isGitConnected: boolean; + isConnected: boolean; isProtectedMode: boolean; isPullFailing: boolean; isPullLoading: boolean; @@ -57,10 +57,10 @@ function QuickActionsView({ isAutocommitEnabled = false, isAutocommitPolling = false, isBranchPopupOpen = false, + isConnected = false, isConnectPermitted = false, isDiscardLoading = false, isFetchStatusLoading = false, - isGitConnected = false, isProtectedMode = false, isPullFailing = false, isPullLoading = false, @@ -131,7 +131,7 @@ function QuickActionsView({ toggleConnectModal(true); }, [toggleConnectModal]); - return isGitConnected ? ( + return isConnected ? ( { + return selectConnected(state, artifactDef); + }); + + return isConnected; +} diff --git a/app/client/src/git/hooks/useCurrentBranch.ts b/app/client/src/git/hooks/useCurrentBranch.ts new file mode 100644 index 000000000000..2077d0cd39f5 --- /dev/null +++ b/app/client/src/git/hooks/useCurrentBranch.ts @@ -0,0 +1,8 @@ +import { useGitContext } from "git/components/GitContextProvider"; + +// refactor to use branch from git metadata +export default function useCurrentBranch() { + const { artifact } = useGitContext(); + + return artifact?.gitApplicationMetadata?.branchName; +} diff --git a/app/client/src/git/hooks/useMetadata.ts b/app/client/src/git/hooks/useMetadata.ts index 9bd5356ad763..3edad04d8560 100644 --- a/app/client/src/git/hooks/useMetadata.ts +++ b/app/client/src/git/hooks/useMetadata.ts @@ -1,8 +1,5 @@ import { useGitContext } from "git/components/GitContextProvider"; -import { - selectGitConnected, - selectMetadataState, -} from "git/store/selectors/gitSingleArtifactSelectors"; +import { selectMetadataState } from "git/store/selectors/gitSingleArtifactSelectors"; import type { GitRootState } from "git/store/types"; import { useSelector } from "react-redux"; @@ -13,14 +10,9 @@ export default function useMetadata() { selectMetadataState(state, artifactDef), ); - const isGitConnected = useSelector((state: GitRootState) => - selectGitConnected(state, artifactDef), - ); - return { metadata: metadataState?.value ?? null, isFetchMetadataLoading: metadataState?.loading ?? false, fetchMetadataError: metadataState?.error ?? null, - isGitConnected, }; } diff --git a/app/client/src/git/hooks/useProtectedBranches.ts b/app/client/src/git/hooks/useProtectedBranches.ts index fa3b2ef89307..f59b18f1ce10 100644 --- a/app/client/src/git/hooks/useProtectedBranches.ts +++ b/app/client/src/git/hooks/useProtectedBranches.ts @@ -2,7 +2,6 @@ import { useGitContext } from "git/components/GitContextProvider"; import { gitArtifactActions } from "git/store/gitArtifactSlice"; import { selectFetchProtectedBranchesState, - selectProtectedMode, selectUpdateProtectedBranchesState, } from "git/store/selectors/gitSingleArtifactSelectors"; import type { GitRootState } from "git/store/types"; @@ -38,10 +37,6 @@ function useProtectedBranches() { [dispatch, artifactDef], ); - const isProtectedMode = useSelector((state: GitRootState) => - selectProtectedMode(state, artifactDef), - ); - return { protectedBranches: fetchProtectedBranchesState.value, isFetchProtectedBranchesLoading: fetchProtectedBranchesState.loading, @@ -50,7 +45,6 @@ function useProtectedBranches() { isUpdateProtectedBranchesLoading: updateProtectedBranchesState.loading, updateProtectedBranchesError: updateProtectedBranchesState.error, updateProtectedBranches, - isProtectedMode, }; } diff --git a/app/client/src/git/hooks/useProtectedMode.ts b/app/client/src/git/hooks/useProtectedMode.ts new file mode 100644 index 000000000000..b97d3793e7ff --- /dev/null +++ b/app/client/src/git/hooks/useProtectedMode.ts @@ -0,0 +1,14 @@ +import { useGitContext } from "git/components/GitContextProvider"; +import { selectProtectedMode } from "git/store/selectors/gitSingleArtifactSelectors"; +import type { GitRootState } from "git/store/types"; +import { useSelector } from "react-redux"; + +export default function useProtectedMode() { + const { artifactDef } = useGitContext(); + + const isProtectedMode = useSelector((state: GitRootState) => { + return selectProtectedMode(state, artifactDef); + }); + + return isProtectedMode; +} diff --git a/app/client/src/git/index.ts b/app/client/src/git/index.ts new file mode 100644 index 000000000000..37206b881573 --- /dev/null +++ b/app/client/src/git/index.ts @@ -0,0 +1,22 @@ +// enums +export { GitArtifactType } from "./constants/enums"; + +// components +export { default as GitContextProvider } from "./components/GitContextProvider"; +export { default as GitModals } from "./ee/components/GitModals"; +export { default as GitImportModal } from "./components/ImportModal"; +export { default as GitQuickActions } from "./components/QuickActions"; + +// hooks +export { default as useGitCurrentBranch } from "./hooks/useCurrentBranch"; +export { default as useGitProtectedMode } from "./hooks/useProtectedMode"; +export { default as useGitConnected } from "./hooks/useConnected"; + +// reducer +export { gitReducer } from "./store"; + +// selectors +export { selectCurrentBranch as selectGitCurrentBranch } from "./store/selectors/gitSingleArtifactSelectors"; + +// sagas +export { default as gitSagas } from "./sagas"; diff --git a/app/client/src/git/store/selectors/gitSingleArtifactSelectors.ts b/app/client/src/git/store/selectors/gitSingleArtifactSelectors.ts index 845a2cfe41fe..367097e40a58 100644 --- a/app/client/src/git/store/selectors/gitSingleArtifactSelectors.ts +++ b/app/client/src/git/store/selectors/gitSingleArtifactSelectors.ts @@ -21,7 +21,7 @@ export const selectMetadataState = ( artifactDef: GitArtifactDef, ) => selectGitArtifact(state, artifactDef)?.apiResponses.metadata; -export const selectGitConnected = ( +export const selectConnected = ( state: GitRootState, artifactDef: GitArtifactDef, ) => !!selectMetadataState(state, artifactDef)?.value; diff --git a/app/client/src/pages/Editor/gitSync/hooks/modHooks.ts b/app/client/src/pages/Editor/gitSync/hooks/modHooks.ts new file mode 100644 index 000000000000..86d44b700b87 --- /dev/null +++ b/app/client/src/pages/Editor/gitSync/hooks/modHooks.ts @@ -0,0 +1,44 @@ +// temp file will be removed after git mod is fully rolled out + +import { useSelector } from "react-redux"; +import { + getCurrentGitBranch, + getIsGitConnected, + protectedModeSelector, +} from "selectors/gitSyncSelectors"; +import { + useGitProtectedMode as useGitProtectedModeNew, + useGitCurrentBranch as useGitCurrentBranchNew, + useGitConnected as useGitConnectedNew, +} from "git"; +import { selectGitModEnabled } from "selectors/gitModSelectors"; + +export function useGitModEnabled() { + const isGitModEnabled = useSelector(selectGitModEnabled); + + return isGitModEnabled; +} + +export function useGitCurrentBranch() { + const isGitModEnabled = useGitModEnabled(); + const currentBranchOld = useSelector(getCurrentGitBranch); + const currentBranchNew = useGitCurrentBranchNew(); + + return isGitModEnabled ? currentBranchNew : currentBranchOld; +} + +export function useGitProtectedMode() { + const isGitModEnabled = useGitModEnabled(); + const isProtectedModeOld = useSelector(protectedModeSelector); + const isProtectedModeNew = useGitProtectedModeNew(); + + return isGitModEnabled ? isProtectedModeNew : isProtectedModeOld; +} + +export function useGitConnected() { + const isGitModEnabled = useGitModEnabled(); + const isGitConnectedOld = useSelector(getIsGitConnected); + const isGitConnectedNew = useGitConnectedNew(); + + return isGitModEnabled ? isGitConnectedNew : isGitConnectedOld; +} diff --git a/app/client/src/pages/Editor/index.tsx b/app/client/src/pages/Editor/index.tsx index 739cf04c3d00..79496b67fa50 100644 --- a/app/client/src/pages/Editor/index.tsx +++ b/app/client/src/pages/Editor/index.tsx @@ -1,6 +1,6 @@ import React, { Component } from "react"; import { Helmet } from "react-helmet"; -import { connect, useSelector } from "react-redux"; +import { connect } from "react-redux"; import type { RouteComponentProps } from "react-router-dom"; import { withRouter } from "react-router-dom"; import type { BuilderRouteParams } from "constants/routes"; @@ -45,9 +45,8 @@ import type { Page } from "entities/Page"; import { AppCURLImportModal } from "ee/pages/Editor/CurlImport"; import { IDE_HEADER_HEIGHT } from "@appsmith/ads"; import GeneratePageModal from "./GeneratePage"; -import { GitModals as NewGitModals } from "git/components"; +import { GitModals as NewGitModals } from "git"; import GitApplicationContextProvider from "components/gitContexts/GitApplicationContextProvider"; -import { isGitModEnabledSelector } from "selectors/gitSyncSelectors"; import GitSyncModal from "./gitSync/GitSyncModal"; import GitSettingsModal from "./gitSync/GitSettingsModal"; import DisconnectGitModal from "./gitSync/DisconnectGitModal"; @@ -55,9 +54,10 @@ import DisableAutocommitModal from "./gitSync/DisableAutocommitModal"; import ReconfigureCDKeyModal from "ee/components/gitComponents/ReconfigureCDKeyModal"; import DisableCDModal from "ee/components/gitComponents/DisableCDModal"; import RepoLimitExceededErrorModal from "./gitSync/RepoLimitExceededErrorModal"; +import { useGitModEnabled } from "./gitSync/hooks/modHooks"; function GitModals() { - const isGitModEnabled = useSelector(isGitModEnabledSelector); + const isGitModEnabled = useGitModEnabled(); return isGitModEnabled ? ( diff --git a/app/client/src/selectors/gitModSelectors.ts b/app/client/src/selectors/gitModSelectors.ts new file mode 100644 index 000000000000..ad505d1ce638 --- /dev/null +++ b/app/client/src/selectors/gitModSelectors.ts @@ -0,0 +1,27 @@ +// temp file will be removed after git mod is fully rolled out + +import { selectFeatureFlags } from "ee/selectors/featureFlagsSelectors"; +import type { GitArtifactDef } from "git/store/selectors/gitSingleArtifactSelectors"; +import { createSelector } from "reselect"; +import { getCurrentGitBranch } from "./gitSyncSelectors"; +import type { AppState } from "ee/reducers"; +import { selectGitCurrentBranch as selectGitCurrentBranchNew } from "git"; + +export const selectGitModEnabled = createSelector( + selectFeatureFlags, + // (featureFlags) => featureFlags.release_git_modularisation_enabled ?? false, + () => true, +); + +export function selectGitCurrentBranch( + state: AppState, + artifactDef: GitArtifactDef, +) { + const isGitModEnabled = selectGitModEnabled(state); + + if (isGitModEnabled) { + return getCurrentGitBranch(state); + } else { + return selectGitCurrentBranchNew(state, artifactDef); + } +} diff --git a/app/client/src/selectors/gitSyncSelectors.tsx b/app/client/src/selectors/gitSyncSelectors.tsx index 6017c2de282b..bf3b009667bf 100644 --- a/app/client/src/selectors/gitSyncSelectors.tsx +++ b/app/client/src/selectors/gitSyncSelectors.tsx @@ -286,9 +286,3 @@ export const isGitPersistBranchEnabledSelector = createSelector( selectFeatureFlags, (featureFlags) => featureFlags.release_git_persist_branch_enabled ?? false, ); - -export const isGitModEnabledSelector = createSelector( - selectFeatureFlags, - // (featureFlags) => featureFlags.release_git_modularisation_enabled ?? false, - () => true, -); From c100cc232e2eacb6f74c9b6be88c218a40b13fbe Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Wed, 18 Dec 2024 07:55:26 +0800 Subject: [PATCH 081/143] chore: introducing artfactdef for better state mgmt --- .../request/apiRequestInterceptor.ts | 1 + app/client/src/ce/AppRouter.tsx | 5 +- .../FocusStrategy/AppIDEFocusStrategy.ts | 6 +- .../src/ce/pages/Applications/index.tsx | 4 - .../src/entities/Engine/AppEditorEngine.ts | 4 +- app/client/src/entities/Engine/index.ts | 11 +- .../src/git/ce/hooks/useDefaultBranch.ts | 12 +- .../components/ConflictErrorModal/index.tsx | 4 +- .../src/git/components/ConnectModal/index.tsx | 3 +- .../components/GitContextProvider/index.tsx | 21 +-- .../src/git/components/OpsModal/index.tsx | 7 +- .../ProtectedBranchCalloutView.tsx | 85 ++++++++++++ .../ProtectedBranchCallout/index.tsx | 33 +++++ .../git/components/SettingsModal/index.tsx | 3 +- .../src/git/hooks/useArtifactSelector.ts | 30 +++++ app/client/src/git/hooks/useAutocommit.ts | 48 +++---- app/client/src/git/hooks/useBranches.ts | 122 +++++++++--------- app/client/src/git/hooks/useCommit.ts | 37 +++--- app/client/src/git/hooks/useConnect.ts | 61 ++++----- app/client/src/git/hooks/useConnected.ts | 12 +- app/client/src/git/hooks/useCurrentBranch.ts | 2 +- app/client/src/git/hooks/useDiscard.ts | 16 ++- app/client/src/git/hooks/useDisconnect.ts | 32 +++-- app/client/src/git/hooks/useGitPermissions.ts | 17 ++- app/client/src/git/hooks/useLocalProfile.ts | 30 +++-- app/client/src/git/hooks/useMerge.ts | 44 ++++--- app/client/src/git/hooks/useMetadata.ts | 10 +- app/client/src/git/hooks/useOps.ts | 34 +++-- .../src/git/hooks/useProtectedBranches.ts | 42 +++--- app/client/src/git/hooks/useProtectedMode.ts | 12 +- app/client/src/git/hooks/usePull.ts | 22 ++-- app/client/src/git/hooks/useSettings.ts | 22 ++-- app/client/src/git/hooks/useStatus.ts | 32 ++--- app/client/src/git/index.ts | 1 + .../src/git/requests/connectRequest.types.ts | 17 +-- .../src/git/sagas/checkoutBranchSaga.ts | 13 +- app/client/src/git/sagas/commitSaga.ts | 16 +-- app/client/src/git/sagas/connectSaga.ts | 25 ++-- app/client/src/git/sagas/createBranchSaga.ts | 16 ++- app/client/src/git/sagas/deleteBranchSaga.ts | 21 ++- app/client/src/git/sagas/disconnectSaga.ts | 13 +- app/client/src/git/sagas/fetchBranchesSaga.ts | 9 +- .../src/git/sagas/fetchLocalProfileSaga.ts | 9 +- .../src/git/sagas/fetchMergeStatusSaga.ts | 10 +- app/client/src/git/sagas/fetchMetadataSaga.ts | 9 +- .../git/sagas/fetchProtectedBranchesSaga.ts | 12 +- app/client/src/git/sagas/fetchSSHKeySaga.ts | 9 +- app/client/src/git/sagas/fetchStatusSaga.ts | 9 +- .../src/git/sagas/generateSSHKeySaga.ts | 17 +-- app/client/src/git/sagas/initGitSaga.ts | 27 ++-- app/client/src/git/sagas/pullSaga.ts | 9 +- .../src/git/sagas/toggleAutocommitSaga.ts | 11 +- .../src/git/sagas/triggerAutocommitSaga.ts | 51 ++++---- .../src/git/sagas/updateLocalProfileSaga.ts | 15 ++- .../git/sagas/updateProtectedBranchesSaga.ts | 13 +- .../store/actions/checkoutBranchActions.ts | 5 +- .../src/git/store/actions/commitActions.ts | 4 +- .../git/store/actions/createBranchActions.ts | 4 +- .../git/store/actions/deleteBranchActions.ts | 4 +- .../git/store/actions/fetchBranchesActions.ts | 4 +- .../git/store/actions/fetchStatusActions.ts | 4 +- .../src/git/store/actions/initGitActions.ts | 8 +- .../src/git/store/actions/mountActions.ts | 6 +- app/client/src/git/store/actions/uiActions.ts | 3 +- .../helpers/createSingleArtifactAction.ts | 2 +- app/client/src/git/store/types.ts | 10 +- app/client/src/pages/AppViewer/PrimaryCTA.tsx | 4 +- .../AppSettings/ImportAppSettings.tsx | 4 +- .../Editor/IDE/Layout/AnimatedLayout.tsx | 25 +++- .../Editor/IDE/Layout/UnanimatedLayout.tsx | 25 +++- app/client/src/pages/Editor/IDE/hooks.ts | 4 +- .../Editor/commons/EditorWrapperContainer.tsx | 4 +- app/client/src/pages/Editor/index.tsx | 27 ++-- .../sagas/ActionExecution/StoreActionSaga.ts | 9 +- app/client/src/sagas/DatasourcesSagas.ts | 1 + app/client/src/sagas/FocusRetentionSaga.ts | 10 +- app/client/src/sagas/GlobalSearchSagas.ts | 12 +- 77 files changed, 767 insertions(+), 568 deletions(-) create mode 100644 app/client/src/git/components/ProtectedBranchCallout/ProtectedBranchCalloutView.tsx create mode 100644 app/client/src/git/components/ProtectedBranchCallout/index.tsx create mode 100644 app/client/src/git/hooks/useArtifactSelector.ts diff --git a/app/client/src/api/interceptors/request/apiRequestInterceptor.ts b/app/client/src/api/interceptors/request/apiRequestInterceptor.ts index 5371cbbcf23c..4a9d2ed633cc 100644 --- a/app/client/src/api/interceptors/request/apiRequestInterceptor.ts +++ b/app/client/src/api/interceptors/request/apiRequestInterceptor.ts @@ -30,6 +30,7 @@ const blockAirgappedRoutes = (config: InternalAxiosRequestConfig) => { const addGitBranchHeader = (config: InternalAxiosRequestConfig) => { const state = store.getState(); + // ! git mod - not sure how to replace this, we could directly read state if required const branch = getCurrentGitBranch(state) || getQueryParamsObject().branch; return _addGitBranchHeader(config, { branch }); diff --git a/app/client/src/ce/AppRouter.tsx b/app/client/src/ce/AppRouter.tsx index 0675d4ba7bc1..498433dc9282 100644 --- a/app/client/src/ce/AppRouter.tsx +++ b/app/client/src/ce/AppRouter.tsx @@ -64,6 +64,7 @@ import { FEATURE_FLAG } from "ee/entities/FeatureFlag"; import CustomWidgetBuilderLoader from "pages/Editor/CustomWidgetBuilder/loader"; import { getIsConsolidatedPageLoading } from "selectors/ui"; import { useFeatureFlagOverride } from "utils/hooks/useFeatureFlagOverride"; +import GitApplicationContextProvider from "components/gitContexts/GitApplicationContextProvider"; export const SentryRoute = Sentry.withSentryRouting(Route); @@ -187,13 +188,13 @@ export default function AppRouter() { ) : ( - <> + - + )} diff --git a/app/client/src/ce/navigation/FocusStrategy/AppIDEFocusStrategy.ts b/app/client/src/ce/navigation/FocusStrategy/AppIDEFocusStrategy.ts index 5eaabd59a60e..f9c2122b0ec3 100644 --- a/app/client/src/ce/navigation/FocusStrategy/AppIDEFocusStrategy.ts +++ b/app/client/src/ce/navigation/FocusStrategy/AppIDEFocusStrategy.ts @@ -88,8 +88,10 @@ const isPageChange = (prevPath: string, currentPath: string) => { ); }; -export const createEditorFocusInfoKey = (basePageId: string, branch?: string) => - `EDITOR_STATE.${basePageId}#${branch}`; +export const createEditorFocusInfoKey = ( + basePageId: string, + branch?: string | null, +) => `EDITOR_STATE.${basePageId}#${branch}`; export const createEditorFocusInfo = (basePageId: string, branch?: string) => ({ key: createEditorFocusInfoKey(basePageId, branch), entityInfo: { diff --git a/app/client/src/ce/pages/Applications/index.tsx b/app/client/src/ce/pages/Applications/index.tsx index 3f7c476113f0..3d215119a84b 100644 --- a/app/client/src/ce/pages/Applications/index.tsx +++ b/app/client/src/ce/pages/Applications/index.tsx @@ -964,10 +964,6 @@ export function ApplicationsSection(props: any) { > {workspacesListComponent} - {/* - - */} - {/* */} ); diff --git a/app/client/src/entities/Engine/AppEditorEngine.ts b/app/client/src/entities/Engine/AppEditorEngine.ts index 41238aa2bc3d..f84807058663 100644 --- a/app/client/src/entities/Engine/AppEditorEngine.ts +++ b/app/client/src/entities/Engine/AppEditorEngine.ts @@ -61,7 +61,6 @@ import { getCurrentUser } from "selectors/usersSelectors"; import type { User } from "constants/userConstants"; import log from "loglevel"; import { gitArtifactActions } from "git/store/gitArtifactSlice"; -import { GitArtifactType } from "git/constants/enums"; import { restoreRecentEntitiesRequest } from "actions/globalSearchActions"; import { fetchBranchesInit, @@ -397,8 +396,7 @@ export default class AppEditorEngine extends AppEngine { yield put( gitArtifactActions.initGitForEditor({ - artifactType: GitArtifactType.Application, - baseArtifactId: currentApplication.baseId, + artifactDef: applicationArtifact(currentApplication.baseId), artifact: currentApplication, }), ); diff --git a/app/client/src/entities/Engine/index.ts b/app/client/src/entities/Engine/index.ts index 03d66ec09a5e..c62c4babe8f0 100644 --- a/app/client/src/entities/Engine/index.ts +++ b/app/client/src/entities/Engine/index.ts @@ -17,10 +17,11 @@ import history from "utils/history"; import type URLRedirect from "entities/URLRedirect/index"; import URLGeneratorFactory from "entities/URLRedirect/factory"; import { updateBranchLocally } from "actions/gitSyncActions"; -import { getCurrentGitBranch } from "selectors/gitSyncSelectors"; import { restoreIDEEditorViewMode } from "actions/ideActions"; import type { Span } from "@opentelemetry/api"; import { endSpan, startNestedSpan } from "UITelemetry/generateTraces"; +import { selectGitCurrentBranch } from "selectors/gitModSelectors"; +import { applicationArtifact } from "git/artifact-helpers/application"; export interface AppEnginePayload { applicationId?: string; @@ -114,12 +115,14 @@ export default abstract class AppEngine { } const application: ApplicationPayload = yield select(getCurrentApplication); - const currentGitBranch: ReturnType = - yield select(getCurrentGitBranch); + const currentBranch: string | undefined = yield select( + selectGitCurrentBranch, + applicationArtifact(application.baseId), + ); yield put( updateAppStore( - getPersistentAppStore(application.id, branch || currentGitBranch), + getPersistentAppStore(application.id, branch || currentBranch), ), ); const defaultPageId: string = yield select(getDefaultPageId); diff --git a/app/client/src/git/ce/hooks/useDefaultBranch.ts b/app/client/src/git/ce/hooks/useDefaultBranch.ts index 6bc27c1c08c0..3f639e231555 100644 --- a/app/client/src/git/ce/hooks/useDefaultBranch.ts +++ b/app/client/src/git/ce/hooks/useDefaultBranch.ts @@ -1,17 +1,11 @@ -import { useGitContext } from "git/components/GitContextProvider"; +import useAritfactSelector from "git/hooks/useArtifactSelector"; import { selectDefaultBranch } from "git/store/selectors/gitSingleArtifactSelectors"; -import type { GitRootState } from "git/store/types"; -import { useSelector } from "react-redux"; function useDefaultBranch() { - const { artifactDef } = useGitContext(); - - const defaultBranch = useSelector((state: GitRootState) => - selectDefaultBranch(state, artifactDef), - ); + const defaultBranch = useAritfactSelector(selectDefaultBranch); return { - defaultBranch, + defaultBranch: defaultBranch ?? null, }; } diff --git a/app/client/src/git/components/ConflictErrorModal/index.tsx b/app/client/src/git/components/ConflictErrorModal/index.tsx index db9568836032..a67a429aff35 100644 --- a/app/client/src/git/components/ConflictErrorModal/index.tsx +++ b/app/client/src/git/components/ConflictErrorModal/index.tsx @@ -3,11 +3,11 @@ import ConflictErrorModalView from "./ConflictErrorModalView"; import useOps from "git/hooks/useOps"; export default function ConflictErrorModal() { - const { conflictErrorModalOpen, toggleConflictErrorModal } = useOps(); + const { isConflictErrorModalOpen, toggleConflictErrorModal } = useOps(); return ( ); diff --git a/app/client/src/git/components/ConnectModal/index.tsx b/app/client/src/git/components/ConnectModal/index.tsx index f2e5ee486177..2dcecebeb942 100644 --- a/app/client/src/git/components/ConnectModal/index.tsx +++ b/app/client/src/git/components/ConnectModal/index.tsx @@ -5,6 +5,7 @@ import useConnect from "git/hooks/useConnect"; import useMetadata from "git/hooks/useMetadata"; import useSettings from "git/hooks/useSettings"; import useConnected from "git/hooks/useConnected"; +import { GitArtifactType } from "git/constants/enums"; interface ConnectModalProps { isImport?: boolean; @@ -33,7 +34,7 @@ function ConnectModal({ isImport = false }: ConnectModalProps) { const { metadata } = useMetadata(); const { toggleSettingsModal } = useSettings(); - const { artifactType } = artifactDef; + const artifactType = artifactDef?.artifactType ?? GitArtifactType.Application; const sshPublicKey = sshKey?.publicKey ?? null; const remoteUrl = metadata?.remoteUrl ?? null; const repoName = metadata?.repoName ?? null; diff --git a/app/client/src/git/components/GitContextProvider/index.tsx b/app/client/src/git/components/GitContextProvider/index.tsx index 4d4b88b4f6ad..68e3c0bab450 100644 --- a/app/client/src/git/components/GitContextProvider/index.tsx +++ b/app/client/src/git/components/GitContextProvider/index.tsx @@ -4,12 +4,10 @@ import type { ApplicationPayload } from "entities/Application"; import type { FetchStatusResponseData } from "git/requests/fetchStatusRequest.types"; import type { StatusTreeStruct } from "../StatusChanges/StatusTree"; import { useDispatch } from "react-redux"; +import type { GitArtifactDef } from "git/store/selectors/gitSingleArtifactSelectors"; export interface GitContextValue { - artifactDef: { - artifactType: keyof typeof GitArtifactType; - baseArtifactId: string; - }; + artifactDef: GitArtifactDef | null; artifact: ApplicationPayload | null; statusTransformer: ( status: FetchStatusResponseData, @@ -27,8 +25,8 @@ export const useGitContext = () => { }; interface GitContextProviderProps { - artifactType: keyof typeof GitArtifactType; - baseArtifactId: string; + artifactType: keyof typeof GitArtifactType | null; + baseArtifactId: string | null; artifact: ApplicationPayload | null; isCreateArtifactPermitted: boolean; setWorkspaceIdForImport: (params: { @@ -50,10 +48,13 @@ export default function GitContextProvider({ setWorkspaceIdForImport, statusTransformer, }: GitContextProviderProps) { - const artifactDef = useMemo( - () => ({ artifactType, baseArtifactId }), - [artifactType, baseArtifactId], - ); + const artifactDef = useMemo(() => { + if (artifactType && baseArtifactId) { + return { artifactType, baseArtifactId }; + } + + return null; + }, [artifactType, baseArtifactId]); const dispatch = useDispatch(); diff --git a/app/client/src/git/components/OpsModal/index.tsx b/app/client/src/git/components/OpsModal/index.tsx index 420ff2bea102..66ea3ddf0182 100644 --- a/app/client/src/git/components/OpsModal/index.tsx +++ b/app/client/src/git/components/OpsModal/index.tsx @@ -4,9 +4,10 @@ import useMetadata from "git/hooks/useMetadata"; import useStatus from "git/hooks/useStatus"; import useOps from "git/hooks/useOps"; import useProtectedMode from "git/hooks/useProtectedMode"; +import { GitOpsTab } from "git/constants/enums"; export default function OpsModal() { - const { opsModalOpen, opsModalTab, toggleOpsModal } = useOps(); + const { isOpsModalOpen, opsModalTab, toggleOpsModal } = useOps(); const { fetchStatus } = useStatus(); const isProtectedMode = useProtectedMode(); @@ -17,9 +18,9 @@ export default function OpsModal() { return ( diff --git a/app/client/src/git/components/ProtectedBranchCallout/ProtectedBranchCalloutView.tsx b/app/client/src/git/components/ProtectedBranchCallout/ProtectedBranchCalloutView.tsx new file mode 100644 index 000000000000..89b37bbfa239 --- /dev/null +++ b/app/client/src/git/components/ProtectedBranchCallout/ProtectedBranchCalloutView.tsx @@ -0,0 +1,85 @@ +import React, { useCallback, useMemo } from "react"; +import { Callout } from "@appsmith/ads"; +import styled from "styled-components"; +import { + BRANCH_PROTECTION_CALLOUT_CREATE_BRANCH, + BRANCH_PROTECTION_CALLOUT_MSG, + BRANCH_PROTECTION_CALLOUT_UNPROTECT, + BRANCH_PROTECTION_CALLOUT_UNPROTECT_LOADING, + createMessage, +} from "ee/constants/messages"; +import { noop } from "lodash"; +import type { FetchProtectedBranchesResponseData } from "git/requests/fetchProtectedBranchesRequest.types"; + +export const PROTECTED_CALLOUT_HEIGHT = 70; + +const StyledCallout = styled(Callout)` + height: ${PROTECTED_CALLOUT_HEIGHT}px; + overflow-y: hidden; +`; + +interface ProtectedBranchCalloutViewProps { + currentBranch: string | null; + isUpdateProtectedBranchesLoading: boolean; + protectedBranches: FetchProtectedBranchesResponseData | null; + toggleBranchPopup: (isOpen: boolean) => void; + updateProtectedBranches: (branches: string[]) => void; +} + +function ProtectedBranchCalloutView({ + currentBranch = null, + isUpdateProtectedBranchesLoading = false, + protectedBranches = null, + toggleBranchPopup = noop, + updateProtectedBranches = noop, +}: ProtectedBranchCalloutViewProps) { + const handleClickOnNewBranch = useCallback(() => { + toggleBranchPopup(true); + }, [toggleBranchPopup]); + + const handleClickOnUnprotect = useCallback(() => { + const allBranches = protectedBranches || []; + const remainingBranches = allBranches.filter( + (protectedBranch) => protectedBranch !== currentBranch, + ); + + updateProtectedBranches(remainingBranches); + }, [currentBranch, protectedBranches, updateProtectedBranches]); + + const links = useMemo( + () => [ + { + key: "create-branch", + "data-testid": "t--git-protected-create-branch-cta", + children: createMessage(BRANCH_PROTECTION_CALLOUT_CREATE_BRANCH), + onClick: handleClickOnNewBranch, + }, + { + key: "unprotect", + "data-testid": "t--git-protected-unprotect-branch-cta", + children: isUpdateProtectedBranchesLoading + ? createMessage(BRANCH_PROTECTION_CALLOUT_UNPROTECT_LOADING) + : createMessage(BRANCH_PROTECTION_CALLOUT_UNPROTECT), + onClick: handleClickOnUnprotect, + isDisabled: isUpdateProtectedBranchesLoading, + }, + ], + [ + handleClickOnNewBranch, + handleClickOnUnprotect, + isUpdateProtectedBranchesLoading, + ], + ); + + return ( + + {createMessage(BRANCH_PROTECTION_CALLOUT_MSG)} + + ); +} + +export default ProtectedBranchCalloutView; diff --git a/app/client/src/git/components/ProtectedBranchCallout/index.tsx b/app/client/src/git/components/ProtectedBranchCallout/index.tsx new file mode 100644 index 000000000000..aca08dfc1e87 --- /dev/null +++ b/app/client/src/git/components/ProtectedBranchCallout/index.tsx @@ -0,0 +1,33 @@ +import React from "react"; +import ProtectedBranchCalloutView from "./ProtectedBranchCalloutView"; +import useProtectedBranches from "git/hooks/useProtectedBranches"; +import useCurrentBranch from "git/hooks/useCurrentBranch"; +import useBranches from "git/hooks/useBranches"; +import useProtectedMode from "git/hooks/useProtectedMode"; + +function ProtectedBranchCallout() { + const isProtectedMode = useProtectedMode(); + const currentBranch = useCurrentBranch(); + const { toggleBranchPopup } = useBranches(); + const { + isUpdateProtectedBranchesLoading, + protectedBranches, + updateProtectedBranches, + } = useProtectedBranches(); + + if (!isProtectedMode) { + return null; + } + + return ( + + ); +} + +export default ProtectedBranchCallout; diff --git a/app/client/src/git/components/SettingsModal/index.tsx b/app/client/src/git/components/SettingsModal/index.tsx index 47ca695ab500..968c8030312e 100644 --- a/app/client/src/git/components/SettingsModal/index.tsx +++ b/app/client/src/git/components/SettingsModal/index.tsx @@ -2,6 +2,7 @@ import React from "react"; import SettingsModalView from "./SettingsModalView"; import useGitPermissions from "git/hooks/useGitPermissions"; import useSettings from "git/hooks/useSettings"; +import { GitSettingsTab } from "git/constants/enums"; function SettingsModal() { const { isSettingsModalOpen, settingsModalTab, toggleSettingsModal } = @@ -21,7 +22,7 @@ function SettingsModal() { isManageDefaultBranchPermitted={isManageDefaultBranchPermitted} isManageProtectedBranchesPermitted={isManageProtectedBranchesPermitted} isSettingsModalOpen={isSettingsModalOpen} - settingsModalTab={settingsModalTab} + settingsModalTab={settingsModalTab ?? GitSettingsTab.General} toggleSettingsModal={toggleSettingsModal} /> ); diff --git a/app/client/src/git/hooks/useArtifactSelector.ts b/app/client/src/git/hooks/useArtifactSelector.ts new file mode 100644 index 000000000000..bf19b8b1e26d --- /dev/null +++ b/app/client/src/git/hooks/useArtifactSelector.ts @@ -0,0 +1,30 @@ +import { useGitContext } from "git/components/GitContextProvider"; +import type { GitArtifactDef } from "git/store/selectors/gitSingleArtifactSelectors"; +import type { GitRootState } from "git/store/types"; +import { useSelector } from "react-redux"; +import type { Tail } from "redux-saga/effects"; + +/** + * This hook is used to select data from the redux store based on the artifactDef. + **/ +export default function useAritfactSelector< + // need any type to properly infer the return type + /* eslint-disable @typescript-eslint/no-explicit-any */ + Fn extends (state: any, artifactDef: GitArtifactDef, ...args: any[]) => any, +>(selectorFn: Fn, ...args: Tail>>): ReturnType | null { + const { artifactDef } = useGitContext(); + + return useSelector((state: GitRootState) => { + if (typeof selectorFn !== "function" || !artifactDef) { + return null; + } + + const { artifactType, baseArtifactId } = artifactDef; + + if (!state.git?.artifacts?.[artifactType]?.[baseArtifactId]) { + return null; + } + + return selectorFn(state, artifactDef, ...args); + }); +} diff --git a/app/client/src/git/hooks/useAutocommit.ts b/app/client/src/git/hooks/useAutocommit.ts index 73d7d955caca..bcc9de06af47 100644 --- a/app/client/src/git/hooks/useAutocommit.ts +++ b/app/client/src/git/hooks/useAutocommit.ts @@ -7,49 +7,49 @@ import { selectToggleAutocommitState, selectTriggerAutocommitState, } from "git/store/selectors/gitSingleArtifactSelectors"; -import type { GitRootState } from "git/store/types"; import { useCallback } from "react"; -import { useDispatch, useSelector } from "react-redux"; +import { useDispatch } from "react-redux"; +import useAritfactSelector from "./useArtifactSelector"; export default function useAutocommit() { const { artifactDef } = useGitContext(); const dispatch = useDispatch(); - const toggleAutocommitState = useSelector((state: GitRootState) => - selectToggleAutocommitState(state, artifactDef), + const toggleAutocommitState = useAritfactSelector( + selectToggleAutocommitState, ); - const triggerAutocommitState = useSelector((state: GitRootState) => - selectTriggerAutocommitState(state, artifactDef), + const triggerAutocommitState = useAritfactSelector( + selectTriggerAutocommitState, ); const toggleAutocommit = useCallback(() => { - dispatch(gitArtifactActions.toggleAutocommitInit(artifactDef)); + if (artifactDef) { + dispatch(gitArtifactActions.toggleAutocommitInit({ artifactDef })); + } }, [artifactDef, dispatch]); - const isAutocommitDisableModalOpen = useSelector((state: GitRootState) => - selectAutocommitDisableModalOpen(state, artifactDef), + const isAutocommitDisableModalOpen = useAritfactSelector( + selectAutocommitDisableModalOpen, ); const toggleAutocommitDisableModal = useCallback( (open: boolean) => { - dispatch( - gitArtifactActions.toggleAutocommitDisableModal({ - ...artifactDef, - open, - }), - ); + if (artifactDef) { + dispatch( + gitArtifactActions.toggleAutocommitDisableModal({ + artifactDef, + open, + }), + ); + } }, [artifactDef, dispatch], ); - const isAutocommitEnabled = useSelector((state: GitRootState) => - selectAutocommitEnabled(state, artifactDef), - ); + const isAutocommitEnabled = useAritfactSelector(selectAutocommitEnabled); - const isAutocommitPolling = useSelector((state: GitRootState) => - selectAutocommitPolling(state, artifactDef), - ); + const isAutocommitPolling = useAritfactSelector(selectAutocommitPolling); return { isToggleAutocommitLoading: toggleAutocommitState?.loading ?? false, @@ -57,9 +57,9 @@ export default function useAutocommit() { toggleAutocommit, isTriggerAutocommitLoading: triggerAutocommitState?.loading ?? false, triggerAutocommitError: triggerAutocommitState?.error ?? null, - isAutocommitDisableModalOpen, + isAutocommitDisableModalOpen: isAutocommitDisableModalOpen ?? false, toggleAutocommitDisableModal, - isAutocommitEnabled, - isAutocommitPolling, + isAutocommitEnabled: isAutocommitEnabled ?? false, + isAutocommitPolling: isAutocommitPolling ?? false, }; } diff --git a/app/client/src/git/hooks/useBranches.ts b/app/client/src/git/hooks/useBranches.ts index 4a0ecead44d7..2ac945f838af 100644 --- a/app/client/src/git/hooks/useBranches.ts +++ b/app/client/src/git/hooks/useBranches.ts @@ -9,102 +9,104 @@ import { selectDeleteBranchState, selectCurrentBranch, } from "git/store/selectors/gitSingleArtifactSelectors"; -import type { GitRootState } from "git/store/types"; import { useCallback } from "react"; -import { useDispatch, useSelector } from "react-redux"; +import { useDispatch } from "react-redux"; +import useAritfactSelector from "./useArtifactSelector"; export default function useBranches() { - const { artifactDef } = useGitContext(); + const { artifact, artifactDef } = useGitContext(); + const artifactId = artifact?.id; const dispatch = useDispatch(); // fetch branches - const branchesState = useSelector((state: GitRootState) => - selectFetchBranchesState(state, artifactDef), - ); + const branchesState = useAritfactSelector(selectFetchBranchesState); + const fetchBranches = useCallback(() => { - dispatch( - gitArtifactActions.fetchBranchesInit({ - ...artifactDef, - pruneBranches: true, - }), - ); - }, [artifactDef, dispatch]); + if (artifactDef && artifactId) { + dispatch( + gitArtifactActions.fetchBranchesInit({ + artifactId, + artifactDef, + pruneBranches: true, + }), + ); + } + }, [artifactDef, artifactId, dispatch]); // create branch - const createBranchState = useSelector((state: GitRootState) => - selectCreateBranchState(state, artifactDef), - ); + const createBranchState = useAritfactSelector(selectCreateBranchState); const createBranch = useCallback( (branchName: string) => { - dispatch( - gitArtifactActions.createBranchInit({ - ...artifactDef, - branchName, - }), - ); + if (artifactDef && artifactId) { + dispatch( + gitArtifactActions.createBranchInit({ + artifactDef, + artifactId, + branchName, + }), + ); + } }, - [artifactDef, dispatch], + [artifactDef, artifactId, dispatch], ); // delete branch - const deleteBranchState = useSelector((state: GitRootState) => - selectDeleteBranchState(state, artifactDef), - ); + const deleteBranchState = useAritfactSelector(selectDeleteBranchState); const deleteBranch = useCallback( (branchName: string) => { - dispatch( - gitArtifactActions.deleteBranchInit({ - ...artifactDef, - branchName, - }), - ); + if (artifactDef && artifactId) { + dispatch( + gitArtifactActions.deleteBranchInit({ + artifactId, + artifactDef, + branchName, + }), + ); + } }, - [artifactDef, dispatch], + [artifactDef, artifactId, dispatch], ); // checkout branch - const checkoutBranchState = useSelector((state: GitRootState) => - selectCheckoutBranchState(state, artifactDef), - ); + const checkoutBranchState = useAritfactSelector(selectCheckoutBranchState); const checkoutBranch = useCallback( (branchName: string) => { - dispatch( - gitArtifactActions.checkoutBranchInit({ - ...artifactDef, - branchName, - }), - ); + if (artifactDef && artifactId) { + dispatch( + gitArtifactActions.checkoutBranchInit({ + artifactDef, + artifactId, + branchName, + }), + ); + } }, - [artifactDef, dispatch], + [artifactDef, artifactId, dispatch], ); - const checkoutDestBranch = useSelector((state: GitRootState) => - selectCheckoutDestBranch(state, artifactDef), - ); + const checkoutDestBranch = useAritfactSelector(selectCheckoutDestBranch); // derived - const currentBranch = useSelector((state: GitRootState) => - selectCurrentBranch(state, artifactDef), - ); + const currentBranch = useAritfactSelector(selectCurrentBranch); // git branch list popup - const isBranchPopupOpen = useSelector((state: GitRootState) => - selectBranchPopupOpen(state, artifactDef), - ); + const isBranchPopupOpen = useAritfactSelector(selectBranchPopupOpen); const toggleBranchPopup = useCallback( (open: boolean) => { - dispatch( - gitArtifactActions.toggleBranchPopup({ - ...artifactDef, - open, - }), - ); + if (artifactDef) { + dispatch( + gitArtifactActions.toggleBranchPopup({ + artifactDef, + open, + }), + ); + } }, [artifactDef, dispatch], ); return { - branches: branchesState?.value, + branches: branchesState?.value ?? null, isFetchBranchesLoading: branchesState?.loading ?? false, fetchBranchesError: branchesState?.error ?? null, fetchBranches, @@ -119,7 +121,7 @@ export default function useBranches() { checkoutBranch, checkoutDestBranch, currentBranch: currentBranch ?? null, - isBranchPopupOpen, + isBranchPopupOpen: isBranchPopupOpen ?? false, toggleBranchPopup, }; } diff --git a/app/client/src/git/hooks/useCommit.ts b/app/client/src/git/hooks/useCommit.ts index 56f78cc11bcd..fce3d4ebbe52 100644 --- a/app/client/src/git/hooks/useCommit.ts +++ b/app/client/src/git/hooks/useCommit.ts @@ -1,38 +1,43 @@ import { useGitContext } from "git/components/GitContextProvider"; import { gitArtifactActions } from "git/store/gitArtifactSlice"; import { selectCommitState } from "git/store/selectors/gitSingleArtifactSelectors"; -import type { GitRootState } from "git/store/types"; import { useCallback } from "react"; -import { useDispatch, useSelector } from "react-redux"; +import { useDispatch } from "react-redux"; +import useAritfactSelector from "./useArtifactSelector"; export default function useCommit() { - const { artifactDef } = useGitContext(); + const { artifact, artifactDef } = useGitContext(); + const artifactId = artifact?.id; + const dispatch = useDispatch(); - const commitState = useSelector((state: GitRootState) => - selectCommitState(state, artifactDef), - ); + const commitState = useAritfactSelector(selectCommitState); const commit = useCallback( (commitMessage: string) => { - dispatch( - gitArtifactActions.commitInit({ - ...artifactDef, - commitMessage, - doPush: true, - }), - ); + if (artifactDef && artifactId) { + dispatch( + gitArtifactActions.commitInit({ + artifactId, + artifactDef, + commitMessage, + doPush: true, + }), + ); + } }, - [artifactDef, dispatch], + [artifactDef, artifactId, dispatch], ); const clearCommitError = useCallback(() => { - dispatch(gitArtifactActions.clearCommitError(artifactDef)); + if (artifactDef) { + dispatch(gitArtifactActions.clearCommitError({ artifactDef })); + } }, [artifactDef, dispatch]); return { isCommitLoading: commitState?.loading ?? false, - commitError: commitState?.error, + commitError: commitState?.error ?? null, commit, clearCommitError, }; diff --git a/app/client/src/git/hooks/useConnect.ts b/app/client/src/git/hooks/useConnect.ts index 1064ce7ff26e..0e6187cc25d0 100644 --- a/app/client/src/git/hooks/useConnect.ts +++ b/app/client/src/git/hooks/useConnect.ts @@ -8,30 +8,27 @@ import { selectGenerateSSHKeyState, selectGitImportState, } from "git/store/selectors/gitSingleArtifactSelectors"; -import type { GitRootState } from "git/store/types"; import { useCallback } from "react"; import { useDispatch } from "react-redux"; -import { useSelector } from "react-redux"; +import useAritfactSelector from "./useArtifactSelector"; export default function useConnect() { const { artifactDef } = useGitContext(); const dispatch = useDispatch(); - const connectState = useSelector((state: GitRootState) => - selectConnectState(state, artifactDef), - ); + const connectState = useAritfactSelector(selectConnectState); const connect = useCallback( (params: ConnectRequestParams) => { - dispatch(gitArtifactActions.connectInit({ ...artifactDef, ...params })); + if (artifactDef) { + dispatch(gitArtifactActions.connectInit({ artifactDef, ...params })); + } }, [artifactDef, dispatch], ); - const gitImportState = useSelector((state: GitRootState) => - selectGitImportState(state, artifactDef), - ); + const gitImportState = useAritfactSelector(selectGitImportState); const gitImport = useCallback( (params) => { @@ -40,46 +37,50 @@ export default function useConnect() { [artifactDef, dispatch], ); - const fetchSSHKeyState = useSelector((state: GitRootState) => - selectFetchSSHKeysState(state, artifactDef), - ); + const fetchSSHKeyState = useAritfactSelector(selectFetchSSHKeysState); const fetchSSHKey = useCallback(() => { - dispatch(gitArtifactActions.fetchSSHKeyInit(artifactDef)); + if (artifactDef) { + dispatch(gitArtifactActions.fetchSSHKeyInit({ artifactDef })); + } }, [artifactDef, dispatch]); const resetFetchSSHKey = useCallback(() => { - dispatch(gitArtifactActions.resetFetchSSHKey(artifactDef)); + if (artifactDef) { + dispatch(gitArtifactActions.resetFetchSSHKey({ artifactDef })); + } }, [artifactDef, dispatch]); - const generateSSHKeyState = useSelector((state: GitRootState) => - selectGenerateSSHKeyState(state, artifactDef), - ); + const generateSSHKeyState = useAritfactSelector(selectGenerateSSHKeyState); const generateSSHKey = useCallback( (keyType: string, isImport: boolean = false) => { - dispatch( - gitArtifactActions.generateSSHKeyInit({ - ...artifactDef, - keyType, - isImport, - }), - ); + if (artifactDef) { + dispatch( + gitArtifactActions.generateSSHKeyInit({ + artifactDef, + keyType, + isImport, + }), + ); + } }, [artifactDef, dispatch], ); const resetGenerateSSHKey = useCallback(() => { - dispatch(gitArtifactActions.resetGenerateSSHKey(artifactDef)); + if (artifactDef) { + dispatch(gitArtifactActions.resetGenerateSSHKey({ artifactDef })); + } }, [artifactDef, dispatch]); - const isConnectModalOpen = useSelector((state: GitRootState) => - selectConnectModalOpen(state, artifactDef), - ); + const isConnectModalOpen = useAritfactSelector(selectConnectModalOpen); const toggleConnectModal = useCallback( (open: boolean) => { - dispatch(gitArtifactActions.toggleConnectModal({ ...artifactDef, open })); + if (artifactDef) { + dispatch(gitArtifactActions.toggleConnectModal({ artifactDef, open })); + } }, [artifactDef, dispatch], ); @@ -100,7 +101,7 @@ export default function useConnect() { generateSSHKeyError: generateSSHKeyState?.error ?? null, generateSSHKey, resetGenerateSSHKey, - isConnectModalOpen, + isConnectModalOpen: isConnectModalOpen ?? false, toggleConnectModal, }; } diff --git a/app/client/src/git/hooks/useConnected.ts b/app/client/src/git/hooks/useConnected.ts index 654103c6827a..94681d6a0ed0 100644 --- a/app/client/src/git/hooks/useConnected.ts +++ b/app/client/src/git/hooks/useConnected.ts @@ -1,14 +1,8 @@ -import { useGitContext } from "git/components/GitContextProvider"; import { selectConnected } from "git/store/selectors/gitSingleArtifactSelectors"; -import type { GitRootState } from "git/store/types"; -import { useSelector } from "react-redux"; +import useAritfactSelector from "./useArtifactSelector"; export default function useConnected() { - const { artifactDef } = useGitContext(); + const isConnected = useAritfactSelector(selectConnected); - const isConnected = useSelector((state: GitRootState) => { - return selectConnected(state, artifactDef); - }); - - return isConnected; + return isConnected ?? false; } diff --git a/app/client/src/git/hooks/useCurrentBranch.ts b/app/client/src/git/hooks/useCurrentBranch.ts index 2077d0cd39f5..ddc7f96ebd5a 100644 --- a/app/client/src/git/hooks/useCurrentBranch.ts +++ b/app/client/src/git/hooks/useCurrentBranch.ts @@ -4,5 +4,5 @@ import { useGitContext } from "git/components/GitContextProvider"; export default function useCurrentBranch() { const { artifact } = useGitContext(); - return artifact?.gitApplicationMetadata?.branchName; + return artifact?.gitApplicationMetadata?.branchName ?? null; } diff --git a/app/client/src/git/hooks/useDiscard.ts b/app/client/src/git/hooks/useDiscard.ts index 2f71c11608f9..76291a637ae1 100644 --- a/app/client/src/git/hooks/useDiscard.ts +++ b/app/client/src/git/hooks/useDiscard.ts @@ -1,24 +1,26 @@ import { useGitContext } from "git/components/GitContextProvider"; import { gitArtifactActions } from "git/store/gitArtifactSlice"; import { selectDiscardState } from "git/store/selectors/gitSingleArtifactSelectors"; -import type { GitRootState } from "git/store/types"; import { useCallback } from "react"; -import { useDispatch, useSelector } from "react-redux"; +import { useDispatch } from "react-redux"; +import useAritfactSelector from "./useArtifactSelector"; export default function useDiscard() { const { artifactDef } = useGitContext(); const dispatch = useDispatch(); - const discardState = useSelector((state: GitRootState) => - selectDiscardState(state, artifactDef), - ); + const discardState = useAritfactSelector(selectDiscardState); const discard = useCallback(() => { - dispatch(gitArtifactActions.discardInit(artifactDef)); + if (artifactDef) { + dispatch(gitArtifactActions.discardInit({ artifactDef })); + } }, [artifactDef, dispatch]); const clearDiscardError = useCallback(() => { - dispatch(gitArtifactActions.clearDiscardError(artifactDef)); + if (artifactDef) { + dispatch(gitArtifactActions.clearDiscardError({ artifactDef })); + } }, [artifactDef, dispatch]); return { diff --git a/app/client/src/git/hooks/useDisconnect.ts b/app/client/src/git/hooks/useDisconnect.ts index 36dfd2cf8cf9..f9734d609ba7 100644 --- a/app/client/src/git/hooks/useDisconnect.ts +++ b/app/client/src/git/hooks/useDisconnect.ts @@ -5,9 +5,9 @@ import { selectDisconnectBaseArtifactId, selectDisconnectState, } from "git/store/selectors/gitSingleArtifactSelectors"; -import type { GitRootState } from "git/store/types"; import { useCallback } from "react"; -import { useDispatch, useSelector } from "react-redux"; +import { useDispatch } from "react-redux"; +import useAritfactSelector from "./useArtifactSelector"; export default function useDisconnect() { const { artifact, artifactDef } = useGitContext(); @@ -15,30 +15,34 @@ export default function useDisconnect() { const dispatch = useDispatch(); - const disconnectState = useSelector((state: GitRootState) => - selectDisconnectState(state, artifactDef), - ); + const disconnectState = useAritfactSelector(selectDisconnectState); const disconnect = useCallback(() => { - dispatch(gitArtifactActions.disconnectInit(artifactDef)); + if (artifactDef) { + dispatch(gitArtifactActions.disconnectInit); + } }, [artifactDef, dispatch]); - const disconnectBaseArtifactId = useSelector((state: GitRootState) => - selectDisconnectBaseArtifactId(state, artifactDef), + const disconnectBaseArtifactId = useAritfactSelector( + selectDisconnectBaseArtifactId, ); - const disconnectArtifactName = useSelector((state: GitRootState) => - selectDisconnectArtifactName(state, artifactDef), + const disconnectArtifactName = useAritfactSelector( + selectDisconnectArtifactName, ); const openDisconnectModal = useCallback(() => { - dispatch( - gitArtifactActions.openDisconnectModal({ ...artifactDef, artifactName }), - ); + if (artifactDef) { + dispatch( + gitArtifactActions.openDisconnectModal({ artifactDef, artifactName }), + ); + } }, [artifactDef, artifactName, dispatch]); const closeDisconnectModal = useCallback(() => { - dispatch(gitArtifactActions.closeDisconnectModal(artifactDef)); + if (artifactDef) { + dispatch(gitArtifactActions.closeDisconnectModal({ artifactDef })); + } }, [artifactDef, dispatch]); return { diff --git a/app/client/src/git/hooks/useGitPermissions.ts b/app/client/src/git/hooks/useGitPermissions.ts index 3279dcd3e00e..13ca2404a161 100644 --- a/app/client/src/git/hooks/useGitPermissions.ts +++ b/app/client/src/git/hooks/useGitPermissions.ts @@ -10,47 +10,46 @@ import { useMemo } from "react"; export default function useGitPermissions() { const { artifact, artifactDef } = useGitContext(); - const { artifactType } = artifactDef; const isConnectPermitted = useMemo(() => { if (artifact) { - if (artifactType === GitArtifactType.Application) { + if (artifactDef?.artifactType === GitArtifactType.Application) { return hasConnectToGitPermission(artifact.userPermissions); } } return false; - }, [artifact, artifactType]); + }, [artifact, artifactDef?.artifactType]); const isManageDefaultBranchPermitted = useMemo(() => { if (artifact) { - if (artifactType === GitArtifactType.Application) { + if (artifactDef?.artifactType === GitArtifactType.Application) { return hasManageDefaultBranchPermission(artifact.userPermissions); } } return false; - }, [artifact, artifactType]); + }, [artifact, artifactDef?.artifactType]); const isManageProtectedBranchesPermitted = useMemo(() => { if (artifact) { - if (artifactType === GitArtifactType.Application) { + if (artifactDef?.artifactType === GitArtifactType.Application) { return hasManageProtectedBranchesPermission(artifact.userPermissions); } } return false; - }, [artifact, artifactType]); + }, [artifact, artifactDef?.artifactType]); const isManageAutocommitPermitted = useMemo(() => { if (artifact) { - if (artifactType === GitArtifactType.Application) { + if (artifactDef?.artifactType === GitArtifactType.Application) { return hasManageAutoCommitPermission(artifact.userPermissions); } } return false; - }, [artifact, artifactType]); + }, [artifact, artifactDef?.artifactType]); return { isConnectPermitted, diff --git a/app/client/src/git/hooks/useLocalProfile.ts b/app/client/src/git/hooks/useLocalProfile.ts index e770ad6356bc..0bce80a705ad 100644 --- a/app/client/src/git/hooks/useLocalProfile.ts +++ b/app/client/src/git/hooks/useLocalProfile.ts @@ -5,35 +5,39 @@ import { selectFetchLocalProfileState, selectUpdateLocalProfileState, } from "git/store/selectors/gitSingleArtifactSelectors"; -import type { GitRootState } from "git/store/types"; import { useCallback } from "react"; -import { useDispatch, useSelector } from "react-redux"; +import { useDispatch } from "react-redux"; +import useAritfactSelector from "./useArtifactSelector"; export default function useLocalProfile() { const { artifactDef } = useGitContext(); const dispatch = useDispatch(); - const fetchLocalProfileState = useSelector((state: GitRootState) => - selectFetchLocalProfileState(state, artifactDef), + const fetchLocalProfileState = useAritfactSelector( + selectFetchLocalProfileState, ); const fetchLocalProfile = useCallback(() => { - dispatch(gitArtifactActions.fetchLocalProfileInit(artifactDef)); + if (artifactDef) { + dispatch(gitArtifactActions.fetchLocalProfileInit({ artifactDef })); + } }, [artifactDef, dispatch]); - const updateLocalProfileState = useSelector((state: GitRootState) => - selectUpdateLocalProfileState(state, artifactDef), + const updateLocalProfileState = useAritfactSelector( + selectUpdateLocalProfileState, ); const updateLocalProfile = useCallback( (params: UpdateLocalProfileRequestParams) => { - dispatch( - gitArtifactActions.updateLocalProfileInit({ - ...artifactDef, - ...params, - }), - ); + if (artifactDef) { + dispatch( + gitArtifactActions.updateLocalProfileInit({ + artifactDef, + ...params, + }), + ); + } }, [artifactDef, dispatch], ); diff --git a/app/client/src/git/hooks/useMerge.ts b/app/client/src/git/hooks/useMerge.ts index f7394601b191..324e532a5daf 100644 --- a/app/client/src/git/hooks/useMerge.ts +++ b/app/client/src/git/hooks/useMerge.ts @@ -4,9 +4,9 @@ import { selectMergeState, selectMergeStatusState, } from "git/store/selectors/gitSingleArtifactSelectors"; -import type { GitRootState } from "git/store/types"; import { useCallback } from "react"; -import { useDispatch, useSelector } from "react-redux"; +import { useDispatch } from "react-redux"; +import useAritfactSelector from "./useArtifactSelector"; export default function useMerge() { const { artifact, artifactDef } = useGitContext(); @@ -14,44 +14,46 @@ export default function useMerge() { const dispatch = useDispatch(); // merge - const mergeState = useSelector((state: GitRootState) => - selectMergeState(state, artifactDef), - ); + const mergeState = useAritfactSelector(selectMergeState); const merge = useCallback(() => { - dispatch(gitArtifactActions.mergeInit(artifactDef)); + if (artifactDef) { + dispatch(gitArtifactActions.mergeInit({ artifactDef })); + } }, [artifactDef, dispatch]); // merge status - const mergeStatusState = useSelector((state: GitRootState) => - selectMergeStatusState(state, artifactDef), - ); + const mergeStatusState = useAritfactSelector(selectMergeStatusState); const fetchMergeStatus = useCallback( (sourceBranch: string, destinationBranch: string) => { - dispatch( - gitArtifactActions.fetchMergeStatusInit({ - ...artifactDef, - artifactId: artifactId ?? "", - sourceBranch, - destinationBranch, - }), - ); + if (artifactDef) { + dispatch( + gitArtifactActions.fetchMergeStatusInit({ + artifactDef, + artifactId: artifactId ?? "", + sourceBranch, + destinationBranch, + }), + ); + } }, [artifactId, artifactDef, dispatch], ); const clearMergeStatus = useCallback(() => { - dispatch(gitArtifactActions.clearMergeStatus(artifactDef)); + if (artifactDef) { + dispatch(gitArtifactActions.clearMergeStatus({ artifactDef })); + } }, [artifactDef, dispatch]); return { isMergeLoading: mergeState?.loading ?? false, - mergeError: mergeState?.error, + mergeError: mergeState?.error ?? null, merge, - mergeStatus: mergeStatusState?.value, + mergeStatus: mergeStatusState?.value ?? null, isFetchMergeStatusLoading: mergeStatusState?.loading ?? false, - fetchMergeStatusError: mergeStatusState?.error, + fetchMergeStatusError: mergeStatusState?.error ?? null, fetchMergeStatus, clearMergeStatus, }; diff --git a/app/client/src/git/hooks/useMetadata.ts b/app/client/src/git/hooks/useMetadata.ts index 3edad04d8560..121c2f93768d 100644 --- a/app/client/src/git/hooks/useMetadata.ts +++ b/app/client/src/git/hooks/useMetadata.ts @@ -1,14 +1,8 @@ -import { useGitContext } from "git/components/GitContextProvider"; import { selectMetadataState } from "git/store/selectors/gitSingleArtifactSelectors"; -import type { GitRootState } from "git/store/types"; -import { useSelector } from "react-redux"; +import useAritfactSelector from "./useArtifactSelector"; export default function useMetadata() { - const { artifactDef } = useGitContext(); - - const metadataState = useSelector((state: GitRootState) => - selectMetadataState(state, artifactDef), - ); + const metadataState = useAritfactSelector(selectMetadataState); return { metadata: metadataState?.value ?? null, diff --git a/app/client/src/git/hooks/useOps.ts b/app/client/src/git/hooks/useOps.ts index 32eec997cf25..527a4e4ecf9f 100644 --- a/app/client/src/git/hooks/useOps.ts +++ b/app/client/src/git/hooks/useOps.ts @@ -6,9 +6,9 @@ import { selectOpsModalOpen, selectOpsModalTab, } from "git/store/selectors/gitSingleArtifactSelectors"; -import type { GitRootState } from "git/store/types"; import { useCallback } from "react"; -import { useDispatch, useSelector } from "react-redux"; +import { useDispatch } from "react-redux"; +import useAritfactSelector from "./useArtifactSelector"; export default function useOps() { const { artifactDef } = useGitContext(); @@ -16,42 +16,40 @@ export default function useOps() { const dispatch = useDispatch(); // ops modal - const opsModalOpen = useSelector((state: GitRootState) => - selectOpsModalOpen(state, artifactDef), - ); + const opsModalOpen = useAritfactSelector(selectOpsModalOpen); - const opsModalTab = useSelector((state: GitRootState) => - selectOpsModalTab(state, artifactDef), - ); + const opsModalTab = useAritfactSelector(selectOpsModalTab); const toggleOpsModal = useCallback( (open: boolean, tab: keyof typeof GitOpsTab = GitOpsTab.Deploy) => { - dispatch( - gitArtifactActions.toggleOpsModal({ ...artifactDef, open, tab }), - ); + if (artifactDef) { + dispatch(gitArtifactActions.toggleOpsModal({ artifactDef, open, tab })); + } }, [artifactDef, dispatch], ); // conflict error modal - const conflictErrorModalOpen = useSelector((state: GitRootState) => - selectConflictErrorModalOpen(state, artifactDef), + const conflictErrorModalOpen = useAritfactSelector( + selectConflictErrorModalOpen, ); const toggleConflictErrorModal = useCallback( (open: boolean) => { - dispatch( - gitArtifactActions.toggleConflictErrorModal({ ...artifactDef, open }), - ); + if (artifactDef) { + dispatch( + gitArtifactActions.toggleConflictErrorModal({ artifactDef, open }), + ); + } }, [artifactDef, dispatch], ); return { opsModalTab, - opsModalOpen, + isOpsModalOpen: opsModalOpen ?? false, toggleOpsModal, - conflictErrorModalOpen, + isConflictErrorModalOpen: conflictErrorModalOpen ?? false, toggleConflictErrorModal, }; } diff --git a/app/client/src/git/hooks/useProtectedBranches.ts b/app/client/src/git/hooks/useProtectedBranches.ts index f59b18f1ce10..799303cb4bca 100644 --- a/app/client/src/git/hooks/useProtectedBranches.ts +++ b/app/client/src/git/hooks/useProtectedBranches.ts @@ -4,46 +4,52 @@ import { selectFetchProtectedBranchesState, selectUpdateProtectedBranchesState, } from "git/store/selectors/gitSingleArtifactSelectors"; -import type { GitRootState } from "git/store/types"; import { useCallback } from "react"; -import { useDispatch, useSelector } from "react-redux"; +import { useDispatch } from "react-redux"; +import useAritfactSelector from "./useArtifactSelector"; function useProtectedBranches() { const { artifactDef } = useGitContext(); const dispatch = useDispatch(); - const fetchProtectedBranchesState = useSelector((state: GitRootState) => - selectFetchProtectedBranchesState(state, artifactDef), + const fetchProtectedBranchesState = useAritfactSelector( + selectFetchProtectedBranchesState, ); const fetchProtectedBranches = useCallback(() => { - dispatch(gitArtifactActions.fetchProtectedBranchesInit(artifactDef)); + if (artifactDef) { + dispatch(gitArtifactActions.fetchProtectedBranchesInit({ artifactDef })); + } }, [dispatch, artifactDef]); - const updateProtectedBranchesState = useSelector((state: GitRootState) => - selectUpdateProtectedBranchesState(state, artifactDef), + const updateProtectedBranchesState = useAritfactSelector( + selectUpdateProtectedBranchesState, ); const updateProtectedBranches = useCallback( (branches: string[]) => { - dispatch( - gitArtifactActions.updateProtectedBranchesInit({ - ...artifactDef, - branchNames: branches, - }), - ); + if (artifactDef) { + dispatch( + gitArtifactActions.updateProtectedBranchesInit({ + artifactDef, + branchNames: branches, + }), + ); + } }, [dispatch, artifactDef], ); return { - protectedBranches: fetchProtectedBranchesState.value, - isFetchProtectedBranchesLoading: fetchProtectedBranchesState.loading, - fetchProtectedBranchesError: fetchProtectedBranchesState.error, + protectedBranches: fetchProtectedBranchesState?.value ?? null, + isFetchProtectedBranchesLoading: + fetchProtectedBranchesState?.loading ?? false, + fetchProtectedBranchesError: fetchProtectedBranchesState?.error ?? null, fetchProtectedBranches, - isUpdateProtectedBranchesLoading: updateProtectedBranchesState.loading, - updateProtectedBranchesError: updateProtectedBranchesState.error, + isUpdateProtectedBranchesLoading: + updateProtectedBranchesState?.loading ?? false, + updateProtectedBranchesError: updateProtectedBranchesState?.error ?? null, updateProtectedBranches, }; } diff --git a/app/client/src/git/hooks/useProtectedMode.ts b/app/client/src/git/hooks/useProtectedMode.ts index b97d3793e7ff..b4475f5fc105 100644 --- a/app/client/src/git/hooks/useProtectedMode.ts +++ b/app/client/src/git/hooks/useProtectedMode.ts @@ -1,14 +1,8 @@ -import { useGitContext } from "git/components/GitContextProvider"; import { selectProtectedMode } from "git/store/selectors/gitSingleArtifactSelectors"; -import type { GitRootState } from "git/store/types"; -import { useSelector } from "react-redux"; +import useAritfactSelector from "./useArtifactSelector"; export default function useProtectedMode() { - const { artifactDef } = useGitContext(); + const isProtectedMode = useAritfactSelector(selectProtectedMode); - const isProtectedMode = useSelector((state: GitRootState) => { - return selectProtectedMode(state, artifactDef); - }); - - return isProtectedMode; + return isProtectedMode ?? false; } diff --git a/app/client/src/git/hooks/usePull.ts b/app/client/src/git/hooks/usePull.ts index 992866f2c277..c7b67031d6e1 100644 --- a/app/client/src/git/hooks/usePull.ts +++ b/app/client/src/git/hooks/usePull.ts @@ -1,26 +1,26 @@ import { useGitContext } from "git/components/GitContextProvider"; import { gitArtifactActions } from "git/store/gitArtifactSlice"; import { selectPullState } from "git/store/selectors/gitSingleArtifactSelectors"; -import type { GitRootState } from "git/store/types"; import { useCallback } from "react"; -import { useDispatch, useSelector } from "react-redux"; +import { useDispatch } from "react-redux"; +import useAritfactSelector from "./useArtifactSelector"; export default function usePull() { const { artifact, artifactDef } = useGitContext(); const artifactId = artifact?.id; const dispatch = useDispatch(); - const pullState = useSelector((state: GitRootState) => - selectPullState(state, artifactDef), - ); + const pullState = useAritfactSelector(selectPullState); const pull = useCallback(() => { - dispatch( - gitArtifactActions.pullInit({ - ...artifactDef, - artifactId: artifactId ?? "", - }), - ); + if (artifactDef) { + dispatch( + gitArtifactActions.pullInit({ + artifactDef, + artifactId: artifactId ?? "", + }), + ); + } }, [artifactDef, artifactId, dispatch]); return { diff --git a/app/client/src/git/hooks/useSettings.ts b/app/client/src/git/hooks/useSettings.ts index d94f9c0e530b..7605ad6cfaa1 100644 --- a/app/client/src/git/hooks/useSettings.ts +++ b/app/client/src/git/hooks/useSettings.ts @@ -5,38 +5,36 @@ import { selectSettingsModalOpen, selectSettingsModalTab, } from "git/store/selectors/gitSingleArtifactSelectors"; -import type { GitRootState } from "git/store/types"; import { useCallback } from "react"; -import { useDispatch, useSelector } from "react-redux"; +import { useDispatch } from "react-redux"; +import useAritfactSelector from "./useArtifactSelector"; export default function useSettings() { const { artifactDef } = useGitContext(); const dispatch = useDispatch(); - const settingsModalOpen = useSelector((state: GitRootState) => - selectSettingsModalOpen(state, artifactDef), - ); + const settingsModalOpen = useAritfactSelector(selectSettingsModalOpen); - const settingsModalTab = useSelector((state: GitRootState) => - selectSettingsModalTab(state, artifactDef), - ); + const settingsModalTab = useAritfactSelector(selectSettingsModalTab); const toggleSettingsModal = useCallback( ( open: boolean, tab: keyof typeof GitSettingsTab = GitSettingsTab.General, ) => { - dispatch( - gitArtifactActions.toggleSettingsModal({ ...artifactDef, open, tab }), - ); + if (artifactDef) { + dispatch( + gitArtifactActions.toggleSettingsModal({ artifactDef, open, tab }), + ); + } }, [artifactDef, dispatch], ); return { isSettingsModalOpen: settingsModalOpen ?? false, - settingsModalTab: settingsModalTab ?? GitSettingsTab.General, + settingsModalTab: settingsModalTab, toggleSettingsModal, }; } diff --git a/app/client/src/git/hooks/useStatus.ts b/app/client/src/git/hooks/useStatus.ts index 97b09b57498a..beec34e01ca1 100644 --- a/app/client/src/git/hooks/useStatus.ts +++ b/app/client/src/git/hooks/useStatus.ts @@ -1,31 +1,33 @@ import { useGitContext } from "git/components/GitContextProvider"; import { gitArtifactActions } from "git/store/gitArtifactSlice"; import { selectStatusState } from "git/store/selectors/gitSingleArtifactSelectors"; -import type { GitRootState } from "git/store/types"; import { useCallback } from "react"; -import { useDispatch, useSelector } from "react-redux"; +import { useDispatch } from "react-redux"; +import useAritfactSelector from "./useArtifactSelector"; export default function useStatus() { - const { artifactDef } = useGitContext(); + const { artifact, artifactDef } = useGitContext(); + const artifactId = artifact?.id; const dispatch = useDispatch(); - const statusState = useSelector((state: GitRootState) => - selectStatusState(state, artifactDef), - ); + const statusState = useAritfactSelector(selectStatusState); const fetchStatus = useCallback(() => { - dispatch( - gitArtifactActions.fetchStatusInit({ - ...artifactDef, - compareRemote: true, - }), - ); - }, [artifactDef, dispatch]); + if (artifactDef && artifactId) { + dispatch( + gitArtifactActions.fetchStatusInit({ + artifactId, + artifactDef, + compareRemote: true, + }), + ); + } + }, [artifactDef, artifactId, dispatch]); return { - status: statusState?.value, + status: statusState?.value ?? null, isFetchStatusLoading: statusState?.loading ?? false, - fetchStatusError: statusState?.error, + fetchStatusError: statusState?.error ?? null, fetchStatus, }; } diff --git a/app/client/src/git/index.ts b/app/client/src/git/index.ts index 37206b881573..72ad9840c06f 100644 --- a/app/client/src/git/index.ts +++ b/app/client/src/git/index.ts @@ -6,6 +6,7 @@ export { default as GitContextProvider } from "./components/GitContextProvider"; export { default as GitModals } from "./ee/components/GitModals"; export { default as GitImportModal } from "./components/ImportModal"; export { default as GitQuickActions } from "./components/QuickActions"; +export { default as GitProtectedBranchCallout } from "./components/ProtectedBranchCallout"; // hooks export { default as useGitCurrentBranch } from "./hooks/useCurrentBranch"; diff --git a/app/client/src/git/requests/connectRequest.types.ts b/app/client/src/git/requests/connectRequest.types.ts index 7e31cf32bf82..d47cc4114b21 100644 --- a/app/client/src/git/requests/connectRequest.types.ts +++ b/app/client/src/git/requests/connectRequest.types.ts @@ -1,4 +1,5 @@ import type { ApiResponse } from "api/types"; +import type { ApplicationPayload } from "entities/Application"; export interface ConnectRequestParams { remoteUrl: string; @@ -9,20 +10,6 @@ export interface ConnectRequestParams { }; } -export interface ConnectResponseData { - id: string; - baseId: string; - gitApplicationMetadata: { - branchName: string; - browserSupportedRemoteUrl: string; - defaultApplicationId: string; - defaultArtifactId: string; - defaultBranchName: string; - isRepoPrivate: boolean; - lastCommitedAt: string; - remoteUrl: string; - repoName: string; - }; -} +export interface ConnectResponseData extends ApplicationPayload {} export type ConnectResponse = ApiResponse; diff --git a/app/client/src/git/sagas/checkoutBranchSaga.ts b/app/client/src/git/sagas/checkoutBranchSaga.ts index 34e48434626c..7fc454f36bc0 100644 --- a/app/client/src/git/sagas/checkoutBranchSaga.ts +++ b/app/client/src/git/sagas/checkoutBranchSaga.ts @@ -25,8 +25,7 @@ import { captureException } from "@sentry/react"; export default function* checkoutBranchSaga( action: GitArtifactPayloadAction, ) { - const { artifactType, baseArtifactId, branchName } = action.payload; - const basePayload = { artifactType, baseArtifactId }; + const { artifactDef, artifactId, branchName } = action.payload; let response: CheckoutBranchResponse | undefined; try { @@ -34,12 +33,12 @@ export default function* checkoutBranchSaga( branchName, }; - response = yield call(checkoutBranchRequest, baseArtifactId, params); + response = yield call(checkoutBranchRequest, artifactId, params); const isValidResponse: boolean = yield validateResponse(response); if (response && isValidResponse) { - if (artifactType === GitArtifactType.Application) { - yield put(gitArtifactActions.checkoutBranchSuccess(basePayload)); + if (artifactDef.artifactType === GitArtifactType.Application) { + yield put(gitArtifactActions.checkoutBranchSuccess({ artifactDef })); const trimmedBranch = branchName.replace(/^origin\//, ""); const destinationHref = addBranchParam(trimmedBranch); @@ -49,7 +48,7 @@ export default function* checkoutBranchSaga( yield put( gitArtifactActions.toggleBranchPopup({ - ...basePayload, + artifactDef, open: false, }), ); @@ -118,7 +117,7 @@ export default function* checkoutBranchSaga( yield put( gitArtifactActions.checkoutBranchError({ - ...basePayload, + artifactDef, error, }), ); diff --git a/app/client/src/git/sagas/commitSaga.ts b/app/client/src/git/sagas/commitSaga.ts index 159021acc145..7ebcb70b9a71 100644 --- a/app/client/src/git/sagas/commitSaga.ts +++ b/app/client/src/git/sagas/commitSaga.ts @@ -17,8 +17,7 @@ import { validateResponse } from "sagas/ErrorSagas"; export default function* commitSaga( action: GitArtifactPayloadAction, ) { - const { artifactType, baseArtifactId } = action.payload; - const basePayload = { artifactType, baseArtifactId }; + const { artifactDef, artifactId } = action.payload; let response: CommitResponse | undefined; @@ -28,20 +27,21 @@ export default function* commitSaga( doPush: action.payload.doPush, }; - response = yield call(commitRequest, baseArtifactId, params); + response = yield call(commitRequest, artifactId, params); const isValidResponse: boolean = yield validateResponse(response, false); if (isValidResponse) { - yield put(gitArtifactActions.commitSuccess(basePayload)); + yield put(gitArtifactActions.commitSuccess({ artifactDef })); yield put( gitArtifactActions.fetchStatusInit({ - ...basePayload, + artifactDef, + artifactId, compareRemote: true, }), ); - if (artifactType === GitArtifactType.Application) { + if (artifactDef.artifactType === GitArtifactType.Application) { // ! case for updating lastDeployedAt in application manually? } } @@ -52,13 +52,13 @@ export default function* commitSaga( if (error.code === GitErrorCodes.REPO_LIMIT_REACHED) { yield put( gitArtifactActions.toggleRepoLimitErrorModal({ - ...basePayload, + artifactDef, open: true, }), ); } - yield put(gitArtifactActions.commitError({ ...basePayload, error })); + yield put(gitArtifactActions.commitError({ artifactDef, error })); } else { log.error(e); captureException(e); diff --git a/app/client/src/git/sagas/connectSaga.ts b/app/client/src/git/sagas/connectSaga.ts index b13c2f6c2c2a..d99627c189a1 100644 --- a/app/client/src/git/sagas/connectSaga.ts +++ b/app/client/src/git/sagas/connectSaga.ts @@ -21,8 +21,7 @@ import { captureException } from "@sentry/react"; export default function* connectSaga( action: GitArtifactPayloadAction, ) { - const { artifactType, baseArtifactId } = action.payload; - const basePayload = { artifactType, baseArtifactId }; + const { artifactDef } = action.payload; let response: ConnectResponse | undefined; @@ -32,31 +31,35 @@ export default function* connectSaga( gitProfile: action.payload.gitProfile, }; - response = yield call(connectRequest, baseArtifactId, params); + response = yield call(connectRequest, artifactDef.baseArtifactId, params); const isValidResponse: boolean = yield validateResponse(response, false); if (response && isValidResponse) { - yield put(gitArtifactActions.connectSuccess(basePayload)); + yield put(gitArtifactActions.connectSuccess({ artifactDef })); // needs to happen only when artifactType is application - if (artifactType === GitArtifactType.Application) { + if (artifactDef.artifactType === GitArtifactType.Application) { const { branchedPageId } = action.payload; if (branchedPageId) { yield put(fetchPageAction(branchedPageId)); } - const branch = response.data.gitApplicationMetadata.branchName; - const newUrl = addBranchParam(branch); + const branch = response.data?.gitApplicationMetadata?.branchName; + + if (branch) { + const newUrl = addBranchParam(branch); + + history.replace(newUrl); + } - history.replace(newUrl); // ! case for updating lastDeployedAt in application manually? } yield put( gitArtifactActions.initGitForEditor({ - ...basePayload, + artifactDef, artifact: response.data, }), ); @@ -68,13 +71,13 @@ export default function* connectSaga( if (GitErrorCodes.REPO_LIMIT_REACHED === error.code) { yield put( gitArtifactActions.toggleRepoLimitErrorModal({ - ...basePayload, + artifactDef, open: true, }), ); } - yield put(gitArtifactActions.connectError({ ...basePayload, error })); + yield put(gitArtifactActions.connectError({ artifactDef, error })); } else { log.error(e); captureException(e); diff --git a/app/client/src/git/sagas/createBranchSaga.ts b/app/client/src/git/sagas/createBranchSaga.ts index 7796f43d74bd..d8aa65418977 100644 --- a/app/client/src/git/sagas/createBranchSaga.ts +++ b/app/client/src/git/sagas/createBranchSaga.ts @@ -16,8 +16,8 @@ import log from "loglevel"; export default function* createBranchSaga( action: GitArtifactPayloadAction, ) { - const { artifactType, baseArtifactId } = action.payload; - const basePayload = { artifactType, baseArtifactId }; + const { artifactDef, artifactId } = action.payload; + const basePayload = { artifactDef }; let response: CreateBranchResponse | undefined; try { @@ -25,27 +25,29 @@ export default function* createBranchSaga( branchName: action.payload.branchName, }; - response = yield call(createBranchRequest, baseArtifactId, params); + response = yield call(createBranchRequest, artifactId, params); const isValidResponse: boolean = yield validateResponse(response); if (isValidResponse) { yield put(gitArtifactActions.createBranchSuccess(basePayload)); yield put( gitArtifactActions.toggleBranchPopup({ - ...basePayload, + artifactDef, open: false, }), ); yield put( gitArtifactActions.fetchBranchesInit({ - ...basePayload, + artifactDef, + artifactId, pruneBranches: true, }), ); yield put( gitArtifactActions.checkoutBranchInit({ - ...basePayload, + artifactDef, + artifactId, branchName: action.payload.branchName, }), ); @@ -56,7 +58,7 @@ export default function* createBranchSaga( yield put( gitArtifactActions.createBranchError({ - ...basePayload, + artifactDef, error, }), ); diff --git a/app/client/src/git/sagas/deleteBranchSaga.ts b/app/client/src/git/sagas/deleteBranchSaga.ts index 4f6bdde2f7fc..ecf560889f1c 100644 --- a/app/client/src/git/sagas/deleteBranchSaga.ts +++ b/app/client/src/git/sagas/deleteBranchSaga.ts @@ -16,8 +16,7 @@ import { captureException } from "@sentry/react"; export default function* deleteBranchSaga( action: GitArtifactPayloadAction, ) { - const { artifactType, baseArtifactId } = action.payload; - const basePayload = { artifactType, baseArtifactId }; + const { artifactDef, artifactId } = action.payload; let response: DeleteBranchResponse | undefined; try { @@ -25,14 +24,19 @@ export default function* deleteBranchSaga( branchName: action.payload.branchName, }; - response = yield call(deleteBranchRequest, baseArtifactId, params); + response = yield call( + deleteBranchRequest, + artifactDef.baseArtifactId, + params, + ); const isValidResponse: boolean = yield validateResponse(response); if (isValidResponse) { - yield put(gitArtifactActions.deleteBranchSuccess(basePayload)); + yield put(gitArtifactActions.deleteBranchSuccess({ artifactDef })); yield put( gitArtifactActions.fetchBranchesInit({ - ...basePayload, + artifactDef, + artifactId, pruneBranches: true, }), ); @@ -41,12 +45,7 @@ export default function* deleteBranchSaga( if (response && response.responseMeta.error) { const { error } = response.responseMeta; - yield put( - gitArtifactActions.deleteBranchError({ - ...basePayload, - error, - }), - ); + yield put(gitArtifactActions.deleteBranchError({ artifactDef, error })); } else { log.error(e); captureException(e); diff --git a/app/client/src/git/sagas/disconnectSaga.ts b/app/client/src/git/sagas/disconnectSaga.ts index 3dc25f1ff079..89fdbd090c29 100644 --- a/app/client/src/git/sagas/disconnectSaga.ts +++ b/app/client/src/git/sagas/disconnectSaga.ts @@ -12,26 +12,25 @@ import { validateResponse } from "sagas/ErrorSagas"; import history from "utils/history"; export default function* disconnectSaga(action: GitArtifactPayloadAction) { - const { artifactType, baseArtifactId } = action.payload; - const artifactDef = { artifactType, baseArtifactId }; + const { artifactDef } = action.payload; let response: DisconnectResponse | undefined; try { - response = yield call(disconnectRequest, baseArtifactId); + response = yield call(disconnectRequest, artifactDef.baseArtifactId); const isValidResponse: boolean = yield validateResponse(response); if (response && isValidResponse) { - yield put(gitArtifactActions.disconnectSuccess(artifactDef)); + yield put(gitArtifactActions.disconnectSuccess({ artifactDef })); const url = new URL(window.location.href); url.searchParams.delete(GIT_BRANCH_QUERY_KEY); history.push(url.toString().slice(url.origin.length)); - yield put(gitArtifactActions.closeDisconnectModal(artifactDef)); + yield put(gitArtifactActions.closeDisconnectModal({ artifactDef })); // !case: why? // yield put(importAppViaGitStatusReset()); yield put( gitArtifactActions.toggleOpsModal({ - ...artifactDef, + artifactDef, open: false, tab: GitOpsTab.Deploy, }), @@ -52,7 +51,7 @@ export default function* disconnectSaga(action: GitArtifactPayloadAction) { if (response && response.responseMeta.error) { const { error } = response.responseMeta; - yield put(gitArtifactActions.disconnectError({ ...artifactDef, error })); + yield put(gitArtifactActions.disconnectError({ artifactDef, error })); } else { log.error(e); captureException(e); diff --git a/app/client/src/git/sagas/fetchBranchesSaga.ts b/app/client/src/git/sagas/fetchBranchesSaga.ts index 465310e01a4f..5141db03e34f 100644 --- a/app/client/src/git/sagas/fetchBranchesSaga.ts +++ b/app/client/src/git/sagas/fetchBranchesSaga.ts @@ -14,8 +14,7 @@ import { captureException } from "@sentry/react"; export default function* fetchBranchesSaga( action: GitArtifactPayloadAction, ) { - const { artifactType, baseArtifactId } = action.payload; - const basePayload = { artifactType, baseArtifactId }; + const { artifactDef, artifactId } = action.payload; let response: FetchBranchesResponse | undefined; try { @@ -23,13 +22,13 @@ export default function* fetchBranchesSaga( pruneBranches: action.payload.pruneBranches, }; - response = yield call(fetchBranchesRequest, baseArtifactId, params); + response = yield call(fetchBranchesRequest, artifactId, params); const isValidResponse: boolean = yield validateResponse(response, false); if (response && isValidResponse) { yield put( gitArtifactActions.fetchBranchesSuccess({ - ...basePayload, + artifactDef, responseData: response.data, }), ); @@ -40,7 +39,7 @@ export default function* fetchBranchesSaga( yield put( gitArtifactActions.fetchBranchesError({ - ...basePayload, + artifactDef, error, }), ); diff --git a/app/client/src/git/sagas/fetchLocalProfileSaga.ts b/app/client/src/git/sagas/fetchLocalProfileSaga.ts index c568129beab9..28f24ef2198d 100644 --- a/app/client/src/git/sagas/fetchLocalProfileSaga.ts +++ b/app/client/src/git/sagas/fetchLocalProfileSaga.ts @@ -10,18 +10,17 @@ import { captureException } from "@sentry/react"; export default function* fetchLocalProfileSaga( action: GitArtifactPayloadAction, ) { - const { artifactType, baseArtifactId } = action.payload; - const basePayload = { artifactType, baseArtifactId }; + const { artifactDef } = action.payload; let response: FetchLocalProfileResponse | undefined; try { - response = yield call(fetchLocalProfileRequest, baseArtifactId); + response = yield call(fetchLocalProfileRequest, artifactDef.baseArtifactId); const isValidResponse: boolean = yield validateResponse(response); if (response && isValidResponse) { yield put( gitArtifactActions.fetchLocalProfileSuccess({ - ...basePayload, + artifactDef, responseData: response.data, }), ); @@ -31,7 +30,7 @@ export default function* fetchLocalProfileSaga( const { error } = response.responseMeta; yield put( - gitArtifactActions.fetchLocalProfileError({ ...basePayload, error }), + gitArtifactActions.fetchLocalProfileError({ artifactDef, error }), ); } else { log.error(e); diff --git a/app/client/src/git/sagas/fetchMergeStatusSaga.ts b/app/client/src/git/sagas/fetchMergeStatusSaga.ts index 684233de206d..024954b017c5 100644 --- a/app/client/src/git/sagas/fetchMergeStatusSaga.ts +++ b/app/client/src/git/sagas/fetchMergeStatusSaga.ts @@ -14,8 +14,7 @@ import { validateResponse } from "sagas/ErrorSagas"; export default function* fetchMergeStatusSaga( action: GitArtifactPayloadAction, ) { - const { artifactId, artifactType, baseArtifactId } = action.payload; - const basePayload = { artifactType, baseArtifactId }; + const { artifactDef, artifactId } = action.payload; let response: FetchMergeStatusResponse | undefined; try { @@ -30,7 +29,7 @@ export default function* fetchMergeStatusSaga( if (response && isValidResponse) { yield put( gitArtifactActions.fetchMergeStatusSuccess({ - ...basePayload, + artifactDef, responseData: response.data, }), ); @@ -40,10 +39,7 @@ export default function* fetchMergeStatusSaga( const { error } = response.responseMeta; yield put( - gitArtifactActions.fetchMergeStatusError({ - ...basePayload, - error, - }), + gitArtifactActions.fetchMergeStatusError({ artifactDef, error }), ); } else { log.error(e); diff --git a/app/client/src/git/sagas/fetchMetadataSaga.ts b/app/client/src/git/sagas/fetchMetadataSaga.ts index 3e2029b6c6b8..9f8285847ee7 100644 --- a/app/client/src/git/sagas/fetchMetadataSaga.ts +++ b/app/client/src/git/sagas/fetchMetadataSaga.ts @@ -8,18 +8,17 @@ import { call, put } from "redux-saga/effects"; import { validateResponse } from "sagas/ErrorSagas"; export default function* fetchMetadataSaga(action: GitArtifactPayloadAction) { - const { artifactType, baseArtifactId } = action.payload; - const basePayload = { artifactType, baseArtifactId }; + const { artifactDef } = action.payload; let response: FetchMetadataResponse | undefined; try { - response = yield call(fetchMetadataRequest, baseArtifactId); + response = yield call(fetchMetadataRequest, artifactDef.baseArtifactId); const isValidResponse: boolean = yield validateResponse(response, false); if (response && isValidResponse) { yield put( gitArtifactActions.fetchMetadataSuccess({ - ...basePayload, + artifactDef, responseData: response.data, }), ); @@ -30,7 +29,7 @@ export default function* fetchMetadataSaga(action: GitArtifactPayloadAction) { yield put( gitArtifactActions.fetchMetadataError({ - ...basePayload, + artifactDef, error, }), ); diff --git a/app/client/src/git/sagas/fetchProtectedBranchesSaga.ts b/app/client/src/git/sagas/fetchProtectedBranchesSaga.ts index 9c81123ea26f..62f36f8ce93c 100644 --- a/app/client/src/git/sagas/fetchProtectedBranchesSaga.ts +++ b/app/client/src/git/sagas/fetchProtectedBranchesSaga.ts @@ -10,19 +10,21 @@ import { validateResponse } from "sagas/ErrorSagas"; export default function* fetchProtectedBranchesSaga( action: GitArtifactPayloadAction, ) { - const { artifactType, baseArtifactId } = action.payload; - const basePayload = { artifactType, baseArtifactId }; + const { artifactDef } = action.payload; let response: FetchProtectedBranchesResponse | undefined; try { - response = yield call(fetchProtectedBranchesRequest, baseArtifactId); + response = yield call( + fetchProtectedBranchesRequest, + artifactDef.baseArtifactId, + ); const isValidResponse: boolean = yield validateResponse(response); if (response && isValidResponse) { yield put( gitArtifactActions.fetchProtectedBranchesSuccess({ - ...basePayload, + artifactDef, responseData: response.data, }), ); @@ -33,7 +35,7 @@ export default function* fetchProtectedBranchesSaga( yield put( gitArtifactActions.fetchProtectedBranchesError({ - ...basePayload, + artifactDef, error, }), ); diff --git a/app/client/src/git/sagas/fetchSSHKeySaga.ts b/app/client/src/git/sagas/fetchSSHKeySaga.ts index 02f797edae66..16736e92f5d1 100644 --- a/app/client/src/git/sagas/fetchSSHKeySaga.ts +++ b/app/client/src/git/sagas/fetchSSHKeySaga.ts @@ -8,18 +8,17 @@ import { call, put } from "redux-saga/effects"; import { validateResponse } from "sagas/ErrorSagas"; export function* fetchSSHKeySaga(action: GitArtifactPayloadAction) { - const { artifactType, baseArtifactId } = action.payload; - const artifactDef = { artifactType, baseArtifactId }; + const { artifactDef } = action.payload; let response: FetchSSHKeyResponse | undefined; try { - response = yield call(fetchSSHKeyRequest, baseArtifactId); + response = yield call(fetchSSHKeyRequest, artifactDef.baseArtifactId); const isValidResponse: boolean = yield validateResponse(response, false); if (response && isValidResponse) { yield put( gitArtifactActions.fetchSSHKeySuccess({ - ...artifactDef, + artifactDef, responseData: response.data, }), ); @@ -28,7 +27,7 @@ export function* fetchSSHKeySaga(action: GitArtifactPayloadAction) { if (response && response.responseMeta.error) { const { error } = response.responseMeta; - yield put(gitArtifactActions.fetchSSHKeyError({ ...artifactDef, error })); + yield put(gitArtifactActions.fetchSSHKeyError({ artifactDef, error })); } else { log.error(e); captureException(e); diff --git a/app/client/src/git/sagas/fetchStatusSaga.ts b/app/client/src/git/sagas/fetchStatusSaga.ts index 4c714a22c0da..733f18cce776 100644 --- a/app/client/src/git/sagas/fetchStatusSaga.ts +++ b/app/client/src/git/sagas/fetchStatusSaga.ts @@ -11,18 +11,17 @@ import { validateResponse } from "sagas/ErrorSagas"; export default function* fetchStatusSaga( action: GitArtifactPayloadAction, ) { - const { artifactType, baseArtifactId } = action.payload; - const basePayload = { artifactType, baseArtifactId }; + const { artifactDef, artifactId } = action.payload; let response: FetchStatusResponse | undefined; try { - response = yield call(fetchStatusRequest, baseArtifactId); + response = yield call(fetchStatusRequest, artifactId); const isValidResponse: boolean = yield validateResponse(response); if (response && isValidResponse) { yield put( gitArtifactActions.fetchStatusSuccess({ - ...basePayload, + artifactDef, responseData: response.data, }), ); @@ -33,7 +32,7 @@ export default function* fetchStatusSaga( yield put( gitArtifactActions.fetchStatusError({ - ...basePayload, + artifactDef, error, }), ); diff --git a/app/client/src/git/sagas/generateSSHKeySaga.ts b/app/client/src/git/sagas/generateSSHKeySaga.ts index 09773f9dc0d4..7078466cc211 100644 --- a/app/client/src/git/sagas/generateSSHKeySaga.ts +++ b/app/client/src/git/sagas/generateSSHKeySaga.ts @@ -15,8 +15,7 @@ import { validateResponse } from "sagas/ErrorSagas"; export function* generateSSHKeySaga( action: GitArtifactPayloadAction, ) { - const { artifactType, baseArtifactId } = action.payload; - const artifactDef = { artifactType, baseArtifactId }; + const { artifactDef } = action.payload; let response: GenerateSSHKeyResponse | undefined; try { @@ -25,13 +24,17 @@ export function* generateSSHKeySaga( isImport: action.payload.isImport, }; - response = yield call(generateSSHKeyRequest, baseArtifactId, params); + response = yield call( + generateSSHKeyRequest, + artifactDef.baseArtifactId, + params, + ); const isValidResponse: boolean = yield validateResponse(response); if (response && isValidResponse) { yield put( gitArtifactActions.generateSSHKeySuccess({ - ...artifactDef, + artifactDef, responseData: response.data, }), ); @@ -43,15 +46,13 @@ export function* generateSSHKeySaga( if (GitErrorCodes.REPO_LIMIT_REACHED === error.code) { yield put( gitArtifactActions.toggleRepoLimitErrorModal({ - ...artifactDef, + artifactDef, open: true, }), ); } - yield put( - gitArtifactActions.generateSSHKeyError({ ...artifactDef, error }), - ); + yield put(gitArtifactActions.generateSSHKeyError({ artifactDef, error })); } else { log.error(e); captureException(e); diff --git a/app/client/src/git/sagas/initGitSaga.ts b/app/client/src/git/sagas/initGitSaga.ts index aa50efce17b1..b880b1854c41 100644 --- a/app/client/src/git/sagas/initGitSaga.ts +++ b/app/client/src/git/sagas/initGitSaga.ts @@ -7,24 +7,25 @@ import { put, take } from "redux-saga/effects"; export default function* initGitForEditorSaga( action: GitArtifactPayloadAction, ) { - const { artifact, artifactType, baseArtifactId } = action.payload; - const basePayload = { artifactType, baseArtifactId }; + const { artifact, artifactDef } = action.payload; + const artifactId = artifact?.id; - yield put(gitArtifactActions.mount(basePayload)); + yield put(gitArtifactActions.mount({ artifactDef })); - if (artifactType === GitArtifactType.Application) { - if (!!artifact.gitApplicationMetadata?.remoteUrl) { - yield put(gitArtifactActions.fetchMetadataInit(basePayload)); + if (artifactId && artifactDef.artifactType === GitArtifactType.Application) { + if (!!artifact?.gitApplicationMetadata?.remoteUrl) { + yield put(gitArtifactActions.fetchMetadataInit({ artifactDef })); yield take(gitArtifactActions.fetchMetadataSuccess.type); yield put( - gitArtifactActions.triggerAutocommitInit({ - ...basePayload, - artifactId: artifact.id, - }), + gitArtifactActions.triggerAutocommitInit({ artifactDef, artifactId }), + ); + yield put( + gitArtifactActions.fetchBranchesInit({ artifactDef, artifactId }), + ); + yield put(gitArtifactActions.fetchProtectedBranchesInit({ artifactDef })); + yield put( + gitArtifactActions.fetchStatusInit({ artifactDef, artifactId }), ); - yield put(gitArtifactActions.fetchBranchesInit(basePayload)); - yield put(gitArtifactActions.fetchProtectedBranchesInit(basePayload)); - yield put(gitArtifactActions.fetchStatusInit(basePayload)); } } } diff --git a/app/client/src/git/sagas/pullSaga.ts b/app/client/src/git/sagas/pullSaga.ts index eafb4a5c098b..40c59651d416 100644 --- a/app/client/src/git/sagas/pullSaga.ts +++ b/app/client/src/git/sagas/pullSaga.ts @@ -17,8 +17,7 @@ import { captureException } from "@sentry/react"; export default function* pullSaga( action: GitArtifactPayloadAction, ) { - const { artifactId, artifactType, baseArtifactId } = action.payload; - const basePayload = { artifactType, baseArtifactId }; + const { artifactDef, artifactId } = action.payload; let response: PullResponse | undefined; try { @@ -26,12 +25,12 @@ export default function* pullSaga( const isValidResponse: boolean = yield validateResponse(response); if (response && isValidResponse) { - yield put(gitArtifactActions.pullSuccess(basePayload)); + yield put(gitArtifactActions.pullSuccess({ artifactDef })); const currentBasePageId: string = yield select(getCurrentBasePageId); const currentBranch: string = yield select( selectCurrentBranch, - basePayload, + artifactDef, ); yield put( @@ -51,7 +50,7 @@ export default function* pullSaga( // yield put(setIsGitErrorPopupVisible({ isVisible: true })); // } - yield put(gitArtifactActions.pullError({ ...basePayload, error })); + yield put(gitArtifactActions.pullError({ artifactDef, error })); } else { log.error(e); captureException(e); diff --git a/app/client/src/git/sagas/toggleAutocommitSaga.ts b/app/client/src/git/sagas/toggleAutocommitSaga.ts index cf8b0e923c67..4f97d0289543 100644 --- a/app/client/src/git/sagas/toggleAutocommitSaga.ts +++ b/app/client/src/git/sagas/toggleAutocommitSaga.ts @@ -10,24 +10,23 @@ import { validateResponse } from "sagas/ErrorSagas"; export default function* toggleAutocommitSaga( action: GitArtifactPayloadAction, ) { - const { artifactType, baseArtifactId } = action.payload; - const artifactDef = { artifactType, baseArtifactId }; + const { artifactDef } = action.payload; let response: ToggleAutocommitResponse | undefined; try { - response = yield call(toggleAutocommitRequest, baseArtifactId); + response = yield call(toggleAutocommitRequest, artifactDef.baseArtifactId); const isValidResponse: boolean = yield validateResponse(response); if (isValidResponse) { - yield put(gitArtifactActions.toggleAutocommitSuccess(artifactDef)); - yield put(gitArtifactActions.fetchMetadataInit(artifactDef)); + yield put(gitArtifactActions.toggleAutocommitSuccess({ artifactDef })); + yield put(gitArtifactActions.fetchMetadataInit({ artifactDef })); } } catch (e) { if (response && response.responseMeta.error) { const { error } = response.responseMeta; yield put( - gitArtifactActions.toggleAutocommitError({ ...artifactDef, error }), + gitArtifactActions.toggleAutocommitError({ artifactDef, error }), ); } else { log.error(e); diff --git a/app/client/src/git/sagas/triggerAutocommitSaga.ts b/app/client/src/git/sagas/triggerAutocommitSaga.ts index d0b316f594ec..37ce54cc53f7 100644 --- a/app/client/src/git/sagas/triggerAutocommitSaga.ts +++ b/app/client/src/git/sagas/triggerAutocommitSaga.ts @@ -1,8 +1,5 @@ import { triggerAutocommitSuccessAction } from "actions/gitSyncActions"; -import { - AutocommitStatusState, - type GitArtifactType, -} from "git/constants/enums"; +import { AutocommitStatusState } from "git/constants/enums"; import fetchAutocommitProgressRequest from "git/requests/fetchAutocommitProgressRequest"; import type { FetchAutocommitProgressResponse, @@ -15,7 +12,10 @@ import type { } from "git/requests/triggerAutocommitRequest.types"; import type { TriggerAutocommitInitPayload } from "git/store/actions/triggerAutocommitActions"; import { gitArtifactActions } from "git/store/gitArtifactSlice"; -import { selectAutocommitEnabled } from "git/store/selectors/gitSingleArtifactSelectors"; +import { + selectAutocommitEnabled, + type GitArtifactDef, +} from "git/store/selectors/gitSingleArtifactSelectors"; import type { GitArtifactPayloadAction } from "git/store/types"; import { call, @@ -39,8 +39,7 @@ const AUTOCOMMIT_WHITELISTED_STATES = [ ]; interface PollAutocommitProgressParams { - artifactType: keyof typeof GitArtifactType; - baseArtifactId: string; + artifactDef: GitArtifactDef; artifactId: string; } @@ -57,8 +56,7 @@ function isAutocommitHappening( } function* pollAutocommitProgressSaga(params: PollAutocommitProgressParams) { - const { artifactId, artifactType, baseArtifactId } = params; - const basePayload = { artifactType, baseArtifactId }; + const { artifactDef, artifactId } = params; let triggerResponse: TriggerAutocommitResponse | undefined; try { @@ -66,14 +64,14 @@ function* pollAutocommitProgressSaga(params: PollAutocommitProgressParams) { const isValidResponse: boolean = yield validateResponse(triggerResponse); if (triggerResponse && isValidResponse) { - yield put(gitArtifactActions.triggerAutocommitSuccess(basePayload)); + yield put(gitArtifactActions.triggerAutocommitSuccess({ artifactDef })); } } catch (e) { if (triggerResponse && triggerResponse.responseMeta.error) { const { error } = triggerResponse.responseMeta; yield put( - gitArtifactActions.triggerAutocommitError({ ...basePayload, error }), + gitArtifactActions.triggerAutocommitError({ artifactDef, error }), ); } else { log.error(e); @@ -85,39 +83,47 @@ function* pollAutocommitProgressSaga(params: PollAutocommitProgressParams) { try { if (isAutocommitHappening(triggerResponse?.data)) { - yield put(gitArtifactActions.pollAutocommitProgressStart(basePayload)); + yield put( + gitArtifactActions.pollAutocommitProgressStart({ artifactDef }), + ); while (true) { - yield put(gitArtifactActions.fetchAutocommitProgressInit(basePayload)); + yield put( + gitArtifactActions.fetchAutocommitProgressInit({ artifactDef }), + ); progressResponse = yield call( fetchAutocommitProgressRequest, - baseArtifactId, + artifactDef.baseArtifactId, ); const isValidResponse: boolean = yield validateResponse(progressResponse); if (isValidResponse && !isAutocommitHappening(progressResponse?.data)) { - yield put(gitArtifactActions.pollAutocommitProgressStop(basePayload)); + yield put( + gitArtifactActions.pollAutocommitProgressStop({ artifactDef }), + ); } if (!isValidResponse) { - yield put(gitArtifactActions.pollAutocommitProgressStop(basePayload)); + yield put( + gitArtifactActions.pollAutocommitProgressStop({ artifactDef }), + ); } yield delay(AUTOCOMMIT_POLL_DELAY); } } else { - yield put(gitArtifactActions.pollAutocommitProgressStop(basePayload)); + yield put(gitArtifactActions.pollAutocommitProgressStop({ artifactDef })); } } catch (e) { - yield put(gitArtifactActions.pollAutocommitProgressStop(basePayload)); + yield put(gitArtifactActions.pollAutocommitProgressStop({ artifactDef })); if (progressResponse && progressResponse.responseMeta.error) { const { error } = progressResponse.responseMeta; yield put( gitArtifactActions.fetchAutocommitProgressError({ - ...basePayload, + artifactDef, error, }), ); @@ -131,15 +137,14 @@ function* pollAutocommitProgressSaga(params: PollAutocommitProgressParams) { export default function* triggerAutocommitSaga( action: GitArtifactPayloadAction, ) { - const { artifactId, artifactType, baseArtifactId } = action.payload; - const basePayload = { artifactType, baseArtifactId }; + const { artifactDef, artifactId } = action.payload; const isAutocommitEnabled: boolean = yield select( selectAutocommitEnabled, - basePayload, + artifactDef, ); if (isAutocommitEnabled) { - const params = { artifactType, baseArtifactId, artifactId }; + const params = { artifactDef, artifactId }; const pollTask: Task = yield fork(pollAutocommitProgressSaga, params); yield take(gitArtifactActions.pollAutocommitProgressStop.type); diff --git a/app/client/src/git/sagas/updateLocalProfileSaga.ts b/app/client/src/git/sagas/updateLocalProfileSaga.ts index 74579562b058..3b7253a391fe 100644 --- a/app/client/src/git/sagas/updateLocalProfileSaga.ts +++ b/app/client/src/git/sagas/updateLocalProfileSaga.ts @@ -14,8 +14,7 @@ import { captureException } from "@sentry/react"; export default function* updateLocalProfileSaga( action: GitArtifactPayloadAction, ) { - const { artifactType, baseArtifactId } = action.payload; - const basePayload = { artifactType, baseArtifactId }; + const { artifactDef } = action.payload; let response: UpdateLocalProfileResponse | undefined; try { @@ -25,20 +24,24 @@ export default function* updateLocalProfileSaga( useGlobalProfile: action.payload.useGlobalProfile, }; - response = yield call(updateLocalProfileRequest, baseArtifactId, params); + response = yield call( + updateLocalProfileRequest, + artifactDef.baseArtifactId, + params, + ); const isValidResponse: boolean = yield validateResponse(response); if (isValidResponse) { - yield put(gitArtifactActions.updateLocalProfileSuccess(basePayload)); - yield put(gitArtifactActions.fetchLocalProfileInit(basePayload)); + yield put(gitArtifactActions.updateLocalProfileSuccess({ artifactDef })); + yield put(gitArtifactActions.fetchLocalProfileInit({ artifactDef })); } } catch (e) { if (response && response.responseMeta.error) { const { error } = response.responseMeta; yield put( - gitArtifactActions.updateLocalProfileError({ ...basePayload, error }), + gitArtifactActions.updateLocalProfileError({ artifactDef, error }), ); } else { log.error(e); diff --git a/app/client/src/git/sagas/updateProtectedBranchesSaga.ts b/app/client/src/git/sagas/updateProtectedBranchesSaga.ts index 3f7bd121270e..f24b20ee9290 100644 --- a/app/client/src/git/sagas/updateProtectedBranchesSaga.ts +++ b/app/client/src/git/sagas/updateProtectedBranchesSaga.ts @@ -14,8 +14,7 @@ import { validateResponse } from "sagas/ErrorSagas"; export default function* updateProtectedBranchesSaga( action: GitArtifactPayloadAction, ) { - const { artifactType, baseArtifactId } = action.payload; - const artifactDef = { artifactType, baseArtifactId }; + const { artifactDef } = action.payload; let response: UpdateProtectedBranchesResponse | undefined; try { @@ -25,14 +24,16 @@ export default function* updateProtectedBranchesSaga( response = yield call( updateProtectedBranchesRequest, - baseArtifactId, + artifactDef.baseArtifactId, params, ); const isValidResponse: boolean = yield validateResponse(response); if (response && isValidResponse) { - yield put(gitArtifactActions.updateProtectedBranchesSuccess(artifactDef)); - yield put(gitArtifactActions.fetchProtectedBranchesInit(artifactDef)); + yield put( + gitArtifactActions.updateProtectedBranchesSuccess({ artifactDef }), + ); + yield put(gitArtifactActions.fetchProtectedBranchesInit({ artifactDef })); } } catch (e) { if (response && response.responseMeta.error) { @@ -40,7 +41,7 @@ export default function* updateProtectedBranchesSaga( yield put( gitArtifactActions.updateProtectedBranchesError({ - ...artifactDef, + artifactDef, error, }), ); diff --git a/app/client/src/git/store/actions/checkoutBranchActions.ts b/app/client/src/git/store/actions/checkoutBranchActions.ts index c771d1887e34..31baf78e7b73 100644 --- a/app/client/src/git/store/actions/checkoutBranchActions.ts +++ b/app/client/src/git/store/actions/checkoutBranchActions.ts @@ -2,8 +2,9 @@ import { createSingleArtifactAction } from "../helpers/createSingleArtifactActio import type { GitAsyncErrorPayload } from "../types"; import type { CheckoutBranchRequestParams } from "git/requests/checkoutBranchRequest.types"; -export interface CheckoutBranchInitPayload - extends CheckoutBranchRequestParams {} +export interface CheckoutBranchInitPayload extends CheckoutBranchRequestParams { + artifactId: string; +} export const checkoutBranchInitAction = createSingleArtifactAction((state, action) => { diff --git a/app/client/src/git/store/actions/commitActions.ts b/app/client/src/git/store/actions/commitActions.ts index 9ebb8d37db60..3a85ef0e1edd 100644 --- a/app/client/src/git/store/actions/commitActions.ts +++ b/app/client/src/git/store/actions/commitActions.ts @@ -2,7 +2,9 @@ import { createSingleArtifactAction } from "../helpers/createSingleArtifactActio import type { GitAsyncErrorPayload } from "../types"; import type { CommitRequestParams } from "git/requests/commitRequest.types"; -export interface CommitInitPayload extends CommitRequestParams {} +export interface CommitInitPayload extends CommitRequestParams { + artifactId: string; +} export const commitInitAction = createSingleArtifactAction( (state) => { diff --git a/app/client/src/git/store/actions/createBranchActions.ts b/app/client/src/git/store/actions/createBranchActions.ts index be0e08445de2..116d8ebcfeef 100644 --- a/app/client/src/git/store/actions/createBranchActions.ts +++ b/app/client/src/git/store/actions/createBranchActions.ts @@ -2,7 +2,9 @@ import { createSingleArtifactAction } from "../helpers/createSingleArtifactActio import type { GitAsyncErrorPayload } from "../types"; import type { CreateBranchRequestParams } from "git/requests/createBranchRequest.types"; -export interface CreateBranchInitPayload extends CreateBranchRequestParams {} +export interface CreateBranchInitPayload extends CreateBranchRequestParams { + artifactId: string; +} export const createBranchInitAction = createSingleArtifactAction((state) => { diff --git a/app/client/src/git/store/actions/deleteBranchActions.ts b/app/client/src/git/store/actions/deleteBranchActions.ts index 09296625f0d6..a7ae769e79eb 100644 --- a/app/client/src/git/store/actions/deleteBranchActions.ts +++ b/app/client/src/git/store/actions/deleteBranchActions.ts @@ -2,7 +2,9 @@ import { createSingleArtifactAction } from "../helpers/createSingleArtifactActio import type { GitAsyncErrorPayload } from "../types"; import type { DeleteBranchRequestParams } from "../../requests/deleteBranchRequest.types"; -export interface DeleteBranchInitPayload extends DeleteBranchRequestParams {} +export interface DeleteBranchInitPayload extends DeleteBranchRequestParams { + artifactId: string; +} export const deleteBranchInitAction = createSingleArtifactAction((state) => { diff --git a/app/client/src/git/store/actions/fetchBranchesActions.ts b/app/client/src/git/store/actions/fetchBranchesActions.ts index e83ce0325e59..d3d2ef98d01b 100644 --- a/app/client/src/git/store/actions/fetchBranchesActions.ts +++ b/app/client/src/git/store/actions/fetchBranchesActions.ts @@ -5,7 +5,9 @@ import type { import type { GitAsyncErrorPayload, GitAsyncSuccessPayload } from "../types"; import { createSingleArtifactAction } from "../helpers/createSingleArtifactAction"; -export interface FetchBranchesInitPayload extends FetchBranchesRequestParams {} +export interface FetchBranchesInitPayload extends FetchBranchesRequestParams { + artifactId: string; +} export const fetchBranchesInitAction = createSingleArtifactAction((state) => { diff --git a/app/client/src/git/store/actions/fetchStatusActions.ts b/app/client/src/git/store/actions/fetchStatusActions.ts index 1121e368d012..eb348e87ac62 100644 --- a/app/client/src/git/store/actions/fetchStatusActions.ts +++ b/app/client/src/git/store/actions/fetchStatusActions.ts @@ -5,7 +5,9 @@ import type { import type { GitAsyncErrorPayload, GitAsyncSuccessPayload } from "../types"; import { createSingleArtifactAction } from "../helpers/createSingleArtifactAction"; -export interface FetchStatusInitPayload extends FetchStatusRequestParams {} +export interface FetchStatusInitPayload extends FetchStatusRequestParams { + artifactId: string; +} export const fetchStatusInitAction = createSingleArtifactAction((state) => { diff --git a/app/client/src/git/store/actions/initGitActions.ts b/app/client/src/git/store/actions/initGitActions.ts index d93cf955eeec..6d53a492474e 100644 --- a/app/client/src/git/store/actions/initGitActions.ts +++ b/app/client/src/git/store/actions/initGitActions.ts @@ -1,12 +1,8 @@ -import type { FetchMetadataResponseData } from "git/requests/fetchMetadataRequest.types"; import { createSingleArtifactAction } from "../helpers/createSingleArtifactAction"; +import type { ApplicationPayload } from "entities/Application"; export interface InitGitForEditorPayload { - artifact: { - id: string; - baseId: string; - gitApplicationMetadata?: Partial; - }; + artifact: ApplicationPayload | null; } export const initGitForEditorAction = diff --git a/app/client/src/git/store/actions/mountActions.ts b/app/client/src/git/store/actions/mountActions.ts index 07a08ee2b566..25ddd1c34674 100644 --- a/app/client/src/git/store/actions/mountActions.ts +++ b/app/client/src/git/store/actions/mountActions.ts @@ -8,7 +8,8 @@ export const mountAction = ( state: GitArtifactReduxState, action: PayloadAction, ) => { - const { artifactType, baseArtifactId } = action.payload; + const { artifactDef } = action.payload; + const { artifactType, baseArtifactId } = artifactDef; state[artifactType] ??= {}; state[artifactType][baseArtifactId] ??= gitSingleArtifactInitialState; @@ -20,7 +21,8 @@ export const unmountAction = ( state: GitArtifactReduxState, action: PayloadAction, ) => { - const { artifactType, baseArtifactId } = action.payload; + const { artifactDef } = action.payload; + const { artifactType, baseArtifactId } = artifactDef; delete state?.[artifactType]?.[baseArtifactId]; diff --git a/app/client/src/git/store/actions/uiActions.ts b/app/client/src/git/store/actions/uiActions.ts index 577d1dfa3d10..34722574fb4e 100644 --- a/app/client/src/git/store/actions/uiActions.ts +++ b/app/client/src/git/store/actions/uiActions.ts @@ -22,7 +22,8 @@ export interface OpenDisconnectModalPayload { export const openDisconnectModalAction = createSingleArtifactAction((state, action) => { - state.ui.disconnectBaseArtifactId = action.payload.baseArtifactId; + state.ui.disconnectBaseArtifactId = + action.payload.artifactDef.baseArtifactId; state.ui.disconnectArtifactName = action.payload.artifactName; return state; diff --git a/app/client/src/git/store/helpers/createSingleArtifactAction.ts b/app/client/src/git/store/helpers/createSingleArtifactAction.ts index 2e0642959be8..5d11065340ac 100644 --- a/app/client/src/git/store/helpers/createSingleArtifactAction.ts +++ b/app/client/src/git/store/helpers/createSingleArtifactAction.ts @@ -18,7 +18,7 @@ export const createSingleArtifactAction = ( state: GitArtifactReduxState, action: GitArtifactPayloadAction, ) => { - const { artifactType, baseArtifactId } = action.payload; + const { artifactType, baseArtifactId } = action.payload.artifactDef; state[artifactType] ??= {}; state[artifactType][baseArtifactId] ??= gitSingleArtifactInitialState; diff --git a/app/client/src/git/store/types.ts b/app/client/src/git/store/types.ts index ccb67a2e7a8b..635bcff795c9 100644 --- a/app/client/src/git/store/types.ts +++ b/app/client/src/git/store/types.ts @@ -1,9 +1,5 @@ import type { PayloadAction } from "@reduxjs/toolkit"; -import type { - GitArtifactType, - GitOpsTab, - GitSettingsTab, -} from "../constants/enums"; +import type { GitOpsTab, GitSettingsTab } from "../constants/enums"; import type { FetchGlobalProfileResponseData } from "../requests/fetchGlobalProfileRequest.types"; import type { FetchBranchesResponseData } from "../requests/fetchBranchesRequest.types"; import type { FetchLocalProfileResponseData } from "../requests/fetchLocalProfileRequest.types"; @@ -17,6 +13,7 @@ import type { GitArtifactAPIResponsesReduxState as GitArtifactAPIResponsesReduxStateExtended, GitArtifactUIReduxState as GitArtifactUIReduxStateExtended, } from "git/ee/store/types"; +import type { GitArtifactDef } from "./selectors/gitSingleArtifactSelectors"; export interface GitApiError extends ApiResponseError { errorType?: string; @@ -98,8 +95,7 @@ export interface GitRootState { } export interface GitArtifactBasePayload { - artifactType: keyof typeof GitArtifactType; - baseArtifactId: string; + artifactDef: GitArtifactDef; } export interface GitAsyncErrorPayload { diff --git a/app/client/src/pages/AppViewer/PrimaryCTA.tsx b/app/client/src/pages/AppViewer/PrimaryCTA.tsx index 9e2816166454..97d0363bbf5f 100644 --- a/app/client/src/pages/AppViewer/PrimaryCTA.tsx +++ b/app/client/src/pages/AppViewer/PrimaryCTA.tsx @@ -25,8 +25,8 @@ import { Icon, Tooltip } from "@appsmith/ads"; import { getApplicationNameTextColor } from "./utils"; import { ButtonVariantTypes } from "components/constants"; import { setPreviewModeInitAction } from "actions/editorActions"; -import { protectedModeSelector } from "selectors/gitSyncSelectors"; import { getCurrentApplication } from "ee/selectors/applicationSelectors"; +import { useGitProtectedMode } from "pages/Editor/gitSync/hooks/modHooks"; /** * --------------------------------------------------------------------------------------------------- @@ -67,7 +67,7 @@ function PrimaryCTA(props: Props) { const canEdit = isPermitted(userPermissions, permissionRequired); const [isForkModalOpen, setIsForkModalOpen] = useState(false); const isPreviewMode = useSelector(previewModeSelector); - const isProtectedMode = useSelector(protectedModeSelector); + const isProtectedMode = useGitProtectedMode(); const dispatch = useDispatch(); const location = useLocation(); const queryParams = new URLSearchParams(location.search); diff --git a/app/client/src/pages/Editor/AppSettingsPane/AppSettings/ImportAppSettings.tsx b/app/client/src/pages/Editor/AppSettingsPane/AppSettings/ImportAppSettings.tsx index 8da3b25343c3..b721e7c5c7af 100644 --- a/app/client/src/pages/Editor/AppSettingsPane/AppSettings/ImportAppSettings.tsx +++ b/app/client/src/pages/Editor/AppSettingsPane/AppSettings/ImportAppSettings.tsx @@ -8,8 +8,8 @@ import ImportModal from "pages/common/ImportModal"; import React from "react"; import { useSelector } from "react-redux"; import { getCurrentApplicationId } from "selectors/editorSelectors"; -import { getIsGitConnected } from "selectors/gitSyncSelectors"; import styled from "styled-components"; +import { useGitConnected } from "pages/Editor/gitSync/hooks/modHooks"; const SettingWrapper = styled.div` display: flex; @@ -21,7 +21,7 @@ const SettingWrapper = styled.div` export function ImportAppSettings() { const appId = useSelector(getCurrentApplicationId); const workspace = useSelector(getCurrentAppWorkspace); - const isGitConnected = useSelector(getIsGitConnected); + const isGitConnected = useGitConnected(); const [isModalOpen, setIsModalOpen] = React.useState(false); function handleClose() { diff --git a/app/client/src/pages/Editor/IDE/Layout/AnimatedLayout.tsx b/app/client/src/pages/Editor/IDE/Layout/AnimatedLayout.tsx index 952b3542c3f8..d58e70910a3f 100644 --- a/app/client/src/pages/Editor/IDE/Layout/AnimatedLayout.tsx +++ b/app/client/src/pages/Editor/IDE/Layout/AnimatedLayout.tsx @@ -2,7 +2,6 @@ import React from "react"; import { useGridLayoutTemplate } from "./hooks/useGridLayoutTemplate"; import EditorWrapperContainer from "pages/Editor/commons/EditorWrapperContainer"; import { AnimatedGridLayout, LayoutArea } from "components/AnimatedGridLayout"; -import { useSelector } from "react-redux"; import BottomBar from "components/BottomBar"; import Sidebar from "../Sidebar"; import LeftPane from "../LeftPane"; @@ -10,10 +9,28 @@ import MainPane from "../MainPane"; import RightPane from "../RightPane"; import { Areas } from "./constants"; import ProtectedCallout from "../ProtectedCallout"; -import { protectedModeSelector } from "selectors/gitSyncSelectors"; +import { useGitModEnabled } from "pages/Editor/gitSync/hooks/modHooks"; +import { + GitProtectedBranchCallout as GitProtectedBranchCalloutNew, + useGitProtectedMode, +} from "git"; + +function GitProtectedBranchCallout() { + const isGitModEnabled = useGitModEnabled(); + const isProtectedMode = useGitProtectedMode(); + + if (isGitModEnabled) { + return ; + } + + if (isProtectedMode) { + return ; + } + + return null; +} function AnimatedLayout() { - const isProtectedMode = useSelector(protectedModeSelector); const { areas, columns, rows } = useGridLayoutTemplate(); if (columns.length === 0) { @@ -22,7 +39,7 @@ function AnimatedLayout() { return ( <> - {isProtectedMode && } + ; + } + + if (isProtectedMode) { + return ; + } + + return null; +} const GridContainer = styled.div` display: grid; @@ -25,14 +43,13 @@ const LayoutContainer = styled.div<{ name: string }>` `; function UnanimatedLayout() { - const isProtectedMode = useSelector(protectedModeSelector); const { areas, columns } = useGridLayoutTemplate(); const isSidebarVisible = columns[0] !== "0px"; return ( <> - {isProtectedMode && } + { const [selectedSegment, setSelectedSegment] = useState( @@ -93,7 +93,7 @@ export const useSegmentNavigation = (): { export const useGetPageFocusUrl = (basePageId: string): string => { const [focusPageUrl, setFocusPageUrl] = useState(builderURL({ basePageId })); - const branch = useSelector(getCurrentGitBranch); + const branch = useGitCurrentBranch(); const editorStateFocusInfo = useSelector((appState) => getCurrentFocusInfo(appState, createEditorFocusInfoKey(basePageId, branch)), ); diff --git a/app/client/src/pages/Editor/commons/EditorWrapperContainer.tsx b/app/client/src/pages/Editor/commons/EditorWrapperContainer.tsx index 990004cbbec5..92fab1972022 100644 --- a/app/client/src/pages/Editor/commons/EditorWrapperContainer.tsx +++ b/app/client/src/pages/Editor/commons/EditorWrapperContainer.tsx @@ -3,10 +3,10 @@ import styled from "styled-components"; import classNames from "classnames"; import { useSelector } from "react-redux"; import { combinedPreviewModeSelector } from "../../../selectors/editorSelectors"; -import { protectedModeSelector } from "selectors/gitSyncSelectors"; import { IDE_HEADER_HEIGHT } from "@appsmith/ads"; import { BOTTOM_BAR_HEIGHT } from "../../../components/BottomBar/constants"; import { PROTECTED_CALLOUT_HEIGHT } from "../IDE/ProtectedCallout"; +import { useGitProtectedMode } from "../gitSync/hooks/modHooks"; interface EditorWrapperContainerProps { children: React.ReactNode; @@ -26,7 +26,7 @@ const Wrapper = styled.div<{ function EditorWrapperContainer({ children }: EditorWrapperContainerProps) { const isCombinedPreviewMode = useSelector(combinedPreviewModeSelector); - const isProtectedMode = useSelector(protectedModeSelector); + const isProtectedMode = useGitProtectedMode(); return ( { {`${this.props.currentApplicationName} | Editor | Appsmith`} - - - - - - - - - - - - - - + + + + + + + + + + + + diff --git a/app/client/src/sagas/ActionExecution/StoreActionSaga.ts b/app/client/src/sagas/ActionExecution/StoreActionSaga.ts index 4bcd909aabf0..2dffadf35f00 100644 --- a/app/client/src/sagas/ActionExecution/StoreActionSaga.ts +++ b/app/client/src/sagas/ActionExecution/StoreActionSaga.ts @@ -4,7 +4,6 @@ import localStorage from "utils/localStorage"; import { updateAppStore } from "actions/pageActions"; import AppsmithConsole from "utils/AppsmithConsole"; import { getAppStoreData } from "ee/selectors/entitiesSelector"; -import { getCurrentGitBranch } from "selectors/gitSyncSelectors"; import { getCurrentApplicationId } from "selectors/editorSelectors"; import type { AppStoreState } from "reducers/entityReducers/appReducer"; import { Severity, LOG_CATEGORY } from "entities/AppsmithConsole"; @@ -13,6 +12,8 @@ import type { TRemoveValueDescription, TStoreValueDescription, } from "workers/Evaluation/fns/storeFns"; +import { selectGitCurrentBranch } from "selectors/gitModSelectors"; +import { applicationArtifact } from "git/artifact-helpers/application"; type StoreOperation = | TStoreValueDescription @@ -21,7 +22,11 @@ type StoreOperation = export function* handleStoreOperations(triggers: StoreOperation[]) { const applicationId: string = yield select(getCurrentApplicationId); - const branch: string | undefined = yield select(getCurrentGitBranch); + const baseApplicationId: string = yield select(getCurrentApplicationId); + const branch: string | undefined = yield select( + selectGitCurrentBranch, + applicationArtifact(baseApplicationId), + ); const appStoreName = getAppStoreName(applicationId, branch); const existingLocalStore = localStorage.getItem(appStoreName) || "{}"; let parsedLocalStore = JSON.parse(existingLocalStore); diff --git a/app/client/src/sagas/DatasourcesSagas.ts b/app/client/src/sagas/DatasourcesSagas.ts index c4c50492829b..8ac3817c0674 100644 --- a/app/client/src/sagas/DatasourcesSagas.ts +++ b/app/client/src/sagas/DatasourcesSagas.ts @@ -714,6 +714,7 @@ function* redirectAuthorizationCodeSaga( const { contextId, contextType, datasourceId, pluginType } = actionPayload.payload; const isImport: string = yield select(getWorkspaceIdForImport); + // ! git mod - not sure how to handle this, there is no definition for the artifact used here const branchName: string | undefined = yield select(getCurrentGitBranch); if (pluginType === PluginType.API) { diff --git a/app/client/src/sagas/FocusRetentionSaga.ts b/app/client/src/sagas/FocusRetentionSaga.ts index 45232d9560dc..6198a7c30f4f 100644 --- a/app/client/src/sagas/FocusRetentionSaga.ts +++ b/app/client/src/sagas/FocusRetentionSaga.ts @@ -18,10 +18,12 @@ import type { AppsmithLocationState } from "utils/history"; import type { Action } from "entities/Action"; import { getAction, getPlugin } from "ee/selectors/entitiesSelector"; import type { Plugin } from "api/PluginApi"; -import { getCurrentGitBranch } from "selectors/gitSyncSelectors"; import { getIDETypeByUrl } from "ee/entities/IDE/utils"; import { getIDEFocusStrategy } from "ee/navigation/FocusStrategy"; import { IDE_TYPE } from "ee/entities/IDE/constants"; +import { getCurrentBaseApplicationId } from "selectors/editorSelectors"; +import { selectGitCurrentBranch } from "selectors/gitModSelectors"; +import { applicationArtifact } from "git/artifact-helpers/application"; export interface FocusPath { key: string; @@ -123,7 +125,11 @@ class FocusRetention { } public *handleRemoveFocusHistory(url: string) { - const branch: string | undefined = yield select(getCurrentGitBranch); + const baseApplicationId: string = yield select(getCurrentBaseApplicationId); + const branch: string | undefined = yield select( + selectGitCurrentBranch, + applicationArtifact(baseApplicationId), + ); const removeKeys: string[] = []; const focusEntityInfo = identifyEntityFromPath(url); diff --git a/app/client/src/sagas/GlobalSearchSagas.ts b/app/client/src/sagas/GlobalSearchSagas.ts index 17cf81e719b3..cb11f9a58298 100644 --- a/app/client/src/sagas/GlobalSearchSagas.ts +++ b/app/client/src/sagas/GlobalSearchSagas.ts @@ -17,22 +17,28 @@ import { import type { AppState } from "ee/reducers"; import { getCurrentApplicationId, + getCurrentBaseApplicationId, getIsEditorInitialized, } from "selectors/editorSelectors"; import type { RecentEntity } from "components/editorComponents/GlobalSearch/utils"; import log from "loglevel"; -import { getCurrentGitBranch } from "selectors/gitSyncSelectors"; import type { FocusEntity, FocusEntityInfo } from "navigation/FocusEntity"; import { convertToPageIdSelector } from "selectors/pageListSelectors"; +import { selectGitCurrentBranch } from "selectors/gitModSelectors"; +import { applicationArtifact } from "git/artifact-helpers/application"; const getRecentEntitiesKey = (applicationId: string, branch?: string) => branch ? `${applicationId}-${branch}` : applicationId; export function* updateRecentEntitySaga(entityInfo: FocusEntityInfo) { try { - const branch: string | undefined = yield select(getCurrentGitBranch); - const applicationId: string = yield select(getCurrentApplicationId); + const baseApplicationId: string = yield select(getCurrentBaseApplicationId); + + const branch: string | undefined = yield select( + selectGitCurrentBranch, + applicationArtifact(baseApplicationId), + ); const recentEntitiesRestored: boolean = yield select( (state: AppState) => state.ui.globalSearch.recentEntitiesRestored, From 64c8a845f9622c04fb2cc45442dc90106846b951 Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Wed, 18 Dec 2024 08:56:27 +0800 Subject: [PATCH 082/143] chore: moving selectors --- .../src/ce/selectors/entitiesSelector.ts | 79 ++++++++++--------- .../src/git/hooks/useArtifactSelector.ts | 6 +- app/client/src/git/index.ts | 5 +- .../selectors/gitSingleArtifactSelectors.ts | 9 ++- app/client/src/git/store/types.ts | 10 +++ .../Editor/GlobalHotKeys/GlobalHotKeys.tsx | 33 +++++--- .../src/pages/Editor/IDE/Header/index.tsx | 12 +-- .../hooks/useEditorStateLeftPaneWidth.ts | 4 +- .../IDE/Layout/hooks/useGridLayoutTemplate.ts | 4 +- .../LayoutSystemBasedPageViewer.tsx | 4 +- app/client/src/selectors/editorSelectors.tsx | 11 ++- app/client/src/selectors/gitModSelectors.ts | 20 ++++- 12 files changed, 125 insertions(+), 72 deletions(-) diff --git a/app/client/src/ce/selectors/entitiesSelector.ts b/app/client/src/ce/selectors/entitiesSelector.ts index 03262d1b6489..75e2ec7dd892 100644 --- a/app/client/src/ce/selectors/entitiesSelector.ts +++ b/app/client/src/ce/selectors/entitiesSelector.ts @@ -51,7 +51,7 @@ import { getEntityNameAndPropertyPath } from "ee/workers/Evaluation/evaluationUt import { getFormValues } from "redux-form"; import { TEMP_DATASOURCE_ID } from "constants/Datasource"; import type { Module } from "ee/constants/ModuleConstants"; -import { getAnvilSpaceDistributionStatus } from "layoutSystems/anvil/integrations/selectors"; +// import { getAnvilSpaceDistributionStatus } from "layoutSystems/anvil/integrations/selectors"; import { getCurrentWorkflowActions, getCurrentWorkflowJSActions, @@ -159,47 +159,48 @@ export const getDatasourceStructureById = ( return state.entities.datasources.structure[id]; }; +// ! git mod - the following function is not getting used /** * Selector to indicate if the widget name should be shown/drawn on canvas */ -export const getShouldShowWidgetName = createSelector( - (state: AppState) => state.ui.widgetDragResize.isResizing, - (state: AppState) => state.ui.widgetDragResize.isDragging, - (state: AppState) => state.ui.editor.isPreviewMode, - (state: AppState) => state.ui.widgetDragResize.isAutoCanvasResizing, - getAnvilSpaceDistributionStatus, - // cannot import other selectors, breaks the app - (state) => { - const gitMetaData = - state.ui.applications.currentApplication?.gitApplicationMetadata; - const isGitConnected = !!(gitMetaData && gitMetaData?.remoteUrl); - const currentBranch = gitMetaData?.branchName; - const { protectedBranches = [] } = state.ui.gitSync; - - if (!isGitConnected || !currentBranch) { - return false; - } else { - return protectedBranches.includes(currentBranch); - } - }, - ( - isResizing, - isDragging, - isPreviewMode, - isAutoCanvasResizing, - isDistributingSpace, - isProtectedMode, - ) => { - return ( - !isResizing && - !isDragging && - !isPreviewMode && - !isAutoCanvasResizing && - !isDistributingSpace && - !isProtectedMode - ); - }, -); +// export const getShouldShowWidgetName = createSelector( +// (state: AppState) => state.ui.widgetDragResize.isResizing, +// (state: AppState) => state.ui.widgetDragResize.isDragging, +// (state: AppState) => state.ui.editor.isPreviewMode, +// (state: AppState) => state.ui.widgetDragResize.isAutoCanvasResizing, +// getAnvilSpaceDistributionStatus, +// // cannot import other selectors, breaks the app +// (state) => { +// const gitMetaData = +// state.ui.applications.currentApplication?.gitApplicationMetadata; +// const isGitConnected = !!(gitMetaData && gitMetaData?.remoteUrl); +// const currentBranch = gitMetaData?.branchName; +// const { protectedBranches = [] } = state.ui.gitSync; + +// if (!isGitConnected || !currentBranch) { +// return false; +// } else { +// return protectedBranches.includes(currentBranch); +// } +// }, +// ( +// isResizing, +// isDragging, +// isPreviewMode, +// isAutoCanvasResizing, +// isDistributingSpace, +// isProtectedMode, +// ) => { +// return ( +// !isResizing && +// !isDragging && +// !isPreviewMode && +// !isAutoCanvasResizing && +// !isDistributingSpace && +// !isProtectedMode +// ); +// }, +// ); export const getDatasourceTableColumns = (datasourceId: string, tableName: string) => (state: AppState) => { diff --git a/app/client/src/git/hooks/useArtifactSelector.ts b/app/client/src/git/hooks/useArtifactSelector.ts index bf19b8b1e26d..3fbac6326e55 100644 --- a/app/client/src/git/hooks/useArtifactSelector.ts +++ b/app/client/src/git/hooks/useArtifactSelector.ts @@ -11,11 +11,11 @@ export default function useAritfactSelector< // need any type to properly infer the return type /* eslint-disable @typescript-eslint/no-explicit-any */ Fn extends (state: any, artifactDef: GitArtifactDef, ...args: any[]) => any, ->(selectorFn: Fn, ...args: Tail>>): ReturnType | null { +>(selector: Fn, ...args: Tail>>): ReturnType | null { const { artifactDef } = useGitContext(); return useSelector((state: GitRootState) => { - if (typeof selectorFn !== "function" || !artifactDef) { + if (typeof selector !== "function" || !artifactDef) { return null; } @@ -25,6 +25,6 @@ export default function useAritfactSelector< return null; } - return selectorFn(state, artifactDef, ...args); + return selector(state, artifactDef, ...args); }); } diff --git a/app/client/src/git/index.ts b/app/client/src/git/index.ts index 72ad9840c06f..d3adb531597b 100644 --- a/app/client/src/git/index.ts +++ b/app/client/src/git/index.ts @@ -17,7 +17,10 @@ export { default as useGitConnected } from "./hooks/useConnected"; export { gitReducer } from "./store"; // selectors -export { selectCurrentBranch as selectGitCurrentBranch } from "./store/selectors/gitSingleArtifactSelectors"; +export { + selectCurrentBranch as selectGitCurrentBranch, + selectProtectedMode as selectGitProtectedMode, +} from "./store/selectors/gitSingleArtifactSelectors"; // sagas export { default as gitSagas } from "./sagas"; diff --git a/app/client/src/git/store/selectors/gitSingleArtifactSelectors.ts b/app/client/src/git/store/selectors/gitSingleArtifactSelectors.ts index 367097e40a58..c651aa2c8c13 100644 --- a/app/client/src/git/store/selectors/gitSingleArtifactSelectors.ts +++ b/app/client/src/git/store/selectors/gitSingleArtifactSelectors.ts @@ -117,11 +117,14 @@ export const selectConflictErrorModalOpen = ( export const selectCurrentBranch = ( state: GitRootState, + // need the arg to preserve type + // eslint-disable-next-line @typescript-eslint/no-unused-vars artifactDef: GitArtifactDef, ) => { - const gitMetadataState = selectMetadataState(state, artifactDef).value; - - return gitMetadataState?.branchName; + return ( + state?.ui?.applications?.currentApplication?.gitApplicationMetadata + ?.branchName ?? null + ); }; export const selectFetchBranchesState = ( diff --git a/app/client/src/git/store/types.ts b/app/client/src/git/store/types.ts index 635bcff795c9..37554eacfd02 100644 --- a/app/client/src/git/store/types.ts +++ b/app/client/src/git/store/types.ts @@ -88,6 +88,16 @@ export interface GitConfigReduxState { } export interface GitRootState { + // will have to remove this later, once metadata is fixed + ui: { + applications: { + currentApplication?: { + gitApplicationMetadata?: { + branchName: string; + }; + }; + }; + }; git: { artifacts: GitArtifactReduxState; config: GitConfigReduxState; diff --git a/app/client/src/pages/Editor/GlobalHotKeys/GlobalHotKeys.tsx b/app/client/src/pages/Editor/GlobalHotKeys/GlobalHotKeys.tsx index 651f57e792c0..39fed4ed8fa1 100644 --- a/app/client/src/pages/Editor/GlobalHotKeys/GlobalHotKeys.tsx +++ b/app/client/src/pages/Editor/GlobalHotKeys/GlobalHotKeys.tsx @@ -35,7 +35,10 @@ import { createMessage, SAVE_HOTKEY_TOASTER_MESSAGE, } from "ee/constants/messages"; -import { previewModeSelector } from "selectors/editorSelectors"; +import { + getCurrentBaseApplicationId, + previewModeSelector, +} from "selectors/editorSelectors"; import { setIsGitSyncModalOpen } from "actions/gitSyncActions"; import { GitSyncModalTab } from "entities/GitSync"; import { matchBuilderPath } from "constants/routes"; @@ -45,8 +48,9 @@ import { toast } from "@appsmith/ads"; import { showDebuggerFlag } from "selectors/debuggerSelectors"; import { getIsFirstTimeUserOnboardingEnabled } from "selectors/onboardingSelectors"; import WalkthroughContext from "components/featureWalkthrough/walkthroughContext"; -import { protectedModeSelector } from "selectors/gitSyncSelectors"; import { setPreviewModeInitAction } from "actions/editorActions"; +import { selectGitProtectedMode } from "selectors/gitModSelectors"; +import { applicationArtifact } from "git/artifact-helpers/application"; interface Props { copySelectedWidget: () => void; @@ -372,15 +376,22 @@ class GlobalHotKeys extends React.Component { } } -const mapStateToProps = (state: AppState) => ({ - selectedWidget: getLastSelectedWidget(state), - selectedWidgets: getSelectedWidgets(state), - isDebuggerOpen: showDebuggerFlag(state), - appMode: getAppMode(state), - isPreviewMode: previewModeSelector(state), - isProtectedMode: protectedModeSelector(state), - isSignpostingEnabled: getIsFirstTimeUserOnboardingEnabled(state), -}); +const mapStateToProps = (state: AppState) => { + const baseApplicationId = getCurrentBaseApplicationId(state); + + return { + selectedWidget: getLastSelectedWidget(state), + selectedWidgets: getSelectedWidgets(state), + isDebuggerOpen: showDebuggerFlag(state), + appMode: getAppMode(state), + isPreviewMode: previewModeSelector(state), + isProtectedMode: selectGitProtectedMode( + state, + applicationArtifact(baseApplicationId), + ), + isSignpostingEnabled: getIsFirstTimeUserOnboardingEnabled(state), + }; +}; // TODO: Fix this the next time the file is edited // eslint-disable-next-line @typescript-eslint/no-explicit-any diff --git a/app/client/src/pages/Editor/IDE/Header/index.tsx b/app/client/src/pages/Editor/IDE/Header/index.tsx index 8a8016939705..8fb06735317c 100644 --- a/app/client/src/pages/Editor/IDE/Header/index.tsx +++ b/app/client/src/pages/Editor/IDE/Header/index.tsx @@ -61,10 +61,6 @@ import DeployLinkButtonDialog from "components/designSystems/appsmith/header/Dep import { useFeatureFlag } from "utils/hooks/useFeatureFlag"; import { FEATURE_FLAG } from "ee/entities/FeatureFlag"; import { getAppsmithConfigs } from "ee/configs"; -import { - getIsGitConnected, - protectedModeSelector, -} from "selectors/gitSyncSelectors"; import { showConnectGitModal } from "actions/gitSyncActions"; import AnalyticsUtil from "ee/utils/AnalyticsUtil"; import type { NavigationSetting } from "constants/AppConstants"; @@ -79,6 +75,10 @@ import { APPLICATIONS_URL } from "constants/routes"; import { useNavigationMenuData } from "../../EditorName/useNavigationMenuData"; import useLibraryHeaderTitle from "ee/pages/Editor/IDE/Header/useLibraryHeaderTitle"; import { AppsmithLink } from "pages/Editor/AppsmithLink"; +import { + useGitConnected, + useGitProtectedMode, +} from "pages/Editor/gitSync/hooks/modHooks"; const StyledDivider = styled(Divider)` height: 50%; @@ -129,9 +129,9 @@ const Header = () => { const currentApplication = useSelector(getCurrentApplication); const isErroredSavingName = useSelector(getIsErroredSavingAppName); const applicationList = useSelector(getApplicationList); - const isProtectedMode = useSelector(protectedModeSelector); + const isProtectedMode = useGitProtectedMode(); const isPublishing = useSelector(getIsPublishingApplication); - const isGitConnected = useSelector(getIsGitConnected); + const isGitConnected = useGitConnected(); const pageId = useSelector(getCurrentPageId) as string; const currentPage = useSelector(getPageById(pageId)); const appState = useCurrentAppState(); diff --git a/app/client/src/pages/Editor/IDE/Layout/hooks/useEditorStateLeftPaneWidth.ts b/app/client/src/pages/Editor/IDE/Layout/hooks/useEditorStateLeftPaneWidth.ts index ace70208b26d..fe8dfd7e8a6a 100644 --- a/app/client/src/pages/Editor/IDE/Layout/hooks/useEditorStateLeftPaneWidth.ts +++ b/app/client/src/pages/Editor/IDE/Layout/hooks/useEditorStateLeftPaneWidth.ts @@ -11,7 +11,7 @@ import { getPropertyPaneWidth } from "selectors/propertyPaneSelectors"; import { EditorEntityTab, EditorViewMode } from "ee/entities/IDE/constants"; import { useCurrentEditorState } from "../../hooks"; import { previewModeSelector } from "selectors/editorSelectors"; -import { protectedModeSelector } from "selectors/gitSyncSelectors"; +import { useGitProtectedMode } from "pages/Editor/gitSync/hooks/modHooks"; export const useEditorStateLeftPaneWidth = (): number => { const [windowWidth] = useWindowDimensions(); @@ -20,7 +20,7 @@ export const useEditorStateLeftPaneWidth = (): number => { const { segment } = useCurrentEditorState(); const propertyPaneWidth = useSelector(getPropertyPaneWidth); const isPreviewMode = useSelector(previewModeSelector); - const isProtectedMode = useSelector(protectedModeSelector); + const isProtectedMode = useGitProtectedMode(); useEffect( function updateWidth() { diff --git a/app/client/src/pages/Editor/IDE/Layout/hooks/useGridLayoutTemplate.ts b/app/client/src/pages/Editor/IDE/Layout/hooks/useGridLayoutTemplate.ts index 789a3837ebfa..dfeac71c26c1 100644 --- a/app/client/src/pages/Editor/IDE/Layout/hooks/useGridLayoutTemplate.ts +++ b/app/client/src/pages/Editor/IDE/Layout/hooks/useGridLayoutTemplate.ts @@ -7,7 +7,6 @@ import { useCurrentAppState } from "../../hooks/useCurrentAppState"; import { getPropertyPaneWidth } from "selectors/propertyPaneSelectors"; import { previewModeSelector } from "selectors/editorSelectors"; import { getIDEViewMode } from "selectors/ideSelectors"; -import { protectedModeSelector } from "selectors/gitSyncSelectors"; import { EditorEntityTab, EditorState, @@ -20,6 +19,7 @@ import { } from "constants/AppConstants"; import { useEditorStateLeftPaneWidth } from "./useEditorStateLeftPaneWidth"; import { type Area, Areas, SIDEBAR_WIDTH } from "../constants"; +import { useGitProtectedMode } from "pages/Editor/gitSync/hooks/modHooks"; interface ReturnValue { areas: Area[][]; @@ -43,7 +43,7 @@ function useGridLayoutTemplate(): ReturnValue { const appState = useCurrentAppState(); const isPreviewMode = useSelector(previewModeSelector); const editorMode = useSelector(getIDEViewMode); - const isProtectedMode = useSelector(protectedModeSelector); + const isProtectedMode = useGitProtectedMode(); React.useEffect( function updateIDEColumns() { diff --git a/app/client/src/pages/Editor/WidgetsEditor/components/LayoutSystemBasedPageViewer.tsx b/app/client/src/pages/Editor/WidgetsEditor/components/LayoutSystemBasedPageViewer.tsx index a430ed2fd02e..935e67cd90f0 100644 --- a/app/client/src/pages/Editor/WidgetsEditor/components/LayoutSystemBasedPageViewer.tsx +++ b/app/client/src/pages/Editor/WidgetsEditor/components/LayoutSystemBasedPageViewer.tsx @@ -8,9 +8,9 @@ import { getCurrentPageId, previewModeSelector, } from "selectors/editorSelectors"; -import { protectedModeSelector } from "selectors/gitSyncSelectors"; import { getAppSettingsPaneContext } from "selectors/appSettingsPaneSelectors"; import { useShowSnapShotBanner } from "pages/Editor/CanvasLayoutConversion/hooks/useShowSnapShotBanner"; +import { useGitProtectedMode } from "pages/Editor/gitSync/hooks/modHooks"; /** * LayoutSystemBasedPageViewer @@ -25,7 +25,7 @@ export const LayoutSystemBasedPageViewer = ({ }) => { const currentPageId = useSelector(getCurrentPageId); const isPreviewMode = useSelector(previewModeSelector); - const isProtectedMode = useSelector(protectedModeSelector); + const isProtectedMode = useGitProtectedMode(); const appSettingsPaneContext = useSelector(getAppSettingsPaneContext); const canvasWidth = useSelector(getCanvasWidth); const shouldShowSnapShotBanner = useShowSnapShotBanner( diff --git a/app/client/src/selectors/editorSelectors.tsx b/app/client/src/selectors/editorSelectors.tsx index ee3560dd5034..a37768af9b81 100644 --- a/app/client/src/selectors/editorSelectors.tsx +++ b/app/client/src/selectors/editorSelectors.tsx @@ -49,6 +49,8 @@ import { getIsAnvilLayout } from "layoutSystems/anvil/integrations/selectors"; import { getCurrentApplication } from "ee/selectors/applicationSelectors"; import type { Page } from "entities/Page"; import { objectKeys } from "@appsmith/utils"; +import { selectGitProtectedMode } from "./gitModSelectors"; +import { applicationArtifact } from "git/artifact-helpers/application"; const getIsDraggingOrResizing = (state: AppState) => state.ui.widgetDragResize.isResizing || state.ui.widgetDragResize.isDragging; @@ -993,6 +995,13 @@ export const getGsheetProjectID = (state: AppState) => export const combinedPreviewModeSelector = createSelector( previewModeSelector, - protectedModeSelector, + (state: AppState) => { + const baseApplicationId = getCurrentBaseApplicationId(state); + + return selectGitProtectedMode( + state, + applicationArtifact(baseApplicationId), + ); + }, (isPreviewMode, isProtectedMode) => isPreviewMode || isProtectedMode, ); diff --git a/app/client/src/selectors/gitModSelectors.ts b/app/client/src/selectors/gitModSelectors.ts index ad505d1ce638..05d4eafefd90 100644 --- a/app/client/src/selectors/gitModSelectors.ts +++ b/app/client/src/selectors/gitModSelectors.ts @@ -3,9 +3,12 @@ import { selectFeatureFlags } from "ee/selectors/featureFlagsSelectors"; import type { GitArtifactDef } from "git/store/selectors/gitSingleArtifactSelectors"; import { createSelector } from "reselect"; -import { getCurrentGitBranch } from "./gitSyncSelectors"; +import { getCurrentGitBranch, protectedModeSelector } from "./gitSyncSelectors"; import type { AppState } from "ee/reducers"; -import { selectGitCurrentBranch as selectGitCurrentBranchNew } from "git"; +import { + selectGitCurrentBranch as selectGitCurrentBranchNew, + selectGitProtectedMode as selectGitProtectedModeNew, +} from "git"; export const selectGitModEnabled = createSelector( selectFeatureFlags, @@ -25,3 +28,16 @@ export function selectGitCurrentBranch( return selectGitCurrentBranchNew(state, artifactDef); } } + +export function selectGitProtectedMode( + state: AppState, + artifactDef: GitArtifactDef, +) { + const isGitModEnabled = selectGitModEnabled(state); + + if (isGitModEnabled) { + return protectedModeSelector(state); + } else { + return selectGitProtectedModeNew(state, artifactDef); + } +} From e724bcbac38f86f1baca6474f2c10eb66edc6970 Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Mon, 23 Dec 2024 16:43:46 +0530 Subject: [PATCH 083/143] chore: typo error --- app/client/src/git/ce/hooks/useDefaultBranch.ts | 4 ++-- app/client/src/git/hooks/useArtifactSelector.ts | 2 +- app/client/src/git/hooks/useAutocommit.ts | 12 ++++++------ app/client/src/git/hooks/useBranches.ts | 16 ++++++++-------- app/client/src/git/hooks/useCommit.ts | 4 ++-- app/client/src/git/hooks/useConnect.ts | 12 ++++++------ app/client/src/git/hooks/useConnected.ts | 4 ++-- app/client/src/git/hooks/useDiscard.ts | 4 ++-- app/client/src/git/hooks/useDisconnect.ts | 8 ++++---- app/client/src/git/hooks/useLocalProfile.ts | 6 +++--- app/client/src/git/hooks/useMerge.ts | 6 +++--- app/client/src/git/hooks/useMetadata.ts | 4 ++-- app/client/src/git/hooks/useOps.ts | 8 ++++---- app/client/src/git/hooks/useProtectedBranches.ts | 6 +++--- app/client/src/git/hooks/useProtectedMode.ts | 4 ++-- app/client/src/git/hooks/usePull.ts | 4 ++-- app/client/src/git/hooks/useSettings.ts | 6 +++--- app/client/src/git/hooks/useStatus.ts | 4 ++-- 18 files changed, 57 insertions(+), 57 deletions(-) diff --git a/app/client/src/git/ce/hooks/useDefaultBranch.ts b/app/client/src/git/ce/hooks/useDefaultBranch.ts index 3f639e231555..c1ca6af726e5 100644 --- a/app/client/src/git/ce/hooks/useDefaultBranch.ts +++ b/app/client/src/git/ce/hooks/useDefaultBranch.ts @@ -1,8 +1,8 @@ -import useAritfactSelector from "git/hooks/useArtifactSelector"; +import useArtifactSelector from "git/hooks/useArtifactSelector"; import { selectDefaultBranch } from "git/store/selectors/gitSingleArtifactSelectors"; function useDefaultBranch() { - const defaultBranch = useAritfactSelector(selectDefaultBranch); + const defaultBranch = useArtifactSelector(selectDefaultBranch); return { defaultBranch: defaultBranch ?? null, diff --git a/app/client/src/git/hooks/useArtifactSelector.ts b/app/client/src/git/hooks/useArtifactSelector.ts index 3fbac6326e55..aeba31ed8110 100644 --- a/app/client/src/git/hooks/useArtifactSelector.ts +++ b/app/client/src/git/hooks/useArtifactSelector.ts @@ -7,7 +7,7 @@ import type { Tail } from "redux-saga/effects"; /** * This hook is used to select data from the redux store based on the artifactDef. **/ -export default function useAritfactSelector< +export default function useArtifactSelector< // need any type to properly infer the return type /* eslint-disable @typescript-eslint/no-explicit-any */ Fn extends (state: any, artifactDef: GitArtifactDef, ...args: any[]) => any, diff --git a/app/client/src/git/hooks/useAutocommit.ts b/app/client/src/git/hooks/useAutocommit.ts index bcc9de06af47..56771f7e0612 100644 --- a/app/client/src/git/hooks/useAutocommit.ts +++ b/app/client/src/git/hooks/useAutocommit.ts @@ -9,17 +9,17 @@ import { } from "git/store/selectors/gitSingleArtifactSelectors"; import { useCallback } from "react"; import { useDispatch } from "react-redux"; -import useAritfactSelector from "./useArtifactSelector"; +import useArtifactSelector from "./useArtifactSelector"; export default function useAutocommit() { const { artifactDef } = useGitContext(); const dispatch = useDispatch(); - const toggleAutocommitState = useAritfactSelector( + const toggleAutocommitState = useArtifactSelector( selectToggleAutocommitState, ); - const triggerAutocommitState = useAritfactSelector( + const triggerAutocommitState = useArtifactSelector( selectTriggerAutocommitState, ); @@ -29,7 +29,7 @@ export default function useAutocommit() { } }, [artifactDef, dispatch]); - const isAutocommitDisableModalOpen = useAritfactSelector( + const isAutocommitDisableModalOpen = useArtifactSelector( selectAutocommitDisableModalOpen, ); @@ -47,9 +47,9 @@ export default function useAutocommit() { [artifactDef, dispatch], ); - const isAutocommitEnabled = useAritfactSelector(selectAutocommitEnabled); + const isAutocommitEnabled = useArtifactSelector(selectAutocommitEnabled); - const isAutocommitPolling = useAritfactSelector(selectAutocommitPolling); + const isAutocommitPolling = useArtifactSelector(selectAutocommitPolling); return { isToggleAutocommitLoading: toggleAutocommitState?.loading ?? false, diff --git a/app/client/src/git/hooks/useBranches.ts b/app/client/src/git/hooks/useBranches.ts index 2ac945f838af..f63473cacc96 100644 --- a/app/client/src/git/hooks/useBranches.ts +++ b/app/client/src/git/hooks/useBranches.ts @@ -11,7 +11,7 @@ import { } from "git/store/selectors/gitSingleArtifactSelectors"; import { useCallback } from "react"; import { useDispatch } from "react-redux"; -import useAritfactSelector from "./useArtifactSelector"; +import useArtifactSelector from "./useArtifactSelector"; export default function useBranches() { const { artifact, artifactDef } = useGitContext(); @@ -20,7 +20,7 @@ export default function useBranches() { const dispatch = useDispatch(); // fetch branches - const branchesState = useAritfactSelector(selectFetchBranchesState); + const branchesState = useArtifactSelector(selectFetchBranchesState); const fetchBranches = useCallback(() => { if (artifactDef && artifactId) { @@ -35,7 +35,7 @@ export default function useBranches() { }, [artifactDef, artifactId, dispatch]); // create branch - const createBranchState = useAritfactSelector(selectCreateBranchState); + const createBranchState = useArtifactSelector(selectCreateBranchState); const createBranch = useCallback( (branchName: string) => { if (artifactDef && artifactId) { @@ -51,7 +51,7 @@ export default function useBranches() { [artifactDef, artifactId, dispatch], ); // delete branch - const deleteBranchState = useAritfactSelector(selectDeleteBranchState); + const deleteBranchState = useArtifactSelector(selectDeleteBranchState); const deleteBranch = useCallback( (branchName: string) => { if (artifactDef && artifactId) { @@ -67,7 +67,7 @@ export default function useBranches() { [artifactDef, artifactId, dispatch], ); // checkout branch - const checkoutBranchState = useAritfactSelector(selectCheckoutBranchState); + const checkoutBranchState = useArtifactSelector(selectCheckoutBranchState); const checkoutBranch = useCallback( (branchName: string) => { if (artifactDef && artifactId) { @@ -83,13 +83,13 @@ export default function useBranches() { [artifactDef, artifactId, dispatch], ); - const checkoutDestBranch = useAritfactSelector(selectCheckoutDestBranch); + const checkoutDestBranch = useArtifactSelector(selectCheckoutDestBranch); // derived - const currentBranch = useAritfactSelector(selectCurrentBranch); + const currentBranch = useArtifactSelector(selectCurrentBranch); // git branch list popup - const isBranchPopupOpen = useAritfactSelector(selectBranchPopupOpen); + const isBranchPopupOpen = useArtifactSelector(selectBranchPopupOpen); const toggleBranchPopup = useCallback( (open: boolean) => { diff --git a/app/client/src/git/hooks/useCommit.ts b/app/client/src/git/hooks/useCommit.ts index fce3d4ebbe52..fe65e6304f59 100644 --- a/app/client/src/git/hooks/useCommit.ts +++ b/app/client/src/git/hooks/useCommit.ts @@ -3,7 +3,7 @@ import { gitArtifactActions } from "git/store/gitArtifactSlice"; import { selectCommitState } from "git/store/selectors/gitSingleArtifactSelectors"; import { useCallback } from "react"; import { useDispatch } from "react-redux"; -import useAritfactSelector from "./useArtifactSelector"; +import useArtifactSelector from "./useArtifactSelector"; export default function useCommit() { const { artifact, artifactDef } = useGitContext(); @@ -11,7 +11,7 @@ export default function useCommit() { const dispatch = useDispatch(); - const commitState = useAritfactSelector(selectCommitState); + const commitState = useArtifactSelector(selectCommitState); const commit = useCallback( (commitMessage: string) => { diff --git a/app/client/src/git/hooks/useConnect.ts b/app/client/src/git/hooks/useConnect.ts index 0e6187cc25d0..435c7bcaf2a7 100644 --- a/app/client/src/git/hooks/useConnect.ts +++ b/app/client/src/git/hooks/useConnect.ts @@ -10,14 +10,14 @@ import { } from "git/store/selectors/gitSingleArtifactSelectors"; import { useCallback } from "react"; import { useDispatch } from "react-redux"; -import useAritfactSelector from "./useArtifactSelector"; +import useArtifactSelector from "./useArtifactSelector"; export default function useConnect() { const { artifactDef } = useGitContext(); const dispatch = useDispatch(); - const connectState = useAritfactSelector(selectConnectState); + const connectState = useArtifactSelector(selectConnectState); const connect = useCallback( (params: ConnectRequestParams) => { @@ -28,7 +28,7 @@ export default function useConnect() { [artifactDef, dispatch], ); - const gitImportState = useAritfactSelector(selectGitImportState); + const gitImportState = useArtifactSelector(selectGitImportState); const gitImport = useCallback( (params) => { @@ -37,7 +37,7 @@ export default function useConnect() { [artifactDef, dispatch], ); - const fetchSSHKeyState = useAritfactSelector(selectFetchSSHKeysState); + const fetchSSHKeyState = useArtifactSelector(selectFetchSSHKeysState); const fetchSSHKey = useCallback(() => { if (artifactDef) { @@ -51,7 +51,7 @@ export default function useConnect() { } }, [artifactDef, dispatch]); - const generateSSHKeyState = useAritfactSelector(selectGenerateSSHKeyState); + const generateSSHKeyState = useArtifactSelector(selectGenerateSSHKeyState); const generateSSHKey = useCallback( (keyType: string, isImport: boolean = false) => { @@ -74,7 +74,7 @@ export default function useConnect() { } }, [artifactDef, dispatch]); - const isConnectModalOpen = useAritfactSelector(selectConnectModalOpen); + const isConnectModalOpen = useArtifactSelector(selectConnectModalOpen); const toggleConnectModal = useCallback( (open: boolean) => { diff --git a/app/client/src/git/hooks/useConnected.ts b/app/client/src/git/hooks/useConnected.ts index 94681d6a0ed0..5b0bc2b05729 100644 --- a/app/client/src/git/hooks/useConnected.ts +++ b/app/client/src/git/hooks/useConnected.ts @@ -1,8 +1,8 @@ import { selectConnected } from "git/store/selectors/gitSingleArtifactSelectors"; -import useAritfactSelector from "./useArtifactSelector"; +import useArtifactSelector from "./useArtifactSelector"; export default function useConnected() { - const isConnected = useAritfactSelector(selectConnected); + const isConnected = useArtifactSelector(selectConnected); return isConnected ?? false; } diff --git a/app/client/src/git/hooks/useDiscard.ts b/app/client/src/git/hooks/useDiscard.ts index 76291a637ae1..9e2a2c72cd5f 100644 --- a/app/client/src/git/hooks/useDiscard.ts +++ b/app/client/src/git/hooks/useDiscard.ts @@ -3,13 +3,13 @@ import { gitArtifactActions } from "git/store/gitArtifactSlice"; import { selectDiscardState } from "git/store/selectors/gitSingleArtifactSelectors"; import { useCallback } from "react"; import { useDispatch } from "react-redux"; -import useAritfactSelector from "./useArtifactSelector"; +import useArtifactSelector from "./useArtifactSelector"; export default function useDiscard() { const { artifactDef } = useGitContext(); const dispatch = useDispatch(); - const discardState = useAritfactSelector(selectDiscardState); + const discardState = useArtifactSelector(selectDiscardState); const discard = useCallback(() => { if (artifactDef) { diff --git a/app/client/src/git/hooks/useDisconnect.ts b/app/client/src/git/hooks/useDisconnect.ts index f9734d609ba7..ea52fa4f27f1 100644 --- a/app/client/src/git/hooks/useDisconnect.ts +++ b/app/client/src/git/hooks/useDisconnect.ts @@ -7,7 +7,7 @@ import { } from "git/store/selectors/gitSingleArtifactSelectors"; import { useCallback } from "react"; import { useDispatch } from "react-redux"; -import useAritfactSelector from "./useArtifactSelector"; +import useArtifactSelector from "./useArtifactSelector"; export default function useDisconnect() { const { artifact, artifactDef } = useGitContext(); @@ -15,7 +15,7 @@ export default function useDisconnect() { const dispatch = useDispatch(); - const disconnectState = useAritfactSelector(selectDisconnectState); + const disconnectState = useArtifactSelector(selectDisconnectState); const disconnect = useCallback(() => { if (artifactDef) { @@ -23,11 +23,11 @@ export default function useDisconnect() { } }, [artifactDef, dispatch]); - const disconnectBaseArtifactId = useAritfactSelector( + const disconnectBaseArtifactId = useArtifactSelector( selectDisconnectBaseArtifactId, ); - const disconnectArtifactName = useAritfactSelector( + const disconnectArtifactName = useArtifactSelector( selectDisconnectArtifactName, ); diff --git a/app/client/src/git/hooks/useLocalProfile.ts b/app/client/src/git/hooks/useLocalProfile.ts index 0bce80a705ad..495da1392c35 100644 --- a/app/client/src/git/hooks/useLocalProfile.ts +++ b/app/client/src/git/hooks/useLocalProfile.ts @@ -7,14 +7,14 @@ import { } from "git/store/selectors/gitSingleArtifactSelectors"; import { useCallback } from "react"; import { useDispatch } from "react-redux"; -import useAritfactSelector from "./useArtifactSelector"; +import useArtifactSelector from "./useArtifactSelector"; export default function useLocalProfile() { const { artifactDef } = useGitContext(); const dispatch = useDispatch(); - const fetchLocalProfileState = useAritfactSelector( + const fetchLocalProfileState = useArtifactSelector( selectFetchLocalProfileState, ); @@ -24,7 +24,7 @@ export default function useLocalProfile() { } }, [artifactDef, dispatch]); - const updateLocalProfileState = useAritfactSelector( + const updateLocalProfileState = useArtifactSelector( selectUpdateLocalProfileState, ); diff --git a/app/client/src/git/hooks/useMerge.ts b/app/client/src/git/hooks/useMerge.ts index 324e532a5daf..3822951cdac2 100644 --- a/app/client/src/git/hooks/useMerge.ts +++ b/app/client/src/git/hooks/useMerge.ts @@ -6,7 +6,7 @@ import { } from "git/store/selectors/gitSingleArtifactSelectors"; import { useCallback } from "react"; import { useDispatch } from "react-redux"; -import useAritfactSelector from "./useArtifactSelector"; +import useArtifactSelector from "./useArtifactSelector"; export default function useMerge() { const { artifact, artifactDef } = useGitContext(); @@ -14,7 +14,7 @@ export default function useMerge() { const dispatch = useDispatch(); // merge - const mergeState = useAritfactSelector(selectMergeState); + const mergeState = useArtifactSelector(selectMergeState); const merge = useCallback(() => { if (artifactDef) { @@ -23,7 +23,7 @@ export default function useMerge() { }, [artifactDef, dispatch]); // merge status - const mergeStatusState = useAritfactSelector(selectMergeStatusState); + const mergeStatusState = useArtifactSelector(selectMergeStatusState); const fetchMergeStatus = useCallback( (sourceBranch: string, destinationBranch: string) => { diff --git a/app/client/src/git/hooks/useMetadata.ts b/app/client/src/git/hooks/useMetadata.ts index 121c2f93768d..61887932a3d6 100644 --- a/app/client/src/git/hooks/useMetadata.ts +++ b/app/client/src/git/hooks/useMetadata.ts @@ -1,8 +1,8 @@ import { selectMetadataState } from "git/store/selectors/gitSingleArtifactSelectors"; -import useAritfactSelector from "./useArtifactSelector"; +import useArtifactSelector from "./useArtifactSelector"; export default function useMetadata() { - const metadataState = useAritfactSelector(selectMetadataState); + const metadataState = useArtifactSelector(selectMetadataState); return { metadata: metadataState?.value ?? null, diff --git a/app/client/src/git/hooks/useOps.ts b/app/client/src/git/hooks/useOps.ts index 527a4e4ecf9f..e25c0ba00ba9 100644 --- a/app/client/src/git/hooks/useOps.ts +++ b/app/client/src/git/hooks/useOps.ts @@ -8,7 +8,7 @@ import { } from "git/store/selectors/gitSingleArtifactSelectors"; import { useCallback } from "react"; import { useDispatch } from "react-redux"; -import useAritfactSelector from "./useArtifactSelector"; +import useArtifactSelector from "./useArtifactSelector"; export default function useOps() { const { artifactDef } = useGitContext(); @@ -16,9 +16,9 @@ export default function useOps() { const dispatch = useDispatch(); // ops modal - const opsModalOpen = useAritfactSelector(selectOpsModalOpen); + const opsModalOpen = useArtifactSelector(selectOpsModalOpen); - const opsModalTab = useAritfactSelector(selectOpsModalTab); + const opsModalTab = useArtifactSelector(selectOpsModalTab); const toggleOpsModal = useCallback( (open: boolean, tab: keyof typeof GitOpsTab = GitOpsTab.Deploy) => { @@ -30,7 +30,7 @@ export default function useOps() { ); // conflict error modal - const conflictErrorModalOpen = useAritfactSelector( + const conflictErrorModalOpen = useArtifactSelector( selectConflictErrorModalOpen, ); diff --git a/app/client/src/git/hooks/useProtectedBranches.ts b/app/client/src/git/hooks/useProtectedBranches.ts index 799303cb4bca..57461f8a02ae 100644 --- a/app/client/src/git/hooks/useProtectedBranches.ts +++ b/app/client/src/git/hooks/useProtectedBranches.ts @@ -6,14 +6,14 @@ import { } from "git/store/selectors/gitSingleArtifactSelectors"; import { useCallback } from "react"; import { useDispatch } from "react-redux"; -import useAritfactSelector from "./useArtifactSelector"; +import useArtifactSelector from "./useArtifactSelector"; function useProtectedBranches() { const { artifactDef } = useGitContext(); const dispatch = useDispatch(); - const fetchProtectedBranchesState = useAritfactSelector( + const fetchProtectedBranchesState = useArtifactSelector( selectFetchProtectedBranchesState, ); @@ -23,7 +23,7 @@ function useProtectedBranches() { } }, [dispatch, artifactDef]); - const updateProtectedBranchesState = useAritfactSelector( + const updateProtectedBranchesState = useArtifactSelector( selectUpdateProtectedBranchesState, ); diff --git a/app/client/src/git/hooks/useProtectedMode.ts b/app/client/src/git/hooks/useProtectedMode.ts index b4475f5fc105..387bd33d9230 100644 --- a/app/client/src/git/hooks/useProtectedMode.ts +++ b/app/client/src/git/hooks/useProtectedMode.ts @@ -1,8 +1,8 @@ import { selectProtectedMode } from "git/store/selectors/gitSingleArtifactSelectors"; -import useAritfactSelector from "./useArtifactSelector"; +import useArtifactSelector from "./useArtifactSelector"; export default function useProtectedMode() { - const isProtectedMode = useAritfactSelector(selectProtectedMode); + const isProtectedMode = useArtifactSelector(selectProtectedMode); return isProtectedMode ?? false; } diff --git a/app/client/src/git/hooks/usePull.ts b/app/client/src/git/hooks/usePull.ts index c7b67031d6e1..1cb1ceb46dea 100644 --- a/app/client/src/git/hooks/usePull.ts +++ b/app/client/src/git/hooks/usePull.ts @@ -3,14 +3,14 @@ import { gitArtifactActions } from "git/store/gitArtifactSlice"; import { selectPullState } from "git/store/selectors/gitSingleArtifactSelectors"; import { useCallback } from "react"; import { useDispatch } from "react-redux"; -import useAritfactSelector from "./useArtifactSelector"; +import useArtifactSelector from "./useArtifactSelector"; export default function usePull() { const { artifact, artifactDef } = useGitContext(); const artifactId = artifact?.id; const dispatch = useDispatch(); - const pullState = useAritfactSelector(selectPullState); + const pullState = useArtifactSelector(selectPullState); const pull = useCallback(() => { if (artifactDef) { diff --git a/app/client/src/git/hooks/useSettings.ts b/app/client/src/git/hooks/useSettings.ts index 7605ad6cfaa1..1a70deada2be 100644 --- a/app/client/src/git/hooks/useSettings.ts +++ b/app/client/src/git/hooks/useSettings.ts @@ -7,16 +7,16 @@ import { } from "git/store/selectors/gitSingleArtifactSelectors"; import { useCallback } from "react"; import { useDispatch } from "react-redux"; -import useAritfactSelector from "./useArtifactSelector"; +import useArtifactSelector from "./useArtifactSelector"; export default function useSettings() { const { artifactDef } = useGitContext(); const dispatch = useDispatch(); - const settingsModalOpen = useAritfactSelector(selectSettingsModalOpen); + const settingsModalOpen = useArtifactSelector(selectSettingsModalOpen); - const settingsModalTab = useAritfactSelector(selectSettingsModalTab); + const settingsModalTab = useArtifactSelector(selectSettingsModalTab); const toggleSettingsModal = useCallback( ( diff --git a/app/client/src/git/hooks/useStatus.ts b/app/client/src/git/hooks/useStatus.ts index beec34e01ca1..dd53dc8dd826 100644 --- a/app/client/src/git/hooks/useStatus.ts +++ b/app/client/src/git/hooks/useStatus.ts @@ -3,14 +3,14 @@ import { gitArtifactActions } from "git/store/gitArtifactSlice"; import { selectStatusState } from "git/store/selectors/gitSingleArtifactSelectors"; import { useCallback } from "react"; import { useDispatch } from "react-redux"; -import useAritfactSelector from "./useArtifactSelector"; +import useArtifactSelector from "./useArtifactSelector"; export default function useStatus() { const { artifact, artifactDef } = useGitContext(); const artifactId = artifact?.id; const dispatch = useDispatch(); - const statusState = useAritfactSelector(selectStatusState); + const statusState = useArtifactSelector(selectStatusState); const fetchStatus = useCallback(() => { if (artifactDef && artifactId) { From 469a675f1522c28888dc272af4f5b967e1741db6 Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Mon, 23 Dec 2024 16:46:43 +0530 Subject: [PATCH 084/143] chore: fix action dispatch call --- app/client/src/git/hooks/useDisconnect.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/client/src/git/hooks/useDisconnect.ts b/app/client/src/git/hooks/useDisconnect.ts index ea52fa4f27f1..9c1bce54440e 100644 --- a/app/client/src/git/hooks/useDisconnect.ts +++ b/app/client/src/git/hooks/useDisconnect.ts @@ -19,7 +19,11 @@ export default function useDisconnect() { const disconnect = useCallback(() => { if (artifactDef) { - dispatch(gitArtifactActions.disconnectInit); + dispatch( + gitArtifactActions.disconnectInit({ + artifactDef, + }), + ); } }, [artifactDef, dispatch]); From 747880490eef405ecbe2bda0b1bcfc6354dc8207 Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Mon, 23 Dec 2024 18:15:32 +0530 Subject: [PATCH 085/143] chore: renaming files and types more consistently --- app/client/src/ce/reducers/index.tsx | 9 +- .../application/applicationArtifact.ts | 2 +- .../src/git/ce/hooks/useDefaultBranch.ts | 2 +- .../components/GitContextProvider/index.tsx | 2 +- .../src/git/hooks/useArtifactSelector.ts | 3 +- app/client/src/git/hooks/useAutocommit.ts | 2 +- app/client/src/git/hooks/useBranches.ts | 2 +- app/client/src/git/hooks/useCommit.ts | 2 +- app/client/src/git/hooks/useConnect.ts | 2 +- app/client/src/git/hooks/useConnected.ts | 2 +- app/client/src/git/hooks/useDiscard.ts | 2 +- app/client/src/git/hooks/useDisconnect.ts | 2 +- app/client/src/git/hooks/useGlobalProfile.ts | 2 +- app/client/src/git/hooks/useLocalProfile.ts | 2 +- app/client/src/git/hooks/useMerge.ts | 2 +- app/client/src/git/hooks/useMetadata.ts | 2 +- app/client/src/git/hooks/useOps.ts | 2 +- .../src/git/hooks/useProtectedBranches.ts | 2 +- app/client/src/git/hooks/useProtectedMode.ts | 2 +- app/client/src/git/hooks/usePull.ts | 2 +- app/client/src/git/hooks/useSettings.ts | 2 +- app/client/src/git/hooks/useStatus.ts | 2 +- app/client/src/git/index.ts | 9 +- app/client/src/git/sagas/pullSaga.ts | 2 +- .../src/git/sagas/triggerAutocommitSaga.ts | 7 +- .../store/actions/checkoutBranchActions.ts | 20 ++- .../src/git/store/actions/commitActions.ts | 15 +- .../src/git/store/actions/connectActions.ts | 13 +- .../git/store/actions/createBranchActions.ts | 8 +- .../git/store/actions/deleteBranchActions.ts | 8 +- .../src/git/store/actions/discardActions.ts | 10 +- .../git/store/actions/disconnectActions.ts | 8 +- .../actions/fetchAutocommitProgressActions.ts | 8 +- .../git/store/actions/fetchBranchesActions.ts | 8 +- .../store/actions/fetchLocalProfileActions.ts | 18 +-- .../store/actions/fetchMergeStatusActions.ts | 10 +- .../git/store/actions/fetchMetadataActions.ts | 8 +- .../actions/fetchProtectedBranchesActions.ts | 8 +- .../git/store/actions/fetchSSHKeyActions.ts | 10 +- .../git/store/actions/fetchStatusActions.ts | 8 +- .../store/actions/generateSSHKeyActions.ts | 10 +- .../src/git/store/actions/gitImportActions.ts | 13 +- .../src/git/store/actions/initGitActions.ts | 4 +- .../src/git/store/actions/mergeActions.ts | 8 +- .../src/git/store/actions/mountActions.ts | 13 +- .../src/git/store/actions/pullActions.ts | 18 +-- .../actions/repoLimitErrorModalActions.ts | 14 +- .../store/actions/toggleAutocommitActions.ts | 26 ++-- .../store/actions/triggerAutocommitActions.ts | 20 ++- app/client/src/git/store/actions/uiActions.ts | 60 ++++---- .../actions/updateLocalProfileActions.ts | 16 +- .../actions/updateProtectedBranchesActions.ts | 8 +- app/client/src/git/store/gitArtifactSlice.ts | 4 +- .../git/store/helpers/createArtifactAction.ts | 35 +++++ .../helpers/createSingleArtifactAction.ts | 35 ----- .../helpers/gitSingleArtifactInitialState.ts | 138 ------------------ .../src/git/store/helpers/initialState.ts | 137 +++++++++++++++++ app/client/src/git/store/index.ts | 2 +- ...ctSelectors.ts => gitArtifactSelectors.ts} | 8 +- ...nfigSelectors.ts => gitGlobalSelectors.ts} | 2 +- app/client/src/git/store/types.ts | 37 +++-- app/client/src/selectors/gitModSelectors.ts | 2 +- 62 files changed, 415 insertions(+), 425 deletions(-) create mode 100644 app/client/src/git/store/helpers/createArtifactAction.ts delete mode 100644 app/client/src/git/store/helpers/createSingleArtifactAction.ts delete mode 100644 app/client/src/git/store/helpers/gitSingleArtifactInitialState.ts create mode 100644 app/client/src/git/store/helpers/initialState.ts rename app/client/src/git/store/selectors/{gitSingleArtifactSelectors.ts => gitArtifactSelectors.ts} (97%) rename app/client/src/git/store/selectors/{gitConfigSelectors.ts => gitGlobalSelectors.ts} (92%) diff --git a/app/client/src/ce/reducers/index.tsx b/app/client/src/ce/reducers/index.tsx index a459076a63c2..b48106fcda83 100644 --- a/app/client/src/ce/reducers/index.tsx +++ b/app/client/src/ce/reducers/index.tsx @@ -78,10 +78,7 @@ import type { SelectedWorkspaceReduxState } from "ee/reducers/uiReducers/selecte import type { ConsolidatedPageLoadState } from "reducers/uiReducers/consolidatedPageLoadReducer"; import type { BuildingBlocksReduxState } from "reducers/uiReducers/buildingBlockReducer"; import { gitReducer } from "git"; -import type { - GitArtifactReduxState, - GitConfigReduxState, -} from "git/store/types"; +import type { GitArtifactRootReduxState, GitConfigReduxState } from "git"; export const reducerObject = { entities: entityReducer, @@ -185,7 +182,7 @@ export interface AppState { // eslint-disable-next-line @typescript-eslint/no-explicit-any tenant: TenantReduxState; git: { - config: GitConfigReduxState; - artifacts: GitArtifactReduxState; + global: GitConfigReduxState; + artifacts: GitArtifactRootReduxState; }; } diff --git a/app/client/src/git/artifact-helpers/application/applicationArtifact.ts b/app/client/src/git/artifact-helpers/application/applicationArtifact.ts index b3c249cf22e6..7337db575ac6 100644 --- a/app/client/src/git/artifact-helpers/application/applicationArtifact.ts +++ b/app/client/src/git/artifact-helpers/application/applicationArtifact.ts @@ -1,5 +1,5 @@ import { GitArtifactType } from "git/constants/enums"; -import type { GitArtifactDef } from "git/store/selectors/gitSingleArtifactSelectors"; +import type { GitArtifactDef } from "git/store/types"; export default function applicationArtifact( baseApplicationId: string, diff --git a/app/client/src/git/ce/hooks/useDefaultBranch.ts b/app/client/src/git/ce/hooks/useDefaultBranch.ts index c1ca6af726e5..53a0f4a1fb01 100644 --- a/app/client/src/git/ce/hooks/useDefaultBranch.ts +++ b/app/client/src/git/ce/hooks/useDefaultBranch.ts @@ -1,5 +1,5 @@ import useArtifactSelector from "git/hooks/useArtifactSelector"; -import { selectDefaultBranch } from "git/store/selectors/gitSingleArtifactSelectors"; +import { selectDefaultBranch } from "git/store/selectors/gitArtifactSelectors"; function useDefaultBranch() { const defaultBranch = useArtifactSelector(selectDefaultBranch); diff --git a/app/client/src/git/components/GitContextProvider/index.tsx b/app/client/src/git/components/GitContextProvider/index.tsx index 68e3c0bab450..388bbb95d9bb 100644 --- a/app/client/src/git/components/GitContextProvider/index.tsx +++ b/app/client/src/git/components/GitContextProvider/index.tsx @@ -4,7 +4,7 @@ import type { ApplicationPayload } from "entities/Application"; import type { FetchStatusResponseData } from "git/requests/fetchStatusRequest.types"; import type { StatusTreeStruct } from "../StatusChanges/StatusTree"; import { useDispatch } from "react-redux"; -import type { GitArtifactDef } from "git/store/selectors/gitSingleArtifactSelectors"; +import type { GitArtifactDef } from "git/store/types"; export interface GitContextValue { artifactDef: GitArtifactDef | null; diff --git a/app/client/src/git/hooks/useArtifactSelector.ts b/app/client/src/git/hooks/useArtifactSelector.ts index aeba31ed8110..dba2a0808bf3 100644 --- a/app/client/src/git/hooks/useArtifactSelector.ts +++ b/app/client/src/git/hooks/useArtifactSelector.ts @@ -1,6 +1,5 @@ import { useGitContext } from "git/components/GitContextProvider"; -import type { GitArtifactDef } from "git/store/selectors/gitSingleArtifactSelectors"; -import type { GitRootState } from "git/store/types"; +import type { GitArtifactDef, GitRootState } from "git/store/types"; import { useSelector } from "react-redux"; import type { Tail } from "redux-saga/effects"; diff --git a/app/client/src/git/hooks/useAutocommit.ts b/app/client/src/git/hooks/useAutocommit.ts index 56771f7e0612..91ad0e8aaae5 100644 --- a/app/client/src/git/hooks/useAutocommit.ts +++ b/app/client/src/git/hooks/useAutocommit.ts @@ -6,7 +6,7 @@ import { selectAutocommitPolling, selectToggleAutocommitState, selectTriggerAutocommitState, -} from "git/store/selectors/gitSingleArtifactSelectors"; +} from "git/store/selectors/gitArtifactSelectors"; import { useCallback } from "react"; import { useDispatch } from "react-redux"; import useArtifactSelector from "./useArtifactSelector"; diff --git a/app/client/src/git/hooks/useBranches.ts b/app/client/src/git/hooks/useBranches.ts index f63473cacc96..fe85a318b8d4 100644 --- a/app/client/src/git/hooks/useBranches.ts +++ b/app/client/src/git/hooks/useBranches.ts @@ -8,7 +8,7 @@ import { selectCreateBranchState, selectDeleteBranchState, selectCurrentBranch, -} from "git/store/selectors/gitSingleArtifactSelectors"; +} from "git/store/selectors/gitArtifactSelectors"; import { useCallback } from "react"; import { useDispatch } from "react-redux"; import useArtifactSelector from "./useArtifactSelector"; diff --git a/app/client/src/git/hooks/useCommit.ts b/app/client/src/git/hooks/useCommit.ts index fe65e6304f59..6a468046a84b 100644 --- a/app/client/src/git/hooks/useCommit.ts +++ b/app/client/src/git/hooks/useCommit.ts @@ -1,6 +1,6 @@ import { useGitContext } from "git/components/GitContextProvider"; import { gitArtifactActions } from "git/store/gitArtifactSlice"; -import { selectCommitState } from "git/store/selectors/gitSingleArtifactSelectors"; +import { selectCommitState } from "git/store/selectors/gitArtifactSelectors"; import { useCallback } from "react"; import { useDispatch } from "react-redux"; import useArtifactSelector from "./useArtifactSelector"; diff --git a/app/client/src/git/hooks/useConnect.ts b/app/client/src/git/hooks/useConnect.ts index 435c7bcaf2a7..6da96edf9d31 100644 --- a/app/client/src/git/hooks/useConnect.ts +++ b/app/client/src/git/hooks/useConnect.ts @@ -7,7 +7,7 @@ import { selectFetchSSHKeysState, selectGenerateSSHKeyState, selectGitImportState, -} from "git/store/selectors/gitSingleArtifactSelectors"; +} from "git/store/selectors/gitArtifactSelectors"; import { useCallback } from "react"; import { useDispatch } from "react-redux"; import useArtifactSelector from "./useArtifactSelector"; diff --git a/app/client/src/git/hooks/useConnected.ts b/app/client/src/git/hooks/useConnected.ts index 5b0bc2b05729..39cfa55ca245 100644 --- a/app/client/src/git/hooks/useConnected.ts +++ b/app/client/src/git/hooks/useConnected.ts @@ -1,4 +1,4 @@ -import { selectConnected } from "git/store/selectors/gitSingleArtifactSelectors"; +import { selectConnected } from "git/store/selectors/gitArtifactSelectors"; import useArtifactSelector from "./useArtifactSelector"; export default function useConnected() { diff --git a/app/client/src/git/hooks/useDiscard.ts b/app/client/src/git/hooks/useDiscard.ts index 9e2a2c72cd5f..19818cb7f8fa 100644 --- a/app/client/src/git/hooks/useDiscard.ts +++ b/app/client/src/git/hooks/useDiscard.ts @@ -1,6 +1,6 @@ import { useGitContext } from "git/components/GitContextProvider"; import { gitArtifactActions } from "git/store/gitArtifactSlice"; -import { selectDiscardState } from "git/store/selectors/gitSingleArtifactSelectors"; +import { selectDiscardState } from "git/store/selectors/gitArtifactSelectors"; import { useCallback } from "react"; import { useDispatch } from "react-redux"; import useArtifactSelector from "./useArtifactSelector"; diff --git a/app/client/src/git/hooks/useDisconnect.ts b/app/client/src/git/hooks/useDisconnect.ts index 9c1bce54440e..42fd878319fd 100644 --- a/app/client/src/git/hooks/useDisconnect.ts +++ b/app/client/src/git/hooks/useDisconnect.ts @@ -4,7 +4,7 @@ import { selectDisconnectArtifactName, selectDisconnectBaseArtifactId, selectDisconnectState, -} from "git/store/selectors/gitSingleArtifactSelectors"; +} from "git/store/selectors/gitArtifactSelectors"; import { useCallback } from "react"; import { useDispatch } from "react-redux"; import useArtifactSelector from "./useArtifactSelector"; diff --git a/app/client/src/git/hooks/useGlobalProfile.ts b/app/client/src/git/hooks/useGlobalProfile.ts index f319f9c1f5db..d5f8f1992114 100644 --- a/app/client/src/git/hooks/useGlobalProfile.ts +++ b/app/client/src/git/hooks/useGlobalProfile.ts @@ -3,7 +3,7 @@ import { gitConfigActions } from "git/store/gitConfigSlice"; import { selectFetchGlobalProfileState, selectUpdateGlobalProfileState, -} from "git/store/selectors/gitConfigSelectors"; +} from "git/store/selectors/gitGlobalSelectors"; import type { GitRootState } from "git/store/types"; import { useCallback } from "react"; diff --git a/app/client/src/git/hooks/useLocalProfile.ts b/app/client/src/git/hooks/useLocalProfile.ts index 495da1392c35..8d77899a7602 100644 --- a/app/client/src/git/hooks/useLocalProfile.ts +++ b/app/client/src/git/hooks/useLocalProfile.ts @@ -4,7 +4,7 @@ import { gitArtifactActions } from "git/store/gitArtifactSlice"; import { selectFetchLocalProfileState, selectUpdateLocalProfileState, -} from "git/store/selectors/gitSingleArtifactSelectors"; +} from "git/store/selectors/gitArtifactSelectors"; import { useCallback } from "react"; import { useDispatch } from "react-redux"; import useArtifactSelector from "./useArtifactSelector"; diff --git a/app/client/src/git/hooks/useMerge.ts b/app/client/src/git/hooks/useMerge.ts index 3822951cdac2..8fa79b16049f 100644 --- a/app/client/src/git/hooks/useMerge.ts +++ b/app/client/src/git/hooks/useMerge.ts @@ -3,7 +3,7 @@ import { gitArtifactActions } from "git/store/gitArtifactSlice"; import { selectMergeState, selectMergeStatusState, -} from "git/store/selectors/gitSingleArtifactSelectors"; +} from "git/store/selectors/gitArtifactSelectors"; import { useCallback } from "react"; import { useDispatch } from "react-redux"; import useArtifactSelector from "./useArtifactSelector"; diff --git a/app/client/src/git/hooks/useMetadata.ts b/app/client/src/git/hooks/useMetadata.ts index 61887932a3d6..2ccd15d7ec89 100644 --- a/app/client/src/git/hooks/useMetadata.ts +++ b/app/client/src/git/hooks/useMetadata.ts @@ -1,4 +1,4 @@ -import { selectMetadataState } from "git/store/selectors/gitSingleArtifactSelectors"; +import { selectMetadataState } from "git/store/selectors/gitArtifactSelectors"; import useArtifactSelector from "./useArtifactSelector"; export default function useMetadata() { diff --git a/app/client/src/git/hooks/useOps.ts b/app/client/src/git/hooks/useOps.ts index e25c0ba00ba9..9b15bd035d85 100644 --- a/app/client/src/git/hooks/useOps.ts +++ b/app/client/src/git/hooks/useOps.ts @@ -5,7 +5,7 @@ import { selectConflictErrorModalOpen, selectOpsModalOpen, selectOpsModalTab, -} from "git/store/selectors/gitSingleArtifactSelectors"; +} from "git/store/selectors/gitArtifactSelectors"; import { useCallback } from "react"; import { useDispatch } from "react-redux"; import useArtifactSelector from "./useArtifactSelector"; diff --git a/app/client/src/git/hooks/useProtectedBranches.ts b/app/client/src/git/hooks/useProtectedBranches.ts index 57461f8a02ae..6ec68ee23b74 100644 --- a/app/client/src/git/hooks/useProtectedBranches.ts +++ b/app/client/src/git/hooks/useProtectedBranches.ts @@ -3,7 +3,7 @@ import { gitArtifactActions } from "git/store/gitArtifactSlice"; import { selectFetchProtectedBranchesState, selectUpdateProtectedBranchesState, -} from "git/store/selectors/gitSingleArtifactSelectors"; +} from "git/store/selectors/gitArtifactSelectors"; import { useCallback } from "react"; import { useDispatch } from "react-redux"; import useArtifactSelector from "./useArtifactSelector"; diff --git a/app/client/src/git/hooks/useProtectedMode.ts b/app/client/src/git/hooks/useProtectedMode.ts index 387bd33d9230..e8e86e9f04a2 100644 --- a/app/client/src/git/hooks/useProtectedMode.ts +++ b/app/client/src/git/hooks/useProtectedMode.ts @@ -1,4 +1,4 @@ -import { selectProtectedMode } from "git/store/selectors/gitSingleArtifactSelectors"; +import { selectProtectedMode } from "git/store/selectors/gitArtifactSelectors"; import useArtifactSelector from "./useArtifactSelector"; export default function useProtectedMode() { diff --git a/app/client/src/git/hooks/usePull.ts b/app/client/src/git/hooks/usePull.ts index 1cb1ceb46dea..19900c98f38e 100644 --- a/app/client/src/git/hooks/usePull.ts +++ b/app/client/src/git/hooks/usePull.ts @@ -1,6 +1,6 @@ import { useGitContext } from "git/components/GitContextProvider"; import { gitArtifactActions } from "git/store/gitArtifactSlice"; -import { selectPullState } from "git/store/selectors/gitSingleArtifactSelectors"; +import { selectPullState } from "git/store/selectors/gitArtifactSelectors"; import { useCallback } from "react"; import { useDispatch } from "react-redux"; import useArtifactSelector from "./useArtifactSelector"; diff --git a/app/client/src/git/hooks/useSettings.ts b/app/client/src/git/hooks/useSettings.ts index 1a70deada2be..0a8b48aa368c 100644 --- a/app/client/src/git/hooks/useSettings.ts +++ b/app/client/src/git/hooks/useSettings.ts @@ -4,7 +4,7 @@ import { gitArtifactActions } from "git/store/gitArtifactSlice"; import { selectSettingsModalOpen, selectSettingsModalTab, -} from "git/store/selectors/gitSingleArtifactSelectors"; +} from "git/store/selectors/gitArtifactSelectors"; import { useCallback } from "react"; import { useDispatch } from "react-redux"; import useArtifactSelector from "./useArtifactSelector"; diff --git a/app/client/src/git/hooks/useStatus.ts b/app/client/src/git/hooks/useStatus.ts index dd53dc8dd826..37a5584911aa 100644 --- a/app/client/src/git/hooks/useStatus.ts +++ b/app/client/src/git/hooks/useStatus.ts @@ -1,6 +1,6 @@ import { useGitContext } from "git/components/GitContextProvider"; import { gitArtifactActions } from "git/store/gitArtifactSlice"; -import { selectStatusState } from "git/store/selectors/gitSingleArtifactSelectors"; +import { selectStatusState } from "git/store/selectors/gitArtifactSelectors"; import { useCallback } from "react"; import { useDispatch } from "react-redux"; import useArtifactSelector from "./useArtifactSelector"; diff --git a/app/client/src/git/index.ts b/app/client/src/git/index.ts index d3adb531597b..28e6da45a4a9 100644 --- a/app/client/src/git/index.ts +++ b/app/client/src/git/index.ts @@ -20,7 +20,14 @@ export { gitReducer } from "./store"; export { selectCurrentBranch as selectGitCurrentBranch, selectProtectedMode as selectGitProtectedMode, -} from "./store/selectors/gitSingleArtifactSelectors"; +} from "./store/selectors/gitArtifactSelectors"; // sagas export { default as gitSagas } from "./sagas"; + +// types +export type { + GitArtifactDef, + GitArtifactRootReduxState, + GitConfigReduxState, +} from "./store/types"; diff --git a/app/client/src/git/sagas/pullSaga.ts b/app/client/src/git/sagas/pullSaga.ts index 40c59651d416..07347326e3e0 100644 --- a/app/client/src/git/sagas/pullSaga.ts +++ b/app/client/src/git/sagas/pullSaga.ts @@ -4,7 +4,7 @@ import type { PullResponse } from "git/requests/pullRequest.types"; import type { PullInitPayload } from "git/store/actions/pullActions"; import { gitArtifactActions } from "git/store/gitArtifactSlice"; import type { GitArtifactPayloadAction } from "git/store/types"; -import { selectCurrentBranch } from "git/store/selectors/gitSingleArtifactSelectors"; +import { selectCurrentBranch } from "git/store/selectors/gitArtifactSelectors"; // internal dependencies import { validateResponse } from "sagas/ErrorSagas"; diff --git a/app/client/src/git/sagas/triggerAutocommitSaga.ts b/app/client/src/git/sagas/triggerAutocommitSaga.ts index 37ce54cc53f7..6725fb0d59f9 100644 --- a/app/client/src/git/sagas/triggerAutocommitSaga.ts +++ b/app/client/src/git/sagas/triggerAutocommitSaga.ts @@ -12,11 +12,8 @@ import type { } from "git/requests/triggerAutocommitRequest.types"; import type { TriggerAutocommitInitPayload } from "git/store/actions/triggerAutocommitActions"; import { gitArtifactActions } from "git/store/gitArtifactSlice"; -import { - selectAutocommitEnabled, - type GitArtifactDef, -} from "git/store/selectors/gitSingleArtifactSelectors"; -import type { GitArtifactPayloadAction } from "git/store/types"; +import { selectAutocommitEnabled } from "git/store/selectors/gitArtifactSelectors"; +import type { GitArtifactDef, GitArtifactPayloadAction } from "git/store/types"; import { call, cancel, diff --git a/app/client/src/git/store/actions/checkoutBranchActions.ts b/app/client/src/git/store/actions/checkoutBranchActions.ts index 31baf78e7b73..e9451a614d7f 100644 --- a/app/client/src/git/store/actions/checkoutBranchActions.ts +++ b/app/client/src/git/store/actions/checkoutBranchActions.ts @@ -1,4 +1,4 @@ -import { createSingleArtifactAction } from "../helpers/createSingleArtifactAction"; +import { createArtifactAction } from "../helpers/createArtifactAction"; import type { GitAsyncErrorPayload } from "../types"; import type { CheckoutBranchRequestParams } from "git/requests/checkoutBranchRequest.types"; @@ -7,7 +7,7 @@ export interface CheckoutBranchInitPayload extends CheckoutBranchRequestParams { } export const checkoutBranchInitAction = - createSingleArtifactAction((state, action) => { + createArtifactAction((state, action) => { state.apiResponses.checkoutBranch.loading = true; state.apiResponses.checkoutBranch.error = null; state.ui.checkoutDestBranch = action.payload.branchName; @@ -15,18 +15,16 @@ export const checkoutBranchInitAction = return state; }); -export const checkoutBranchSuccessAction = createSingleArtifactAction( - (state) => { - state.apiResponses.checkoutBranch.loading = false; - state.apiResponses.checkoutBranch.error = null; - state.ui.checkoutDestBranch = null; +export const checkoutBranchSuccessAction = createArtifactAction((state) => { + state.apiResponses.checkoutBranch.loading = false; + state.apiResponses.checkoutBranch.error = null; + state.ui.checkoutDestBranch = null; - return state; - }, -); + return state; +}); export const checkoutBranchErrorAction = - createSingleArtifactAction((state, action) => { + createArtifactAction((state, action) => { const { error } = action.payload; state.apiResponses.checkoutBranch.loading = false; diff --git a/app/client/src/git/store/actions/commitActions.ts b/app/client/src/git/store/actions/commitActions.ts index 3a85ef0e1edd..876463e803a9 100644 --- a/app/client/src/git/store/actions/commitActions.ts +++ b/app/client/src/git/store/actions/commitActions.ts @@ -1,4 +1,4 @@ -import { createSingleArtifactAction } from "../helpers/createSingleArtifactAction"; +import { createArtifactAction } from "../helpers/createArtifactAction"; import type { GitAsyncErrorPayload } from "../types"; import type { CommitRequestParams } from "git/requests/commitRequest.types"; @@ -6,7 +6,7 @@ export interface CommitInitPayload extends CommitRequestParams { artifactId: string; } -export const commitInitAction = createSingleArtifactAction( +export const commitInitAction = createArtifactAction( (state) => { state.apiResponses.commit.loading = true; state.apiResponses.commit.error = null; @@ -15,23 +15,24 @@ export const commitInitAction = createSingleArtifactAction( }, ); -export const commitSuccessAction = createSingleArtifactAction((state) => { +export const commitSuccessAction = createArtifactAction((state) => { state.apiResponses.commit.loading = false; return state; }); -export const commitErrorAction = - createSingleArtifactAction((state, action) => { +export const commitErrorAction = createArtifactAction( + (state, action) => { const { error } = action.payload; state.apiResponses.commit.loading = false; state.apiResponses.commit.error = error; return state; - }); + }, +); -export const clearCommitErrorAction = createSingleArtifactAction((state) => { +export const clearCommitErrorAction = createArtifactAction((state) => { state.apiResponses.commit.error = null; return state; diff --git a/app/client/src/git/store/actions/connectActions.ts b/app/client/src/git/store/actions/connectActions.ts index 7fed98500000..84f7e3612ccc 100644 --- a/app/client/src/git/store/actions/connectActions.ts +++ b/app/client/src/git/store/actions/connectActions.ts @@ -1,4 +1,4 @@ -import { createSingleArtifactAction } from "../helpers/createSingleArtifactAction"; +import { createArtifactAction } from "../helpers/createArtifactAction"; import type { GitAsyncErrorPayload } from "../types"; import type { ConnectRequestParams } from "git/requests/connectRequest.types"; @@ -6,7 +6,7 @@ export interface ConnectInitPayload extends ConnectRequestParams { branchedPageId?: string; } -export const connectInitAction = createSingleArtifactAction( +export const connectInitAction = createArtifactAction( (state) => { state.apiResponses.connect.loading = true; state.apiResponses.connect.error = null; @@ -15,18 +15,19 @@ export const connectInitAction = createSingleArtifactAction( }, ); -export const connectSuccessAction = createSingleArtifactAction((state) => { +export const connectSuccessAction = createArtifactAction((state) => { state.apiResponses.connect.loading = false; return state; }); -export const connectErrorAction = - createSingleArtifactAction((state, action) => { +export const connectErrorAction = createArtifactAction( + (state, action) => { const { error } = action.payload; state.apiResponses.connect.loading = false; state.apiResponses.connect.error = error; return state; - }); + }, +); diff --git a/app/client/src/git/store/actions/createBranchActions.ts b/app/client/src/git/store/actions/createBranchActions.ts index 116d8ebcfeef..010a7550888f 100644 --- a/app/client/src/git/store/actions/createBranchActions.ts +++ b/app/client/src/git/store/actions/createBranchActions.ts @@ -1,4 +1,4 @@ -import { createSingleArtifactAction } from "../helpers/createSingleArtifactAction"; +import { createArtifactAction } from "../helpers/createArtifactAction"; import type { GitAsyncErrorPayload } from "../types"; import type { CreateBranchRequestParams } from "git/requests/createBranchRequest.types"; @@ -7,21 +7,21 @@ export interface CreateBranchInitPayload extends CreateBranchRequestParams { } export const createBranchInitAction = - createSingleArtifactAction((state) => { + createArtifactAction((state) => { state.apiResponses.createBranch.loading = true; state.apiResponses.createBranch.error = null; return state; }); -export const createBranchSuccessAction = createSingleArtifactAction((state) => { +export const createBranchSuccessAction = createArtifactAction((state) => { state.apiResponses.createBranch.loading = false; return state; }); export const createBranchErrorAction = - createSingleArtifactAction((state, action) => { + createArtifactAction((state, action) => { const { error } = action.payload; state.apiResponses.createBranch.loading = false; diff --git a/app/client/src/git/store/actions/deleteBranchActions.ts b/app/client/src/git/store/actions/deleteBranchActions.ts index a7ae769e79eb..0656886f39d4 100644 --- a/app/client/src/git/store/actions/deleteBranchActions.ts +++ b/app/client/src/git/store/actions/deleteBranchActions.ts @@ -1,4 +1,4 @@ -import { createSingleArtifactAction } from "../helpers/createSingleArtifactAction"; +import { createArtifactAction } from "../helpers/createArtifactAction"; import type { GitAsyncErrorPayload } from "../types"; import type { DeleteBranchRequestParams } from "../../requests/deleteBranchRequest.types"; @@ -7,21 +7,21 @@ export interface DeleteBranchInitPayload extends DeleteBranchRequestParams { } export const deleteBranchInitAction = - createSingleArtifactAction((state) => { + createArtifactAction((state) => { state.apiResponses.deleteBranch.loading = true; state.apiResponses.deleteBranch.error = null; return state; }); -export const deleteBranchSuccessAction = createSingleArtifactAction((state) => { +export const deleteBranchSuccessAction = createArtifactAction((state) => { state.apiResponses.deleteBranch.loading = false; return state; }); export const deleteBranchErrorAction = - createSingleArtifactAction((state, action) => { + createArtifactAction((state, action) => { const { error } = action.payload; state.apiResponses.deleteBranch.loading = false; diff --git a/app/client/src/git/store/actions/discardActions.ts b/app/client/src/git/store/actions/discardActions.ts index 35d37c0a6d0e..0f514cd0e585 100644 --- a/app/client/src/git/store/actions/discardActions.ts +++ b/app/client/src/git/store/actions/discardActions.ts @@ -1,20 +1,20 @@ -import { createSingleArtifactAction } from "../helpers/createSingleArtifactAction"; +import { createArtifactAction } from "../helpers/createArtifactAction"; import type { GitArtifactErrorPayloadAction } from "../types"; -export const discardInitAction = createSingleArtifactAction((state) => { +export const discardInitAction = createArtifactAction((state) => { state.apiResponses.discard.loading = true; state.apiResponses.discard.error = null; return state; }); -export const discardSuccessAction = createSingleArtifactAction((state) => { +export const discardSuccessAction = createArtifactAction((state) => { state.apiResponses.discard.loading = false; return state; }); -export const discardErrorAction = createSingleArtifactAction( +export const discardErrorAction = createArtifactAction( (state, action: GitArtifactErrorPayloadAction) => { const { error } = action.payload; @@ -25,7 +25,7 @@ export const discardErrorAction = createSingleArtifactAction( }, ); -export const clearDiscardErrorAction = createSingleArtifactAction((state) => { +export const clearDiscardErrorAction = createArtifactAction((state) => { state.apiResponses.discard.error = null; return state; diff --git a/app/client/src/git/store/actions/disconnectActions.ts b/app/client/src/git/store/actions/disconnectActions.ts index dba26c0de629..082aa91b7970 100644 --- a/app/client/src/git/store/actions/disconnectActions.ts +++ b/app/client/src/git/store/actions/disconnectActions.ts @@ -1,20 +1,20 @@ -import { createSingleArtifactAction } from "../helpers/createSingleArtifactAction"; +import { createArtifactAction } from "../helpers/createArtifactAction"; import type { GitArtifactErrorPayloadAction } from "../types"; -export const disconnectInitAction = createSingleArtifactAction((state) => { +export const disconnectInitAction = createArtifactAction((state) => { state.apiResponses.disconnect.loading = true; state.apiResponses.disconnect.error = null; return state; }); -export const disconnectSuccessAction = createSingleArtifactAction((state) => { +export const disconnectSuccessAction = createArtifactAction((state) => { state.apiResponses.disconnect.loading = false; return state; }); -export const disconnectErrorAction = createSingleArtifactAction( +export const disconnectErrorAction = createArtifactAction( (state, action: GitArtifactErrorPayloadAction) => { const { error } = action.payload; diff --git a/app/client/src/git/store/actions/fetchAutocommitProgressActions.ts b/app/client/src/git/store/actions/fetchAutocommitProgressActions.ts index a7d92793e4aa..bbde6e4dd649 100644 --- a/app/client/src/git/store/actions/fetchAutocommitProgressActions.ts +++ b/app/client/src/git/store/actions/fetchAutocommitProgressActions.ts @@ -1,7 +1,7 @@ import type { GitAsyncErrorPayload } from "../types"; -import { createSingleArtifactAction } from "../helpers/createSingleArtifactAction"; +import { createArtifactAction } from "../helpers/createArtifactAction"; -export const fetchAutocommitProgressInitAction = createSingleArtifactAction( +export const fetchAutocommitProgressInitAction = createArtifactAction( (state) => { state.apiResponses.autocommitProgress.loading = true; state.apiResponses.autocommitProgress.error = null; @@ -10,7 +10,7 @@ export const fetchAutocommitProgressInitAction = createSingleArtifactAction( }, ); -export const fetchAutocommitProgressSuccessAction = createSingleArtifactAction( +export const fetchAutocommitProgressSuccessAction = createArtifactAction( (state) => { state.apiResponses.autocommitProgress.loading = false; @@ -19,7 +19,7 @@ export const fetchAutocommitProgressSuccessAction = createSingleArtifactAction( ); export const fetchAutocommitProgressErrorAction = - createSingleArtifactAction((state, action) => { + createArtifactAction((state, action) => { const { error } = action.payload; state.apiResponses.autocommitProgress.loading = false; diff --git a/app/client/src/git/store/actions/fetchBranchesActions.ts b/app/client/src/git/store/actions/fetchBranchesActions.ts index d3d2ef98d01b..6758ad918eb0 100644 --- a/app/client/src/git/store/actions/fetchBranchesActions.ts +++ b/app/client/src/git/store/actions/fetchBranchesActions.ts @@ -3,21 +3,21 @@ import type { FetchBranchesResponseData, } from "../../requests/fetchBranchesRequest.types"; import type { GitAsyncErrorPayload, GitAsyncSuccessPayload } from "../types"; -import { createSingleArtifactAction } from "../helpers/createSingleArtifactAction"; +import { createArtifactAction } from "../helpers/createArtifactAction"; export interface FetchBranchesInitPayload extends FetchBranchesRequestParams { artifactId: string; } export const fetchBranchesInitAction = - createSingleArtifactAction((state) => { + createArtifactAction((state) => { state.apiResponses.branches.loading = true; state.apiResponses.branches.error = null; return state; }); -export const fetchBranchesSuccessAction = createSingleArtifactAction< +export const fetchBranchesSuccessAction = createArtifactAction< GitAsyncSuccessPayload >((state, action) => { state.apiResponses.branches.loading = false; @@ -27,7 +27,7 @@ export const fetchBranchesSuccessAction = createSingleArtifactAction< }); export const fetchBranchesErrorAction = - createSingleArtifactAction((state, action) => { + createArtifactAction((state, action) => { const { error } = action.payload; state.apiResponses.branches.loading = false; diff --git a/app/client/src/git/store/actions/fetchLocalProfileActions.ts b/app/client/src/git/store/actions/fetchLocalProfileActions.ts index 3559a2814c35..33a62514f44c 100644 --- a/app/client/src/git/store/actions/fetchLocalProfileActions.ts +++ b/app/client/src/git/store/actions/fetchLocalProfileActions.ts @@ -3,18 +3,16 @@ import type { GitArtifactErrorPayloadAction, GitAsyncSuccessPayload, } from "../types"; -import { createSingleArtifactAction } from "../helpers/createSingleArtifactAction"; +import { createArtifactAction } from "../helpers/createArtifactAction"; -export const fetchLocalProfileInitAction = createSingleArtifactAction( - (state) => { - state.apiResponses.localProfile.loading = true; - state.apiResponses.localProfile.error = null; +export const fetchLocalProfileInitAction = createArtifactAction((state) => { + state.apiResponses.localProfile.loading = true; + state.apiResponses.localProfile.error = null; - return state; - }, -); + return state; +}); -export const fetchLocalProfileSuccessAction = createSingleArtifactAction< +export const fetchLocalProfileSuccessAction = createArtifactAction< GitAsyncSuccessPayload >((state, action) => { state.apiResponses.localProfile.loading = false; @@ -23,7 +21,7 @@ export const fetchLocalProfileSuccessAction = createSingleArtifactAction< return state; }); -export const fetchLocalProfileErrorAction = createSingleArtifactAction( +export const fetchLocalProfileErrorAction = createArtifactAction( (state, action: GitArtifactErrorPayloadAction) => { const { error } = action.payload; diff --git a/app/client/src/git/store/actions/fetchMergeStatusActions.ts b/app/client/src/git/store/actions/fetchMergeStatusActions.ts index 65ed313114cb..26b72829fadd 100644 --- a/app/client/src/git/store/actions/fetchMergeStatusActions.ts +++ b/app/client/src/git/store/actions/fetchMergeStatusActions.ts @@ -1,5 +1,5 @@ import type { GitAsyncSuccessPayload, GitAsyncErrorPayload } from "../types"; -import { createSingleArtifactAction } from "../helpers/createSingleArtifactAction"; +import { createArtifactAction } from "../helpers/createArtifactAction"; import type { FetchMergeStatusRequestParams, FetchMergeStatusResponseData, @@ -11,14 +11,14 @@ export interface FetchMergeStatusInitPayload } export const fetchMergeStatusInitAction = - createSingleArtifactAction((state) => { + createArtifactAction((state) => { state.apiResponses.mergeStatus.loading = true; state.apiResponses.mergeStatus.error = null; return state; }); -export const fetchMergeStatusSuccessAction = createSingleArtifactAction< +export const fetchMergeStatusSuccessAction = createArtifactAction< GitAsyncSuccessPayload >((state, action) => { state.apiResponses.mergeStatus.loading = false; @@ -28,7 +28,7 @@ export const fetchMergeStatusSuccessAction = createSingleArtifactAction< }); export const fetchMergeStatusErrorAction = - createSingleArtifactAction((state, action) => { + createArtifactAction((state, action) => { const { error } = action.payload; state.apiResponses.mergeStatus.loading = false; @@ -37,7 +37,7 @@ export const fetchMergeStatusErrorAction = return state; }); -export const clearMergeStatusAction = createSingleArtifactAction((state) => { +export const clearMergeStatusAction = createArtifactAction((state) => { state.apiResponses.mergeStatus.loading = false; state.apiResponses.mergeStatus.error = null; state.apiResponses.mergeStatus.value = null; diff --git a/app/client/src/git/store/actions/fetchMetadataActions.ts b/app/client/src/git/store/actions/fetchMetadataActions.ts index 176413dfbaaa..6e7a9f2f1e3d 100644 --- a/app/client/src/git/store/actions/fetchMetadataActions.ts +++ b/app/client/src/git/store/actions/fetchMetadataActions.ts @@ -1,15 +1,15 @@ import type { GitAsyncErrorPayload, GitAsyncSuccessPayload } from "../types"; -import { createSingleArtifactAction } from "../helpers/createSingleArtifactAction"; +import { createArtifactAction } from "../helpers/createArtifactAction"; import type { FetchMetadataResponseData } from "git/requests/fetchMetadataRequest.types"; -export const fetchMetadataInitAction = createSingleArtifactAction((state) => { +export const fetchMetadataInitAction = createArtifactAction((state) => { state.apiResponses.metadata.loading = true; state.apiResponses.metadata.error = null; return state; }); -export const fetchMetadataSuccessAction = createSingleArtifactAction< +export const fetchMetadataSuccessAction = createArtifactAction< GitAsyncSuccessPayload >((state, action) => { state.apiResponses.metadata.loading = false; @@ -19,7 +19,7 @@ export const fetchMetadataSuccessAction = createSingleArtifactAction< }); export const fetchMetadataErrorAction = - createSingleArtifactAction((state, action) => { + createArtifactAction((state, action) => { const { error } = action.payload; state.apiResponses.metadata.loading = false; diff --git a/app/client/src/git/store/actions/fetchProtectedBranchesActions.ts b/app/client/src/git/store/actions/fetchProtectedBranchesActions.ts index dc66ff2290c0..1ad38bf4096c 100644 --- a/app/client/src/git/store/actions/fetchProtectedBranchesActions.ts +++ b/app/client/src/git/store/actions/fetchProtectedBranchesActions.ts @@ -1,8 +1,8 @@ import type { GitAsyncSuccessPayload, GitAsyncErrorPayload } from "../types"; -import { createSingleArtifactAction } from "../helpers/createSingleArtifactAction"; +import { createArtifactAction } from "../helpers/createArtifactAction"; import type { FetchProtectedBranchesResponseData } from "git/requests/fetchProtectedBranchesRequest.types"; -export const fetchProtectedBranchesInitAction = createSingleArtifactAction( +export const fetchProtectedBranchesInitAction = createArtifactAction( (state) => { state.apiResponses.protectedBranches.loading = true; state.apiResponses.protectedBranches.error = null; @@ -11,7 +11,7 @@ export const fetchProtectedBranchesInitAction = createSingleArtifactAction( }, ); -export const fetchProtectedBranchesSuccessAction = createSingleArtifactAction< +export const fetchProtectedBranchesSuccessAction = createArtifactAction< GitAsyncSuccessPayload >((state, action) => { state.apiResponses.protectedBranches.loading = false; @@ -21,7 +21,7 @@ export const fetchProtectedBranchesSuccessAction = createSingleArtifactAction< }); export const fetchProtectedBranchesErrorAction = - createSingleArtifactAction((state, action) => { + createArtifactAction((state, action) => { const { error } = action.payload; state.apiResponses.protectedBranches.loading = false; diff --git a/app/client/src/git/store/actions/fetchSSHKeyActions.ts b/app/client/src/git/store/actions/fetchSSHKeyActions.ts index 828cf6ebcb75..386dd4643411 100644 --- a/app/client/src/git/store/actions/fetchSSHKeyActions.ts +++ b/app/client/src/git/store/actions/fetchSSHKeyActions.ts @@ -1,15 +1,15 @@ import type { GitAsyncErrorPayload, GitAsyncSuccessPayload } from "../types"; -import { createSingleArtifactAction } from "../helpers/createSingleArtifactAction"; +import { createArtifactAction } from "../helpers/createArtifactAction"; import type { FetchSSHKeyResponseData } from "git/requests/fetchSSHKeyRequest.types"; -export const fetchSSHKeyInitAction = createSingleArtifactAction((state) => { +export const fetchSSHKeyInitAction = createArtifactAction((state) => { state.apiResponses.sshKey.loading = true; state.apiResponses.sshKey.error = null; return state; }); -export const fetchSSHKeySuccessAction = createSingleArtifactAction< +export const fetchSSHKeySuccessAction = createArtifactAction< GitAsyncSuccessPayload >((state, action) => { state.apiResponses.sshKey.loading = false; @@ -20,7 +20,7 @@ export const fetchSSHKeySuccessAction = createSingleArtifactAction< }); export const fetchSSHKeyErrorAction = - createSingleArtifactAction((state, action) => { + createArtifactAction((state, action) => { const { error } = action.payload; state.apiResponses.sshKey.loading = false; @@ -29,7 +29,7 @@ export const fetchSSHKeyErrorAction = return state; }); -export const resetFetchSSHKeyAction = createSingleArtifactAction((state) => { +export const resetFetchSSHKeyAction = createArtifactAction((state) => { state.apiResponses.sshKey.loading = false; state.apiResponses.sshKey.error = null; state.apiResponses.sshKey.value = null; diff --git a/app/client/src/git/store/actions/fetchStatusActions.ts b/app/client/src/git/store/actions/fetchStatusActions.ts index eb348e87ac62..47097593260b 100644 --- a/app/client/src/git/store/actions/fetchStatusActions.ts +++ b/app/client/src/git/store/actions/fetchStatusActions.ts @@ -3,21 +3,21 @@ import type { FetchStatusResponseData, } from "git/requests/fetchStatusRequest.types"; import type { GitAsyncErrorPayload, GitAsyncSuccessPayload } from "../types"; -import { createSingleArtifactAction } from "../helpers/createSingleArtifactAction"; +import { createArtifactAction } from "../helpers/createArtifactAction"; export interface FetchStatusInitPayload extends FetchStatusRequestParams { artifactId: string; } export const fetchStatusInitAction = - createSingleArtifactAction((state) => { + createArtifactAction((state) => { state.apiResponses.status.loading = true; state.apiResponses.status.error = null; return state; }); -export const fetchStatusSuccessAction = createSingleArtifactAction< +export const fetchStatusSuccessAction = createArtifactAction< GitAsyncSuccessPayload >((state, action) => { state.apiResponses.status.loading = false; @@ -27,7 +27,7 @@ export const fetchStatusSuccessAction = createSingleArtifactAction< }); export const fetchStatusErrorAction = - createSingleArtifactAction((state, action) => { + createArtifactAction((state, action) => { const { error } = action.payload; state.apiResponses.status.loading = false; diff --git a/app/client/src/git/store/actions/generateSSHKeyActions.ts b/app/client/src/git/store/actions/generateSSHKeyActions.ts index fa70c3a1ba28..569d7d9995c2 100644 --- a/app/client/src/git/store/actions/generateSSHKeyActions.ts +++ b/app/client/src/git/store/actions/generateSSHKeyActions.ts @@ -2,21 +2,21 @@ import type { GenerateSSHKeyRequestParams, GenerateSSHKeyResponseData, } from "git/requests/generateSSHKeyRequest.types"; -import { createSingleArtifactAction } from "../helpers/createSingleArtifactAction"; +import { createArtifactAction } from "../helpers/createArtifactAction"; import type { GitAsyncErrorPayload, GitAsyncSuccessPayload } from "../types"; export interface GenerateSSHKeyInitPayload extends GenerateSSHKeyRequestParams {} export const generateSSHKeyInitAction = - createSingleArtifactAction((state) => { + createArtifactAction((state) => { state.apiResponses.generateSSHKey.loading = true; state.apiResponses.generateSSHKey.error = null; return state; }); -export const generateSSHKeySuccessAction = createSingleArtifactAction< +export const generateSSHKeySuccessAction = createArtifactAction< GitAsyncSuccessPayload >((state, action) => { state.apiResponses.generateSSHKey.loading = false; @@ -27,7 +27,7 @@ export const generateSSHKeySuccessAction = createSingleArtifactAction< }); export const generateSSHKeyErrorAction = - createSingleArtifactAction((state, action) => { + createArtifactAction((state, action) => { const { error } = action.payload; state.apiResponses.generateSSHKey.loading = false; @@ -36,7 +36,7 @@ export const generateSSHKeyErrorAction = return state; }); -export const resetGenerateSSHKeyAction = createSingleArtifactAction((state) => { +export const resetGenerateSSHKeyAction = createArtifactAction((state) => { state.apiResponses.generateSSHKey.loading = false; state.apiResponses.generateSSHKey.error = null; diff --git a/app/client/src/git/store/actions/gitImportActions.ts b/app/client/src/git/store/actions/gitImportActions.ts index 49411b55dd55..d0c3665dc1ad 100644 --- a/app/client/src/git/store/actions/gitImportActions.ts +++ b/app/client/src/git/store/actions/gitImportActions.ts @@ -1,25 +1,26 @@ -import { createSingleArtifactAction } from "../helpers/createSingleArtifactAction"; +import { createArtifactAction } from "../helpers/createArtifactAction"; import type { GitAsyncErrorPayload } from "../types"; -export const gitImportInitAction = createSingleArtifactAction((state) => { +export const gitImportInitAction = createArtifactAction((state) => { state.apiResponses.gitImport.loading = true; state.apiResponses.gitImport.error = null; return state; }); -export const gitImportSuccessAction = createSingleArtifactAction((state) => { +export const gitImportSuccessAction = createArtifactAction((state) => { state.apiResponses.gitImport.loading = false; return state; }); -export const gitImportErrorAction = - createSingleArtifactAction((state, action) => { +export const gitImportErrorAction = createArtifactAction( + (state, action) => { const { error } = action.payload; state.apiResponses.gitImport.loading = false; state.apiResponses.gitImport.error = error; return state; - }); + }, +); diff --git a/app/client/src/git/store/actions/initGitActions.ts b/app/client/src/git/store/actions/initGitActions.ts index 6d53a492474e..ebe588555a24 100644 --- a/app/client/src/git/store/actions/initGitActions.ts +++ b/app/client/src/git/store/actions/initGitActions.ts @@ -1,4 +1,4 @@ -import { createSingleArtifactAction } from "../helpers/createSingleArtifactAction"; +import { createArtifactAction } from "../helpers/createArtifactAction"; import type { ApplicationPayload } from "entities/Application"; export interface InitGitForEditorPayload { @@ -6,6 +6,6 @@ export interface InitGitForEditorPayload { } export const initGitForEditorAction = - createSingleArtifactAction((state) => { + createArtifactAction((state) => { return state; }); diff --git a/app/client/src/git/store/actions/mergeActions.ts b/app/client/src/git/store/actions/mergeActions.ts index 5bb17a351ce6..0d4e67eea8fe 100644 --- a/app/client/src/git/store/actions/mergeActions.ts +++ b/app/client/src/git/store/actions/mergeActions.ts @@ -1,20 +1,20 @@ -import { createSingleArtifactAction } from "../helpers/createSingleArtifactAction"; +import { createArtifactAction } from "../helpers/createArtifactAction"; import type { GitArtifactErrorPayloadAction } from "../types"; -export const mergeInitAction = createSingleArtifactAction((state) => { +export const mergeInitAction = createArtifactAction((state) => { state.apiResponses.merge.loading = true; state.apiResponses.merge.error = null; return state; }); -export const mergeSuccessAction = createSingleArtifactAction((state) => { +export const mergeSuccessAction = createArtifactAction((state) => { state.apiResponses.merge.loading = false; return state; }); -export const mergeErrorAction = createSingleArtifactAction( +export const mergeErrorAction = createArtifactAction( (state, action: GitArtifactErrorPayloadAction) => { const { error } = action.payload; diff --git a/app/client/src/git/store/actions/mountActions.ts b/app/client/src/git/store/actions/mountActions.ts index 25ddd1c34674..8d35126d9502 100644 --- a/app/client/src/git/store/actions/mountActions.ts +++ b/app/client/src/git/store/actions/mountActions.ts @@ -1,24 +1,27 @@ import type { PayloadAction } from "@reduxjs/toolkit"; -import type { GitArtifactBasePayload, GitArtifactReduxState } from "../types"; -import { gitSingleArtifactInitialState } from "../helpers/gitSingleArtifactInitialState"; +import type { + GitArtifactBasePayload, + GitArtifactRootReduxState, +} from "../types"; +import { gitArtifactInitialState } from "../helpers/initialState"; // ! This might be removed later export const mountAction = ( - state: GitArtifactReduxState, + state: GitArtifactRootReduxState, action: PayloadAction, ) => { const { artifactDef } = action.payload; const { artifactType, baseArtifactId } = artifactDef; state[artifactType] ??= {}; - state[artifactType][baseArtifactId] ??= gitSingleArtifactInitialState; + state[artifactType][baseArtifactId] ??= gitArtifactInitialState; return state; }; export const unmountAction = ( - state: GitArtifactReduxState, + state: GitArtifactRootReduxState, action: PayloadAction, ) => { const { artifactDef } = action.payload; diff --git a/app/client/src/git/store/actions/pullActions.ts b/app/client/src/git/store/actions/pullActions.ts index 00a0d00f2033..48d3398e18c6 100644 --- a/app/client/src/git/store/actions/pullActions.ts +++ b/app/client/src/git/store/actions/pullActions.ts @@ -1,26 +1,24 @@ -import { createSingleArtifactAction } from "../helpers/createSingleArtifactAction"; +import { createArtifactAction } from "../helpers/createArtifactAction"; import type { GitAsyncErrorPayload } from "../types"; export interface PullInitPayload { artifactId: string; } -export const pullInitAction = createSingleArtifactAction( - (state) => { - state.apiResponses.pull.loading = true; - state.apiResponses.pull.error = null; +export const pullInitAction = createArtifactAction((state) => { + state.apiResponses.pull.loading = true; + state.apiResponses.pull.error = null; - return state; - }, -); + return state; +}); -export const pullSuccessAction = createSingleArtifactAction((state) => { +export const pullSuccessAction = createArtifactAction((state) => { state.apiResponses.pull.loading = false; return state; }); -export const pullErrorAction = createSingleArtifactAction( +export const pullErrorAction = createArtifactAction( (state, action) => { const { error } = action.payload; diff --git a/app/client/src/git/store/actions/repoLimitErrorModalActions.ts b/app/client/src/git/store/actions/repoLimitErrorModalActions.ts index b1867c1d5926..a2c96bac7721 100644 --- a/app/client/src/git/store/actions/repoLimitErrorModalActions.ts +++ b/app/client/src/git/store/actions/repoLimitErrorModalActions.ts @@ -1,16 +1,14 @@ -import { createSingleArtifactAction } from "../helpers/createSingleArtifactAction"; +import { createArtifactAction } from "../helpers/createArtifactAction"; interface ToggleRepoLimitModalActionPayload { open: boolean; } export const toggleRepoLimitErrorModalAction = - createSingleArtifactAction( - (state, action) => { - const { open } = action.payload; + createArtifactAction((state, action) => { + const { open } = action.payload; - state.ui.repoLimitErrorModalOpen = open; + state.ui.repoLimitErrorModalOpen = open; - return state; - }, - ); + return state; + }); diff --git a/app/client/src/git/store/actions/toggleAutocommitActions.ts b/app/client/src/git/store/actions/toggleAutocommitActions.ts index 96721698196f..d9c700cbb457 100644 --- a/app/client/src/git/store/actions/toggleAutocommitActions.ts +++ b/app/client/src/git/store/actions/toggleAutocommitActions.ts @@ -1,24 +1,20 @@ -import { createSingleArtifactAction } from "../helpers/createSingleArtifactAction"; +import { createArtifactAction } from "../helpers/createArtifactAction"; import type { GitArtifactErrorPayloadAction } from "../types"; -export const toggleAutocommitInitAction = createSingleArtifactAction( - (state) => { - state.apiResponses.toggleAutocommit.loading = true; - state.apiResponses.toggleAutocommit.error = null; +export const toggleAutocommitInitAction = createArtifactAction((state) => { + state.apiResponses.toggleAutocommit.loading = true; + state.apiResponses.toggleAutocommit.error = null; - return state; - }, -); + return state; +}); -export const toggleAutocommitSuccessAction = createSingleArtifactAction( - (state) => { - state.apiResponses.toggleAutocommit.loading = false; +export const toggleAutocommitSuccessAction = createArtifactAction((state) => { + state.apiResponses.toggleAutocommit.loading = false; - return state; - }, -); + return state; +}); -export const toggleAutocommitErrorAction = createSingleArtifactAction( +export const toggleAutocommitErrorAction = createArtifactAction( (state, action: GitArtifactErrorPayloadAction) => { const { error } = action.payload; diff --git a/app/client/src/git/store/actions/triggerAutocommitActions.ts b/app/client/src/git/store/actions/triggerAutocommitActions.ts index 28e88ecd2f16..da8075bc347f 100644 --- a/app/client/src/git/store/actions/triggerAutocommitActions.ts +++ b/app/client/src/git/store/actions/triggerAutocommitActions.ts @@ -1,4 +1,4 @@ -import { createSingleArtifactAction } from "../helpers/createSingleArtifactAction"; +import { createArtifactAction } from "../helpers/createArtifactAction"; import type { GitAsyncErrorPayload } from "../types"; export interface TriggerAutocommitInitPayload { @@ -6,23 +6,21 @@ export interface TriggerAutocommitInitPayload { } export const triggerAutocommitInitAction = - createSingleArtifactAction((state) => { + createArtifactAction((state) => { state.apiResponses.triggerAutocommit.loading = true; state.apiResponses.triggerAutocommit.error = null; return state; }); -export const triggerAutocommitSuccessAction = createSingleArtifactAction( - (state) => { - state.apiResponses.triggerAutocommit.loading = false; +export const triggerAutocommitSuccessAction = createArtifactAction((state) => { + state.apiResponses.triggerAutocommit.loading = false; - return state; - }, -); + return state; +}); export const triggerAutocommitErrorAction = - createSingleArtifactAction((state, action) => { + createArtifactAction((state, action) => { const { error } = action.payload; state.apiResponses.triggerAutocommit.loading = false; @@ -31,7 +29,7 @@ export const triggerAutocommitErrorAction = return state; }); -export const pollAutocommitProgressStartAction = createSingleArtifactAction( +export const pollAutocommitProgressStartAction = createArtifactAction( (state) => { state.ui.autocommitPolling = true; @@ -39,7 +37,7 @@ export const pollAutocommitProgressStartAction = createSingleArtifactAction( }, ); -export const pollAutocommitProgressStopAction = createSingleArtifactAction( +export const pollAutocommitProgressStopAction = createArtifactAction( (state) => { state.ui.autocommitPolling = false; diff --git a/app/client/src/git/store/actions/uiActions.ts b/app/client/src/git/store/actions/uiActions.ts index 34722574fb4e..c98c53cd3485 100644 --- a/app/client/src/git/store/actions/uiActions.ts +++ b/app/client/src/git/store/actions/uiActions.ts @@ -1,5 +1,5 @@ import type { GitOpsTab, GitSettingsTab } from "git/constants/enums"; -import { createSingleArtifactAction } from "../helpers/createSingleArtifactAction"; +import { createArtifactAction } from "../helpers/createArtifactAction"; // connect modal export interface ToggleConnectModalPayload { @@ -7,7 +7,7 @@ export interface ToggleConnectModalPayload { } export const toggleConnectModalAction = - createSingleArtifactAction((state, action) => { + createArtifactAction((state, action) => { const { open } = action.payload; state.ui.connectModalOpen = open; @@ -21,7 +21,7 @@ export interface OpenDisconnectModalPayload { } export const openDisconnectModalAction = - createSingleArtifactAction((state, action) => { + createArtifactAction((state, action) => { state.ui.disconnectBaseArtifactId = action.payload.artifactDef.baseArtifactId; state.ui.disconnectArtifactName = action.payload.artifactName; @@ -29,14 +29,12 @@ export const openDisconnectModalAction = return state; }); -export const closeDisconnectModalAction = createSingleArtifactAction( - (state) => { - state.ui.disconnectBaseArtifactId = null; - state.ui.disconnectArtifactName = null; +export const closeDisconnectModalAction = createArtifactAction((state) => { + state.ui.disconnectBaseArtifactId = null; + state.ui.disconnectArtifactName = null; - return state; - }, -); + return state; +}); // ops modal @@ -45,15 +43,16 @@ export interface ToggleOpsModalPayload { tab: keyof typeof GitOpsTab; } -export const toggleOpsModalAction = - createSingleArtifactAction((state, action) => { +export const toggleOpsModalAction = createArtifactAction( + (state, action) => { const { open, tab } = action.payload; state.ui.opsModalOpen = open; state.ui.opsModalTab = tab; return state; - }); + }, +); // settings modal export interface ToggleSettingsModalPayload { @@ -62,7 +61,7 @@ export interface ToggleSettingsModalPayload { } export const toggleSettingsModalAction = - createSingleArtifactAction((state, action) => { + createArtifactAction((state, action) => { const { open, tab } = action.payload; state.ui.settingsModalOpen = open; @@ -77,29 +76,28 @@ interface ToggleAutocommitDisableModalPayload { } export const toggleAutocommitDisableModalAction = - createSingleArtifactAction( - (state, action) => { - const { open } = action.payload; + createArtifactAction((state, action) => { + const { open } = action.payload; - state.ui.autocommitDisableModalOpen = open; + state.ui.autocommitDisableModalOpen = open; - return state; - }, - ); + return state; + }); // branch popup interface BranchPopupPayload { open: boolean; } -export const toggleBranchPopupAction = - createSingleArtifactAction((state, action) => { +export const toggleBranchPopupAction = createArtifactAction( + (state, action) => { const { open } = action.payload; state.ui.branchPopupOpen = open; return state; - }); + }, +); // error modals interface ToggleRepoLimitModalPayload { @@ -107,7 +105,7 @@ interface ToggleRepoLimitModalPayload { } export const toggleRepoLimitErrorModalAction = - createSingleArtifactAction((state, action) => { + createArtifactAction((state, action) => { const { open } = action.payload; state.ui.repoLimitErrorModalOpen = open; @@ -120,12 +118,10 @@ interface ToggleConflictErrorModalPayload { } export const toggleConflictErrorModalAction = - createSingleArtifactAction( - (state, action) => { - const { open } = action.payload; + createArtifactAction((state, action) => { + const { open } = action.payload; - state.ui.conflictErrorModalOpen = open; + state.ui.conflictErrorModalOpen = open; - return state; - }, - ); + return state; + }); diff --git a/app/client/src/git/store/actions/updateLocalProfileActions.ts b/app/client/src/git/store/actions/updateLocalProfileActions.ts index 717bb388cb9b..84ac561a5026 100644 --- a/app/client/src/git/store/actions/updateLocalProfileActions.ts +++ b/app/client/src/git/store/actions/updateLocalProfileActions.ts @@ -1,4 +1,4 @@ -import { createSingleArtifactAction } from "../helpers/createSingleArtifactAction"; +import { createArtifactAction } from "../helpers/createArtifactAction"; import type { GitAsyncErrorPayload } from "../types"; import type { UpdateLocalProfileRequestParams } from "git/requests/updateLocalProfileRequest.types"; @@ -6,23 +6,21 @@ export interface UpdateLocalProfileInitPayload extends UpdateLocalProfileRequestParams {} export const updateLocalProfileInitAction = - createSingleArtifactAction((state) => { + createArtifactAction((state) => { state.apiResponses.updateLocalProfile.loading = true; state.apiResponses.updateLocalProfile.error = null; return state; }); -export const updateLocalProfileSuccessAction = createSingleArtifactAction( - (state) => { - state.apiResponses.updateLocalProfile.loading = false; +export const updateLocalProfileSuccessAction = createArtifactAction((state) => { + state.apiResponses.updateLocalProfile.loading = false; - return state; - }, -); + return state; +}); export const updateLocalProfileErrorAction = - createSingleArtifactAction((state, action) => { + createArtifactAction((state, action) => { const { error } = action.payload; state.apiResponses.updateLocalProfile.loading = false; diff --git a/app/client/src/git/store/actions/updateProtectedBranchesActions.ts b/app/client/src/git/store/actions/updateProtectedBranchesActions.ts index 6e45bf0dcca5..a19926b673f9 100644 --- a/app/client/src/git/store/actions/updateProtectedBranchesActions.ts +++ b/app/client/src/git/store/actions/updateProtectedBranchesActions.ts @@ -1,19 +1,19 @@ import type { UpdateProtectedBranchesRequestParams } from "git/requests/updateProtectedBranchesRequest.types"; -import { createSingleArtifactAction } from "../helpers/createSingleArtifactAction"; +import { createArtifactAction } from "../helpers/createArtifactAction"; import type { GitArtifactErrorPayloadAction } from "../types"; export interface UpdateProtectedBranchesInitPayload extends UpdateProtectedBranchesRequestParams {} export const updateProtectedBranchesInitAction = - createSingleArtifactAction((state) => { + createArtifactAction((state) => { state.apiResponses.updateProtectedBranches.loading = true; state.apiResponses.updateProtectedBranches.error = null; return state; }); -export const updateProtectedBranchesSuccessAction = createSingleArtifactAction( +export const updateProtectedBranchesSuccessAction = createArtifactAction( (state) => { state.apiResponses.updateProtectedBranches.loading = false; @@ -21,7 +21,7 @@ export const updateProtectedBranchesSuccessAction = createSingleArtifactAction( }, ); -export const updateProtectedBranchesErrorAction = createSingleArtifactAction( +export const updateProtectedBranchesErrorAction = createArtifactAction( (state, action: GitArtifactErrorPayloadAction) => { const { error } = action.payload; diff --git a/app/client/src/git/store/gitArtifactSlice.ts b/app/client/src/git/store/gitArtifactSlice.ts index 924785f80c76..cd526c5eebf4 100644 --- a/app/client/src/git/store/gitArtifactSlice.ts +++ b/app/client/src/git/store/gitArtifactSlice.ts @@ -1,5 +1,5 @@ import { createSlice } from "@reduxjs/toolkit"; -import type { GitArtifactReduxState } from "./types"; +import type { GitArtifactRootReduxState } from "./types"; import { mountAction, unmountAction } from "./actions/mountActions"; import { connectErrorAction, @@ -137,7 +137,7 @@ import { resetGenerateSSHKeyAction, } from "./actions/generateSSHKeyActions"; -const initialState: GitArtifactReduxState = {}; +const initialState: GitArtifactRootReduxState = {}; export const gitArtifactSlice = createSlice({ name: "git/artifact", diff --git a/app/client/src/git/store/helpers/createArtifactAction.ts b/app/client/src/git/store/helpers/createArtifactAction.ts new file mode 100644 index 000000000000..c138af710d53 --- /dev/null +++ b/app/client/src/git/store/helpers/createArtifactAction.ts @@ -0,0 +1,35 @@ +import type { + GitArtifactBasePayload, + GitArtifactPayloadAction, + GitArtifactReduxState, + GitArtifactRootReduxState, +} from "../types"; +import { gitArtifactInitialState } from "./initialState"; + +type ArtifactStateCb = ( + artifactState: GitArtifactReduxState, + action: GitArtifactPayloadAction, +) => GitArtifactReduxState; + +export const createArtifactAction = ( + artifactStateCb: ArtifactStateCb, +) => { + return ( + state: GitArtifactRootReduxState, + action: GitArtifactPayloadAction, + ) => { + const { artifactType, baseArtifactId } = action.payload.artifactDef; + + state[artifactType] ??= {}; + state[artifactType][baseArtifactId] ??= gitArtifactInitialState; + + const artifactState = state[artifactType][baseArtifactId]; + + state[artifactType][baseArtifactId] = artifactStateCb( + artifactState, + action, + ); + + return state; + }; +}; diff --git a/app/client/src/git/store/helpers/createSingleArtifactAction.ts b/app/client/src/git/store/helpers/createSingleArtifactAction.ts deleted file mode 100644 index 5d11065340ac..000000000000 --- a/app/client/src/git/store/helpers/createSingleArtifactAction.ts +++ /dev/null @@ -1,35 +0,0 @@ -import type { - GitArtifactBasePayload, - GitArtifactPayloadAction, - GitArtifactReduxState, - GitSingleArtifactReduxState, -} from "../types"; -import { gitSingleArtifactInitialState } from "./gitSingleArtifactInitialState"; - -type SingleArtifactStateCb = ( - singleArtifactState: GitSingleArtifactReduxState, - action: GitArtifactPayloadAction, -) => GitSingleArtifactReduxState; - -export const createSingleArtifactAction = ( - singleArtifactStateCb: SingleArtifactStateCb, -) => { - return ( - state: GitArtifactReduxState, - action: GitArtifactPayloadAction, - ) => { - const { artifactType, baseArtifactId } = action.payload.artifactDef; - - state[artifactType] ??= {}; - state[artifactType][baseArtifactId] ??= gitSingleArtifactInitialState; - - const singleArtifactState = state[artifactType][baseArtifactId]; - - state[artifactType][baseArtifactId] = singleArtifactStateCb( - singleArtifactState, - action, - ); - - return state; - }; -}; diff --git a/app/client/src/git/store/helpers/gitSingleArtifactInitialState.ts b/app/client/src/git/store/helpers/gitSingleArtifactInitialState.ts deleted file mode 100644 index b17c93a126cb..000000000000 --- a/app/client/src/git/store/helpers/gitSingleArtifactInitialState.ts +++ /dev/null @@ -1,138 +0,0 @@ -import { - gitArtifactAPIResponsesInitialState as gitArtifactAPIResponsesInitialStateExtended, - gitArtifactUIInitialState as gitArtifactUIInitialStateExtended, -} from "git/ee/store/helpers/initialState"; -import { GitOpsTab, GitSettingsTab } from "../../constants/enums"; -import type { - GitSingleArtifactAPIResponsesReduxState, - GitSingleArtifactUIReduxState, - GitSingleArtifactReduxState, -} from "../types"; - -const gitSingleArtifactInitialUIState: GitSingleArtifactUIReduxState = { - connectModalOpen: false, - disconnectBaseArtifactId: null, - disconnectArtifactName: null, - branchPopupOpen: false, - checkoutDestBranch: null, - opsModalOpen: false, - opsModalTab: GitOpsTab.Deploy, - settingsModalOpen: false, - settingsModalTab: GitSettingsTab.General, - autocommitDisableModalOpen: false, - autocommitPolling: false, - conflictErrorModalOpen: false, - repoLimitErrorModalOpen: false, - // EE - ...gitArtifactUIInitialStateExtended, -}; - -const gitSingleArtifactInitialAPIResponses: GitSingleArtifactAPIResponsesReduxState = - { - metadata: { - value: null, - loading: false, - error: null, - }, - connect: { - loading: false, - error: null, - }, - gitImport: { - loading: false, - error: null, - }, - status: { - value: null, - loading: false, - error: null, - }, - commit: { - loading: false, - error: null, - }, - pull: { - loading: false, - error: null, - }, - discard: { - loading: false, - error: null, - }, - mergeStatus: { - value: null, - loading: false, - error: null, - }, - merge: { - loading: false, - error: null, - }, - branches: { - value: null, - loading: false, - error: null, - }, - checkoutBranch: { - loading: false, - error: null, - }, - createBranch: { - loading: false, - error: null, - }, - deleteBranch: { - loading: false, - error: null, - }, - localProfile: { - value: null, - loading: false, - error: null, - }, - updateLocalProfile: { - loading: false, - error: null, - }, - disconnect: { - loading: false, - error: null, - }, - protectedBranches: { - value: null, - loading: false, - error: null, - }, - updateProtectedBranches: { - loading: false, - error: null, - }, - autocommitProgress: { - loading: false, - error: null, - }, - toggleAutocommit: { - loading: false, - error: null, - }, - triggerAutocommit: { - loading: false, - error: null, - }, - generateSSHKey: { - loading: false, - error: null, - }, - sshKey: { - value: null, - loading: false, - error: null, - }, - // EE - ...gitArtifactAPIResponsesInitialStateExtended, - }; - -export const gitSingleArtifactInitialState: GitSingleArtifactReduxState = { - ui: gitSingleArtifactInitialUIState, - apiResponses: gitSingleArtifactInitialAPIResponses, -}; diff --git a/app/client/src/git/store/helpers/initialState.ts b/app/client/src/git/store/helpers/initialState.ts new file mode 100644 index 000000000000..81d09151037a --- /dev/null +++ b/app/client/src/git/store/helpers/initialState.ts @@ -0,0 +1,137 @@ +import { + gitArtifactAPIResponsesInitialState as gitArtifactAPIResponsesInitialStateExtended, + gitArtifactUIInitialState as gitArtifactUIInitialStateExtended, +} from "git/ee/store/helpers/initialState"; +import { GitOpsTab, GitSettingsTab } from "../../constants/enums"; +import type { + GitArtifactAPIResponsesReduxState, + GitArtifactUIReduxState, + GitArtifactReduxState, +} from "../types"; + +const gitArtifactInitialUIState: GitArtifactUIReduxState = { + connectModalOpen: false, + disconnectBaseArtifactId: null, + disconnectArtifactName: null, + branchPopupOpen: false, + checkoutDestBranch: null, + opsModalOpen: false, + opsModalTab: GitOpsTab.Deploy, + settingsModalOpen: false, + settingsModalTab: GitSettingsTab.General, + autocommitDisableModalOpen: false, + autocommitPolling: false, + conflictErrorModalOpen: false, + repoLimitErrorModalOpen: false, + // EE + ...gitArtifactUIInitialStateExtended, +}; + +const gitArtifactInitialAPIResponses: GitArtifactAPIResponsesReduxState = { + metadata: { + value: null, + loading: false, + error: null, + }, + connect: { + loading: false, + error: null, + }, + gitImport: { + loading: false, + error: null, + }, + status: { + value: null, + loading: false, + error: null, + }, + commit: { + loading: false, + error: null, + }, + pull: { + loading: false, + error: null, + }, + discard: { + loading: false, + error: null, + }, + mergeStatus: { + value: null, + loading: false, + error: null, + }, + merge: { + loading: false, + error: null, + }, + branches: { + value: null, + loading: false, + error: null, + }, + checkoutBranch: { + loading: false, + error: null, + }, + createBranch: { + loading: false, + error: null, + }, + deleteBranch: { + loading: false, + error: null, + }, + localProfile: { + value: null, + loading: false, + error: null, + }, + updateLocalProfile: { + loading: false, + error: null, + }, + disconnect: { + loading: false, + error: null, + }, + protectedBranches: { + value: null, + loading: false, + error: null, + }, + updateProtectedBranches: { + loading: false, + error: null, + }, + autocommitProgress: { + loading: false, + error: null, + }, + toggleAutocommit: { + loading: false, + error: null, + }, + triggerAutocommit: { + loading: false, + error: null, + }, + generateSSHKey: { + loading: false, + error: null, + }, + sshKey: { + value: null, + loading: false, + error: null, + }, + // EE + ...gitArtifactAPIResponsesInitialStateExtended, +}; + +export const gitArtifactInitialState: GitArtifactReduxState = { + ui: gitArtifactInitialUIState, + apiResponses: gitArtifactInitialAPIResponses, +}; diff --git a/app/client/src/git/store/index.ts b/app/client/src/git/store/index.ts index f5337e564f97..21fb06e112af 100644 --- a/app/client/src/git/store/index.ts +++ b/app/client/src/git/store/index.ts @@ -4,5 +4,5 @@ import { gitConfigReducer } from "./gitConfigSlice"; export const gitReducer = combineReducers({ artifacts: gitArtifactReducer, - config: gitConfigReducer, + global: gitConfigReducer, }); diff --git a/app/client/src/git/store/selectors/gitSingleArtifactSelectors.ts b/app/client/src/git/store/selectors/gitArtifactSelectors.ts similarity index 97% rename from app/client/src/git/store/selectors/gitSingleArtifactSelectors.ts rename to app/client/src/git/store/selectors/gitArtifactSelectors.ts index c651aa2c8c13..261663a9bb36 100644 --- a/app/client/src/git/store/selectors/gitSingleArtifactSelectors.ts +++ b/app/client/src/git/store/selectors/gitArtifactSelectors.ts @@ -1,10 +1,4 @@ -import type { GitArtifactType } from "git/constants/enums"; -import type { GitRootState } from "../types"; - -export interface GitArtifactDef { - artifactType: keyof typeof GitArtifactType; - baseArtifactId: string; -} +import type { GitArtifactDef, GitRootState } from "../types"; export const selectGitArtifact = ( state: GitRootState, diff --git a/app/client/src/git/store/selectors/gitConfigSelectors.ts b/app/client/src/git/store/selectors/gitGlobalSelectors.ts similarity index 92% rename from app/client/src/git/store/selectors/gitConfigSelectors.ts rename to app/client/src/git/store/selectors/gitGlobalSelectors.ts index be31a23cda5e..cc444e9634ae 100644 --- a/app/client/src/git/store/selectors/gitConfigSelectors.ts +++ b/app/client/src/git/store/selectors/gitGlobalSelectors.ts @@ -1,7 +1,7 @@ import type { GitRootState } from "../types"; export const selectGitConfig = (state: GitRootState) => { - return state.git.config; + return state.git.global; }; // global profile diff --git a/app/client/src/git/store/types.ts b/app/client/src/git/store/types.ts index 37554eacfd02..ca9e478dcb22 100644 --- a/app/client/src/git/store/types.ts +++ b/app/client/src/git/store/types.ts @@ -1,5 +1,9 @@ import type { PayloadAction } from "@reduxjs/toolkit"; -import type { GitOpsTab, GitSettingsTab } from "../constants/enums"; +import type { + GitArtifactType, + GitOpsTab, + GitSettingsTab, +} from "../constants/enums"; import type { FetchGlobalProfileResponseData } from "../requests/fetchGlobalProfileRequest.types"; import type { FetchBranchesResponseData } from "../requests/fetchBranchesRequest.types"; import type { FetchLocalProfileResponseData } from "../requests/fetchLocalProfileRequest.types"; @@ -13,7 +17,6 @@ import type { GitArtifactAPIResponsesReduxState as GitArtifactAPIResponsesReduxStateExtended, GitArtifactUIReduxState as GitArtifactUIReduxStateExtended, } from "git/ee/store/types"; -import type { GitArtifactDef } from "./selectors/gitSingleArtifactSelectors"; export interface GitApiError extends ApiResponseError { errorType?: string; @@ -30,7 +33,7 @@ export interface GitAsyncStateWithoutValue { loading: boolean; error: GitApiError | null; } -export interface GitSingleArtifactAPIResponsesReduxState +export interface GitArtifactAPIResponsesReduxState extends GitArtifactAPIResponsesReduxStateExtended { metadata: GitAsyncState; connect: GitAsyncStateWithoutValue; @@ -57,7 +60,7 @@ export interface GitSingleArtifactAPIResponsesReduxState generateSSHKey: GitAsyncStateWithoutValue; } -export interface GitSingleArtifactUIReduxState +export interface GitArtifactUIReduxState extends GitArtifactUIReduxStateExtended { connectModalOpen: boolean; disconnectBaseArtifactId: string | null; @@ -73,13 +76,14 @@ export interface GitSingleArtifactUIReduxState conflictErrorModalOpen: boolean; repoLimitErrorModalOpen: boolean; } -export interface GitSingleArtifactReduxState { - ui: GitSingleArtifactUIReduxState; - apiResponses: GitSingleArtifactAPIResponsesReduxState; -} +export interface GitArtifactDef { + artifactType: keyof typeof GitArtifactType; + baseArtifactId: string; +} export interface GitArtifactReduxState { - [key: string]: Record; + ui: GitArtifactUIReduxState; + apiResponses: GitArtifactAPIResponsesReduxState; } export interface GitConfigReduxState { @@ -87,6 +91,16 @@ export interface GitConfigReduxState { updateGlobalProfile: GitAsyncStateWithoutValue; } +export type GitArtifactRootReduxState = Record< + string, + Record +>; + +export interface GitReduxState { + artifacts: GitArtifactRootReduxState; + global: GitConfigReduxState; +} + export interface GitRootState { // will have to remove this later, once metadata is fixed ui: { @@ -98,10 +112,7 @@ export interface GitRootState { }; }; }; - git: { - artifacts: GitArtifactReduxState; - config: GitConfigReduxState; - }; + git: GitReduxState; } export interface GitArtifactBasePayload { diff --git a/app/client/src/selectors/gitModSelectors.ts b/app/client/src/selectors/gitModSelectors.ts index 05d4eafefd90..dfd25de98870 100644 --- a/app/client/src/selectors/gitModSelectors.ts +++ b/app/client/src/selectors/gitModSelectors.ts @@ -1,13 +1,13 @@ // temp file will be removed after git mod is fully rolled out import { selectFeatureFlags } from "ee/selectors/featureFlagsSelectors"; -import type { GitArtifactDef } from "git/store/selectors/gitSingleArtifactSelectors"; import { createSelector } from "reselect"; import { getCurrentGitBranch, protectedModeSelector } from "./gitSyncSelectors"; import type { AppState } from "ee/reducers"; import { selectGitCurrentBranch as selectGitCurrentBranchNew, selectGitProtectedMode as selectGitProtectedModeNew, + type GitArtifactDef, } from "git"; export const selectGitModEnabled = createSelector( From bc06f262d802123017f02dfe51cb1dee00299962 Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Tue, 24 Dec 2024 01:15:25 +0530 Subject: [PATCH 086/143] chore: fixing connect and import flow --- .../src/ce/pages/Applications/index.tsx | 16 +- app/client/src/ce/reducers/index.tsx | 4 +- .../ConnectInitialize/AddDeployKey.test.tsx | 231 ------------------ .../ConnectInitialize/AddDeployKey.tsx | 100 ++++---- .../ChooseGitProvider.test.tsx | 11 +- .../ConnectInitialize/ChooseGitProvider.tsx | 32 +-- .../ConnectInitialize/GenerateSSH.test.tsx | 6 +- .../ConnectInitialize/GenerateSSH.tsx | 10 +- .../ConnectInitialize/index.test.tsx | 32 +-- .../ConnectModal/ConnectInitialize/index.tsx | 126 ++++------ .../ConnectModal/ConnectModalView.tsx | 82 ++----- .../src/git/components/ConnectModal/index.tsx | 92 +++---- .../ConnectSuccessView.tsx} | 20 +- .../git/components/ConnectSuccess/index.tsx | 28 +++ .../src/git/components/ImportModal/index.tsx | 58 ++++- app/client/src/git/hooks/useConnect.ts | 72 ++---- app/client/src/git/hooks/useGlobalProfile.ts | 6 +- app/client/src/git/hooks/useGlobalSSHKey.ts | 29 +++ app/client/src/git/hooks/useImport.ts | 38 +++ app/client/src/git/hooks/useSSHKey.ts | 63 +++++ app/client/src/git/index.ts | 2 +- .../git/requests/fetchGlobalSSHKeyRequest.ts | 15 ++ .../fetchGlobalSSHKeyRequest.types.ts | 15 ++ .../src/git/requests/generateSSHKeyRequest.ts | 8 +- .../requests/generateSSHKeyRequest.types.ts | 1 - .../git/requests/gitImportRequest.types.ts | 18 +- app/client/src/git/sagas/connectSaga.ts | 9 + .../src/git/sagas/fetchGlobalProfileSaga.ts | 6 +- .../src/git/sagas/fetchGlobalSSHKeySaga.ts | 44 ++++ .../src/git/sagas/generateSSHKeySaga.ts | 1 - app/client/src/git/sagas/gitImportSaga.ts | 92 +++++++ app/client/src/git/sagas/index.ts | 12 +- .../src/git/sagas/updateGlobalProfileSaga.ts | 8 +- .../actions/fetchGlobalProfileActions.ts | 8 +- .../store/actions/fetchGlobalSSHKeyActions.ts | 55 +++++ .../src/git/store/actions/gitImportActions.ts | 45 ++-- app/client/src/git/store/actions/uiActions.ts | 30 +++ .../actions/updateGlobalProfileActions.ts | 10 +- app/client/src/git/store/gitArtifactSlice.ts | 10 +- app/client/src/git/store/gitConfigSlice.ts | 29 --- app/client/src/git/store/gitGlobalSlice.ts | 49 ++++ .../store/helpers/gitConfigInitialState.ts | 13 - .../src/git/store/helpers/initialState.ts | 28 ++- app/client/src/git/store/index.ts | 4 +- .../store/selectors/gitArtifactSelectors.ts | 10 +- .../git/store/selectors/gitGlobalSelectors.ts | 15 +- app/client/src/git/store/types.ts | 11 +- 47 files changed, 878 insertions(+), 726 deletions(-) delete mode 100644 app/client/src/git/components/ConnectModal/ConnectInitialize/AddDeployKey.test.tsx rename app/client/src/git/components/{ConnectModal/ConnectSuccess/index.tsx => ConnectSuccess/ConnectSuccessView.tsx} (92%) create mode 100644 app/client/src/git/components/ConnectSuccess/index.tsx create mode 100644 app/client/src/git/hooks/useGlobalSSHKey.ts create mode 100644 app/client/src/git/hooks/useImport.ts create mode 100644 app/client/src/git/hooks/useSSHKey.ts create mode 100644 app/client/src/git/requests/fetchGlobalSSHKeyRequest.ts create mode 100644 app/client/src/git/requests/fetchGlobalSSHKeyRequest.types.ts create mode 100644 app/client/src/git/sagas/fetchGlobalSSHKeySaga.ts create mode 100644 app/client/src/git/sagas/gitImportSaga.ts create mode 100644 app/client/src/git/store/actions/fetchGlobalSSHKeyActions.ts delete mode 100644 app/client/src/git/store/gitConfigSlice.ts create mode 100644 app/client/src/git/store/gitGlobalSlice.ts delete mode 100644 app/client/src/git/store/helpers/gitConfigInitialState.ts diff --git a/app/client/src/ce/pages/Applications/index.tsx b/app/client/src/ce/pages/Applications/index.tsx index 3d215119a84b..6bd875fea98c 100644 --- a/app/client/src/ce/pages/Applications/index.tsx +++ b/app/client/src/ce/pages/Applications/index.tsx @@ -133,13 +133,21 @@ import { ASSETS_CDN_URL } from "constants/ThirdPartyConstants"; import { LayoutSystemTypes } from "layoutSystems/types"; import { getIsAnvilLayoutEnabled } from "layoutSystems/anvil/integrations/selectors"; import OldGitSyncModal from "pages/Editor/gitSync/GitSyncModal"; -import { GitImportModal as NewGitImportModal } from "git"; import { useGitModEnabled } from "pages/Editor/gitSync/hooks/modHooks"; +import { GitImportModal as NewGitImportModal } from "git"; -function GitImportModals() { +interface GitImportModalProps { + workspaceId: string; +} + +function GitImportModal({ workspaceId }: GitImportModalProps) { const isGitModEnabled = useGitModEnabled(); - return isGitModEnabled ? : ; + return isGitModEnabled ? ( + + ) : ( + + ); } export const { cloudHosting } = getAppsmithConfigs(); @@ -963,7 +971,7 @@ export function ApplicationsSection(props: any) { isMobile={isMobile} > {workspacesListComponent} - + ); diff --git a/app/client/src/ce/reducers/index.tsx b/app/client/src/ce/reducers/index.tsx index b48106fcda83..6238302b826a 100644 --- a/app/client/src/ce/reducers/index.tsx +++ b/app/client/src/ce/reducers/index.tsx @@ -78,7 +78,7 @@ import type { SelectedWorkspaceReduxState } from "ee/reducers/uiReducers/selecte import type { ConsolidatedPageLoadState } from "reducers/uiReducers/consolidatedPageLoadReducer"; import type { BuildingBlocksReduxState } from "reducers/uiReducers/buildingBlockReducer"; import { gitReducer } from "git"; -import type { GitArtifactRootReduxState, GitConfigReduxState } from "git"; +import type { GitArtifactRootReduxState, GitGlobalReduxState } from "git"; export const reducerObject = { entities: entityReducer, @@ -182,7 +182,7 @@ export interface AppState { // eslint-disable-next-line @typescript-eslint/no-explicit-any tenant: TenantReduxState; git: { - global: GitConfigReduxState; + global: GitGlobalReduxState; artifacts: GitArtifactRootReduxState; }; } diff --git a/app/client/src/git/components/ConnectModal/ConnectInitialize/AddDeployKey.test.tsx b/app/client/src/git/components/ConnectModal/ConnectInitialize/AddDeployKey.test.tsx deleted file mode 100644 index 176dc5247887..000000000000 --- a/app/client/src/git/components/ConnectModal/ConnectInitialize/AddDeployKey.test.tsx +++ /dev/null @@ -1,231 +0,0 @@ -import React from "react"; -import { render, screen, fireEvent, waitFor } from "@testing-library/react"; -import type { AddDeployKeyProps } from "./AddDeployKey"; -import AddDeployKey from "./AddDeployKey"; -import AnalyticsUtil from "ee/utils/AnalyticsUtil"; -import "@testing-library/jest-dom"; - -jest.mock("ee/utils/AnalyticsUtil", () => ({ - logEvent: jest.fn(), -})); - -jest.mock("copy-to-clipboard", () => ({ - __esModule: true, - default: () => true, -})); - -const DEFAULT_DOCS_URL = - "https://docs.appsmith.com/advanced-concepts/version-control-with-git/connecting-to-git-repository"; - -const defaultProps: AddDeployKeyProps = { - connectError: null, - isLoading: false, - onChange: jest.fn(), - value: { - gitProvider: "github", - isAddedDeployKey: false, - remoteUrl: "git@github.com:owner/repo.git", - }, - fetchSSHKey: jest.fn(), - generateSSHKey: jest.fn(), - isFetchSSHKeyLoading: false, - isGenerateSSHKeyLoading: false, - sshPublicKey: "ecdsa-sha2-nistp256 AAAAE2VjZHNhAAAIBaj...", -}; - -describe("AddDeployKey Component", () => { - beforeEach(() => { - jest.clearAllMocks(); - }); - - it("renders without crashing and shows default UI", () => { - render(); - expect( - screen.getByText("Add deploy key & give write access"), - ).toBeInTheDocument(); - expect(screen.getByRole("combobox")).toBeInTheDocument(); - // Should show ECDSA by default since sshKeyPair includes "ecdsa" - expect( - screen.getByText(defaultProps.sshPublicKey as string), - ).toBeInTheDocument(); - expect( - screen.getByText("I've added the deploy key and gave it write access"), - ).toBeInTheDocument(); - }); - - it("calls fetchSSHKey if modal is open and not importing", () => { - render(); - expect(defaultProps.fetchSSHKey).toHaveBeenCalledTimes(1); - }); - - it("does not call fetchSSHKey if importing", () => { - render(); - expect(defaultProps.fetchSSHKey).not.toHaveBeenCalled(); - }); - - it("shows dummy key loader if loading keys", () => { - render( - , - ); - // The actual key text should not be displayed - expect(screen.queryByText("ecdsa-sha2-nistp256")).not.toBeInTheDocument(); - }); - - it("changes SSH key type when user selects a different type and triggers generateSSHKey if needed", async () => { - const generateSSHKey = jest.fn(); - - render( - , - ); - - fireEvent.mouseDown(screen.getByRole("combobox")); - const rsaOption = screen.getByText("RSA 4096"); - - fireEvent.click(rsaOption); - - await waitFor(() => { - expect(generateSSHKey).toHaveBeenCalledWith("RSA", false); - }); - }); - - it("displays a generic error when errorData is provided and error code is not AE-GIT-4032 or AE-GIT-4033", () => { - // eslint-disable-next-line react-perf/jsx-no-new-object-as-prop - const connectError = { - code: "GENERIC-ERROR", - errorType: "Some Error", - message: "Something went wrong", - }; - - render(); - expect(screen.getByText("Some Error")).toBeInTheDocument(); - expect(screen.getByText("Something went wrong")).toBeInTheDocument(); - }); - - it("displays a misconfiguration error if error code is AE-GIT-4032", () => { - // eslint-disable-next-line react-perf/jsx-no-new-object-as-prop - const connectError = { - code: "AE-GIT-4032", - errorType: "SSH Key Error", - message: "SSH Key misconfiguration", - }; - - render(); - expect(screen.getByText("SSH key misconfiguration")).toBeInTheDocument(); - expect( - screen.getByText( - "It seems that your SSH key hasn't been added to your repository. To proceed, please revisit the steps below and configure your SSH key correctly.", - ), - ).toBeInTheDocument(); - }); - - it("invokes onChange callback when checkbox is toggled", () => { - const onChange = jest.fn(); - - render(); - const checkbox = screen.getByTestId("t--added-deploy-key-checkbox"); - - fireEvent.click(checkbox); - expect(onChange).toHaveBeenCalledWith({ isAddedDeployKey: true }); - }); - - it("calls AnalyticsUtil on copy button click", () => { - render(); - const copyButton = screen.getByTestId("t--copy-generic"); - - fireEvent.click(copyButton); - expect(AnalyticsUtil.logEvent).toHaveBeenCalledWith( - "GS_COPY_SSH_KEY_BUTTON_CLICK", - ); - }); - - it("hides copy button when connectLoading is true", () => { - render(); - expect(screen.queryByTestId("t--copy-generic")).not.toBeInTheDocument(); - }); - - it("shows repository settings link if gitProvider is known and not 'others'", () => { - render(); - const link = screen.getByRole("link", { name: "repository settings." }); - - expect(link).toHaveAttribute( - "href", - "https://github.com/owner/repo/settings/keys", - ); - }); - - it("does not show repository link if gitProvider = 'others'", () => { - render( - , - ); - expect( - screen.queryByRole("link", { name: "repository settings." }), - ).not.toBeInTheDocument(); - }); - - it("shows collapsible section if gitProvider is not 'others'", () => { - render( - , - ); - expect( - screen.getByText("How to paste SSH Key in repo and give write access?"), - ).toBeInTheDocument(); - expect(screen.getByAltText("Add deploy key in gitlab")).toBeInTheDocument(); - }); - - it("does not display collapsible if gitProvider = 'others'", () => { - render( - , - ); - expect( - screen.queryByText("How to paste SSH Key in repo and give write access?"), - ).not.toBeInTheDocument(); - }); - - it("uses default documentation link if none provided", () => { - render(); - const docsLink = screen.getByRole("link", { name: "Read Docs" }); - - expect(docsLink).toHaveAttribute("href", DEFAULT_DOCS_URL); - }); - - it("generates SSH key if none is present and conditions are met", async () => { - const fetchSSHKey = jest.fn(); - const generateSSHKey = jest.fn(); - - render( - , - ); - - expect(fetchSSHKey).toHaveBeenCalledTimes(1); - - await waitFor(() => { - expect(generateSSHKey).toHaveBeenCalledWith("ECDSA", false); - }); - }); -}); diff --git a/app/client/src/git/components/ConnectModal/ConnectInitialize/AddDeployKey.tsx b/app/client/src/git/components/ConnectModal/ConnectInitialize/AddDeployKey.tsx index 75a4a7a50e86..09dcb7df1122 100644 --- a/app/client/src/git/components/ConnectModal/ConnectInitialize/AddDeployKey.tsx +++ b/app/client/src/git/components/ConnectModal/ConnectInitialize/AddDeployKey.tsx @@ -135,93 +135,83 @@ const DEPLOY_DOCS_URL = "https://docs.appsmith.com/advanced-concepts/version-control-with-git/connecting-to-git-repository"; export interface AddDeployKeyProps { - connectError: GitApiError | null; - fetchSSHKey: () => void; - generateSSHKey: (keyType: string, isImport?: boolean) => void; - isFetchSSHKeyLoading: boolean; - isGenerateSSHKeyLoading: boolean; - isImport?: boolean; - isLoading: boolean; + error: GitApiError | null; + isSubmitLoading: boolean; + isSSHKeyLoading: boolean; onChange: (args: Partial) => void; + onFetchSSHKey?: () => void; + onGenerateSSHKey: (keyType: string) => void; sshPublicKey: string | null; value: Partial | null; } function AddDeployKey({ - connectError = null, - fetchSSHKey = noop, - generateSSHKey = noop, - isFetchSSHKeyLoading = false, - isGenerateSSHKeyLoading = false, - isImport = false, - isLoading = false, + error = null, + isSSHKeyLoading = false, + isSubmitLoading = false, onChange = noop, + onFetchSSHKey = noop, + onGenerateSSHKey = noop, sshPublicKey = null, value = null, }: AddDeployKeyProps) { const [fetched, setFetched] = useState(false); - const [sshKeyType, setSshKeyType] = useState(); + const [keyType, setKeyType] = useState(); useEffect( function fetchKeyPairOnInitEffect() { - if (!isImport) { - if (!fetched) { - fetchSSHKey(); - setFetched(true); - // doesn't support callback anymore - // fetchSSHKey({ - // onSuccessCallback: () => { - // setFetched(true); - // }, - // onErrorCallback: () => { - // setFetched(true); - // }, - // }); - } - } else { - if (!fetched) { - setFetched(true); - } + if (!fetched) { + onFetchSSHKey(); + setFetched(true); + // doesn't support callback anymore + // fetchSSHKey({ + // onSuccessCallback: () => { + // setFetched(true); + // }, + // onErrorCallback: () => { + // setFetched(true); + // }, + // }); } }, - [isImport, fetched, fetchSSHKey], + [fetched, onFetchSSHKey], ); useEffect( function setSSHKeyTypeonInitEffect() { - if (fetched && !isFetchSSHKeyLoading) { + if (fetched && !isSSHKeyLoading) { if (sshPublicKey && sshPublicKey.includes("rsa")) { - setSshKeyType("RSA"); + setKeyType("RSA"); } else if ( !sshPublicKey && value?.remoteUrl && value.remoteUrl.toString().toLocaleLowerCase().includes("azure") ) { - setSshKeyType("RSA"); + setKeyType("RSA"); } else { - setSshKeyType("ECDSA"); + setKeyType("ECDSA"); } } }, - [fetched, sshPublicKey, isFetchSSHKeyLoading, value?.remoteUrl], + [fetched, sshPublicKey, value?.remoteUrl, isSSHKeyLoading], ); useEffect( function generateSSHOnInitEffect() { if ( - (sshKeyType && !sshPublicKey) || - (sshKeyType && !sshPublicKey?.includes(sshKeyType.toLowerCase())) + (keyType && !sshPublicKey) || + (keyType && !sshPublicKey?.includes(keyType.toLowerCase())) ) { - generateSSHKey(sshKeyType, isImport); + onGenerateSSHKey(keyType); // doesn't support callback anymore - // generateSSHKey(sshKeyType, { + // generateSSHKey(keyType, { // onSuccessCallback: () => { // toast.show("SSH Key generated successfully", { kind: "success" }); // }, // }); } }, - [sshKeyType, sshPublicKey, generateSSHKey, isImport], + [keyType, sshPublicKey, onGenerateSSHKey], ); const repositorySettingsUrl = getRepositorySettingsUrl( @@ -229,7 +219,7 @@ function AddDeployKey({ value?.remoteUrl, ); - const loading = isFetchSSHKeyLoading || isGenerateSSHKeyLoading; + // const loading = isFetchSSHKeyLoading || isGenerateSSHKeyLoading; const onCopy = useCallback(() => { AnalyticsUtil.logEvent("GS_COPY_SSH_KEY_BUTTON_CLICK"); @@ -244,19 +234,19 @@ function AddDeployKey({ return ( <> - {connectError && - connectError.code !== "AE-GIT-4033" && - connectError.code !== "AE-GIT-4032" && ( + {error && + error.code !== "AE-GIT-4033" && + error.code !== "AE-GIT-4032" && ( - {connectError.errorType} + {error.errorType} - {connectError.message} + {error.message} )} {/* hardcoding message because server doesn't support feature flag. Will change this later */} - {connectError && connectError.code === "AE-GIT-4032" && ( + {error && error.code === "AE-GIT-4032" && ( {createMessage(ERROR_SSH_KEY_MISCONF_TITLE)} @@ -301,20 +291,20 @@ function AddDeployKey({ Now, give write access to it. - + - {!loading ? ( + {!isSSHKeyLoading ? ( - {sshKeyType} + {keyType} {sshPublicKey} - {!isLoading && ( + {!isSubmitLoading && ( { @@ -169,19 +168,19 @@ describe("ChooseGitProvider Component", () => { }); it("clicking on 'Import via git' link calls onImportFromCalloutLinkClick", () => { - const mockSetImportWorkspaceId = jest.fn(); + const onOpenImport = jest.fn(); render( , ); fireEvent.click(screen.getByText("Import via git")); - expect(mockSetImportWorkspaceId).toHaveBeenCalledTimes(1); + expect(onOpenImport).toHaveBeenCalledTimes(1); }); it("when isImport = true, shows a checkbox for existing repo", () => { @@ -218,7 +217,7 @@ describe("ChooseGitProvider Component", () => { render( , ); diff --git a/app/client/src/git/components/ConnectModal/ConnectInitialize/ChooseGitProvider.tsx b/app/client/src/git/components/ConnectModal/ConnectInitialize/ChooseGitProvider.tsx index d24c31de20de..b8aceed5baf4 100644 --- a/app/client/src/git/components/ConnectModal/ConnectInitialize/ChooseGitProvider.tsx +++ b/app/client/src/git/components/ConnectModal/ConnectInitialize/ChooseGitProvider.tsx @@ -34,9 +34,7 @@ import { } from "ee/constants/messages"; import log from "loglevel"; import type { ConnectFormDataState } from "./types"; -import history from "utils/history"; import { useIsMobileDevice } from "utils/hooks/useDeviceDetect"; -import AnalyticsUtil from "ee/utils/AnalyticsUtil"; const WellInnerContainer = styled.div` padding-left: 16px; @@ -53,21 +51,17 @@ export type GitProvider = (typeof GIT_PROVIDERS)[number]; interface ChooseGitProviderProps { artifactType: string; - isCreateArtifactPermitted: boolean; isImport?: boolean; onChange: (args: Partial) => void; - setImportWorkspaceId: () => void; - toggleConnectModal: (open: boolean) => void; + onOpenImport: (() => void) | null; value: Partial; } function ChooseGitProvider({ artifactType, - isCreateArtifactPermitted, isImport = false, onChange = noop, - setImportWorkspaceId = noop, - toggleConnectModal = noop, + onOpenImport = null, value = {}, }: ChooseGitProviderProps) { const isMobile = useIsMobileDevice(); @@ -97,19 +91,19 @@ function ChooseGitProvider({ [onChange], ); - const handleClickOnImport = useCallback(() => { - toggleConnectModal(false); - history.push("/applications"); - setImportWorkspaceId(); - toggleConnectModal(true); - AnalyticsUtil.logEvent("GS_IMPORT_VIA_GIT_DURING_GC"); - }, [setImportWorkspaceId, toggleConnectModal]); + // const handleClickOnImport = useCallback(() => { + // toggleConnectModal(false); + // history.push("/applications"); + // setImportWorkspaceId(); + // toggleConnectModal(true); + // AnalyticsUtil.logEvent("GS_IMPORT_VIA_GIT_DURING_GC"); + // }, [setImportWorkspaceId, toggleConnectModal]); const importCalloutLinks = useMemo(() => { - return !isMobile && isCreateArtifactPermitted - ? [{ children: "Import via git", onClick: handleClickOnImport }] + return !isMobile && onOpenImport && typeof onOpenImport === "function" + ? [{ children: "Import via git", onClick: onOpenImport }] : []; - }, [handleClickOnImport, isCreateArtifactPermitted, isMobile]); + }, [onOpenImport, isMobile]); return ( <> @@ -208,7 +202,7 @@ function ChooseGitProvider({ )} - {!isImport && value?.gitEmptyRepoExists === "no" ? ( + {!isImport && onOpenImport && value?.gitEmptyRepoExists === "no" ? ( {createMessage(IMPORT_ARTIFACT_IF_NOT_EMPTY, artifactType)} diff --git a/app/client/src/git/components/ConnectModal/ConnectInitialize/GenerateSSH.test.tsx b/app/client/src/git/components/ConnectModal/ConnectInitialize/GenerateSSH.test.tsx index d082ee44546d..fc53b8531a4f 100644 --- a/app/client/src/git/components/ConnectModal/ConnectInitialize/GenerateSSH.test.tsx +++ b/app/client/src/git/components/ConnectModal/ConnectInitialize/GenerateSSH.test.tsx @@ -16,7 +16,7 @@ const defaultProps = { gitProvider: "github" as GitProvider, remoteUrl: "", }, - connectError: null, + error: null, }; describe("GenerateSSH Component", () => { @@ -38,7 +38,7 @@ describe("GenerateSSH Component", () => { code: "AE-GIT-4033", }; - render(); + render(); expect( screen.getByText("The repo you added isn't empty"), ).toBeInTheDocument(); @@ -55,7 +55,7 @@ describe("GenerateSSH Component", () => { code: "SOME_OTHER_ERROR", }; - render(); + render(); expect( screen.queryByText("The repo you added isn't empty"), ).not.toBeInTheDocument(); diff --git a/app/client/src/git/components/ConnectModal/ConnectInitialize/GenerateSSH.tsx b/app/client/src/git/components/ConnectModal/ConnectInitialize/GenerateSSH.tsx index 5318b0bd8554..6a8b7536f903 100644 --- a/app/client/src/git/components/ConnectModal/ConnectInitialize/GenerateSSH.tsx +++ b/app/client/src/git/components/ConnectModal/ConnectInitialize/GenerateSSH.tsx @@ -41,17 +41,13 @@ interface GenerateSSHState { interface GenerateSSHProps { onChange: (args: Partial) => void; value: Partial; - connectError: GitApiError | null; + error: GitApiError | null; } const CONNECTING_TO_GIT_DOCS_URL = "https://docs.appsmith.com/advanced-concepts/version-control-with-git/connecting-to-git-repository"; -function GenerateSSH({ - connectError, - onChange = noop, - value = {}, -}: GenerateSSHProps) { +function GenerateSSH({ error, onChange = noop, value = {} }: GenerateSSHProps) { const [isTouched, setIsTouched] = useState(false); const isInvalid = isTouched && @@ -69,7 +65,7 @@ function GenerateSSH({ return ( <> {/* hardcoding messages because server doesn't support feature flag. Will change this later */} - {connectError && connectError?.code === "AE-GIT-4033" && ( + {error && error?.code === "AE-GIT-4033" && ( {createMessage(ERROR_REPO_NOT_EMPTY_TITLE)} diff --git a/app/client/src/git/components/ConnectModal/ConnectInitialize/index.test.tsx b/app/client/src/git/components/ConnectModal/ConnectInitialize/index.test.tsx index 6ac8b83b0761..21f46cf03525 100644 --- a/app/client/src/git/components/ConnectModal/ConnectInitialize/index.test.tsx +++ b/app/client/src/git/components/ConnectModal/ConnectInitialize/index.test.tsx @@ -21,19 +21,15 @@ jest.mock("@appsmith/ads", () => ({ const defaultProps = { artifactType: "Application", - connect: jest.fn(), - connectError: null, - fetchSSHKey: jest.fn(), - generateSSHKey: jest.fn(), - gitImport: jest.fn(), - isConnectLoading: false, - isFetchSSHKeyLoading: false, - isGenerateSSHKeyLoading: false, - isGitImportLoading: false, + error: null, + onFetchSSHKey: jest.fn(), + onGenerateSSHKey: jest.fn(), + isSubmitLoading: false, + isSSHKeyLoading: false, isImport: false, + onSubmit: jest.fn(), + onOpenImport: null, sshPublicKey: "ssh-rsa AAAAB3...", - isCreateArtifactPermitted: true, - setImportWorkspaceId: jest.fn(), toggleConnectModal: jest.fn(), }; @@ -126,7 +122,7 @@ describe("ConnectModal Component", () => { completeAddDeployKeyStep(); await waitFor(() => { - expect(defaultProps.connect).toHaveBeenCalledWith( + expect(defaultProps.onSubmit).toHaveBeenCalledWith( expect.objectContaining({ remoteUrl: "git@example.com:user/repo.git", gitProfile: { @@ -139,14 +135,14 @@ describe("ConnectModal Component", () => { }); }); - it("calls gitImport on completing AddDeployKey step in import mode", async () => { + it("calls onSubmit on completing AddDeployKey step in import mode", async () => { render(); completeChooseProviderStep(true); completeGenerateSSHKeyStep(); completeAddDeployKeyStep(); await waitFor(() => { - expect(defaultProps.gitImport).toHaveBeenCalledWith( + expect(defaultProps.onSubmit).toHaveBeenCalledWith( expect.objectContaining({ remoteUrl: "git@example.com:user/repo.git", gitProfile: { @@ -167,13 +163,11 @@ describe("ConnectModal Component", () => { message: "", }; - rerender( - , - ); + rerender(); }); const { rerender } = render( - , + , ); completeChooseProviderStep(); @@ -216,7 +210,7 @@ describe("ConnectModal Component", () => { }); it("renders loading state and removes buttons when connecting", () => { - render(); + render(); expect( screen.getByText("Please wait while we connect to Git..."), ).toBeInTheDocument(); diff --git a/app/client/src/git/components/ConnectModal/ConnectInitialize/index.tsx b/app/client/src/git/components/ConnectModal/ConnectInitialize/index.tsx index 05046d250d09..72ba9d797c1d 100644 --- a/app/client/src/git/components/ConnectModal/ConnectInitialize/index.tsx +++ b/app/client/src/git/components/ConnectModal/ConnectInitialize/index.tsx @@ -71,41 +71,31 @@ interface StyledModalFooterProps { loading?: boolean; } -interface ConnectModalViewProps { +export interface ConnectInitializeProps { artifactType: string; - connect: (params: ConnectRequestParams) => void; - connectError: GitApiError | null; - fetchSSHKey: () => void; - generateSSHKey: (keyType: string) => void; - gitImport: (params: GitImportRequestParams) => void; - isConnectLoading: boolean; - isCreateArtifactPermitted: boolean; - isFetchSSHKeyLoading: boolean; - isGenerateSSHKeyLoading: boolean; - isGitImportLoading: boolean; + error: GitApiError | null; isImport: boolean; - setImportWorkspaceId: () => void; + isSSHKeyLoading: boolean; + isSubmitLoading: boolean; + onFetchSSHKey: () => void; + onGenerateSSHKey: (keyType: string) => void; + onOpenImport: (() => void) | null; + onSubmit: (params: ConnectRequestParams | GitImportRequestParams) => void; sshPublicKey: string | null; - toggleConnectModal: (open: boolean) => void; } function ConnectInitialize({ artifactType, - connect = noop, - connectError = null, - fetchSSHKey = noop, - generateSSHKey = noop, - gitImport = noop, - isConnectLoading = false, - isCreateArtifactPermitted = false, - isFetchSSHKeyLoading = false, - isGenerateSSHKeyLoading = false, - isGitImportLoading = false, + error = null, isImport = false, - setImportWorkspaceId = noop, + isSSHKeyLoading = false, + isSubmitLoading = false, + onFetchSSHKey = noop, + onGenerateSSHKey = noop, + onOpenImport = null, + onSubmit = noop, sshPublicKey = null, - toggleConnectModal = noop, -}: ConnectModalViewProps) { +}: ConnectInitializeProps) { const nextStepText = { [GIT_CONNECT_STEPS.CHOOSE_PROVIDER]: createMessage(CONFIGURE_GIT), [GIT_CONNECT_STEPS.GENERATE_SSH_KEY]: createMessage(GENERATE_SSH_KEY_STEP), @@ -127,8 +117,8 @@ function ConnectInitialize({ GIT_CONNECT_STEPS.CHOOSE_PROVIDER, ); - const isLoading = - (!isImport && isConnectLoading) || (isImport && isGitImportLoading); + // const isSubmitLoading = + // (!isImport && isConnectLoading) || (isImport && isGitImportLoading); const currentIndex = steps.findIndex((s) => s.key === activeStep); @@ -181,43 +171,40 @@ function ConnectInitialize({ }; if (formData.remoteUrl) { - if (!isImport) { - AnalyticsUtil.logEvent( - "GS_CONNECT_BUTTON_ON_GIT_SYNC_MODAL_CLICK", - { repoUrl: formData?.remoteUrl, connectFlow: "v2" }, - ); - connect({ - remoteUrl: formData.remoteUrl, - gitProfile, - }); - } else { - gitImport({ - remoteUrl: formData.remoteUrl, - gitProfile, - }); - } + onSubmit({ + remoteUrl: formData.remoteUrl, + gitProfile, + }); + // if (!isImport) { + // AnalyticsUtil.logEvent( + // "GS_CONNECT_BUTTON_ON_GIT_SYNC_MODAL_CLICK", + // { repoUrl: formData?.remoteUrl, connectFlow: "v2" }, + // ); + // connect({ + // remoteUrl: formData.remoteUrl, + // gitProfile, + // }); + // } else { + // gitImport({ + // remoteUrl: formData.remoteUrl, + // gitProfile, + // }); + // } } break; } } } - }, [ - activeStep, - connect, - currentIndex, - formData.remoteUrl, - gitImport, - isImport, - ]); + }, [activeStep, currentIndex, formData.remoteUrl, onSubmit]); useEffect( function changeStepOnErrorEffect() { - if (connectError?.code === GitErrorCodes.REPO_NOT_EMPTY) { + if (error?.code === GitErrorCodes.REPO_NOT_EMPTY) { setActiveStep(GIT_CONNECT_STEPS.GENERATE_SSH_KEY); } }, - [connectError?.code], + [error?.code], ); return ( @@ -236,45 +223,38 @@ function ConnectInitialize({ {activeStep === GIT_CONNECT_STEPS.CHOOSE_PROVIDER && ( )} {activeStep === GIT_CONNECT_STEPS.GENERATE_SSH_KEY && ( - + )} {activeStep === GIT_CONNECT_STEPS.ADD_DEPLOY_KEY && ( )} - - {isLoading && ( + + {isSubmitLoading && ( )} - {!isLoading && ( + {!isSubmitLoading && ( + + + + ); +} diff --git a/app/client/src/git/components/GlobalProfile/index.tsx b/app/client/src/git/components/GlobalProfile/index.tsx new file mode 100644 index 000000000000..5ecc06e70c87 --- /dev/null +++ b/app/client/src/git/components/GlobalProfile/index.tsx @@ -0,0 +1,23 @@ +import useGlobalProfile from "git/hooks/useGlobalProfile"; +import React from "react"; +import GlobalProfileView from "./GlobalProfileView"; + +function GlobalProfile() { + const { + globalProfile, + isFetchGlobalProfileLoading, + isUpdateGlobalProfileLoading, + updateGlobalProfile, + } = useGlobalProfile(); + + return ( + + ); +} + +export default GlobalProfile; diff --git a/app/client/src/git/index.ts b/app/client/src/git/index.ts index 876a0a8a0e93..f451600a7407 100644 --- a/app/client/src/git/index.ts +++ b/app/client/src/git/index.ts @@ -7,12 +7,17 @@ export { default as GitModals } from "./ee/components/GitModals"; export { default as GitImportModal } from "./components/ImportModal"; export { default as GitQuickActions } from "./components/QuickActions"; export { default as GitProtectedBranchCallout } from "./components/ProtectedBranchCallout"; +export { default as GitGlobalProfile } from "./components/GlobalProfile"; // hooks export { default as useGitCurrentBranch } from "./hooks/useCurrentBranch"; export { default as useGitProtectedMode } from "./hooks/useProtectedMode"; export { default as useGitConnected } from "./hooks/useConnected"; +// actions +import { gitGlobalActions } from "./store/gitGlobalSlice"; +export const fetchGitGlobalProfile = gitGlobalActions.fetchGlobalProfileInit; + // reducer export { gitReducer } from "./store"; diff --git a/app/client/src/pages/UserProfile/index.tsx b/app/client/src/pages/UserProfile/index.tsx index a715171bc31d..f77d74fedb50 100644 --- a/app/client/src/pages/UserProfile/index.tsx +++ b/app/client/src/pages/UserProfile/index.tsx @@ -3,12 +3,23 @@ import PageWrapper from "pages/common/PageWrapper"; import styled from "styled-components"; import { Tabs, Tab, TabsList, TabPanel } from "@appsmith/ads"; import General from "./General"; -import GitConfig from "./GitConfig"; +import OldGitConfig from "./GitConfig"; import { useLocation } from "react-router"; import { GIT_PROFILE_ROUTE } from "constants/routes"; import { BackButton } from "components/utils/helperComponents"; import { useDispatch } from "react-redux"; import { fetchGlobalGitConfigInit } from "actions/gitSyncActions"; +import { useGitModEnabled } from "pages/Editor/gitSync/hooks/modHooks"; +import { + fetchGitGlobalProfile, + GitGlobalProfile as GitGlobalProfileNew, +} from "git"; + +function GitGlobalProfile() { + const isGitModEnabled = useGitModEnabled(); + + return isGitModEnabled ? : ; +} const ProfileWrapper = styled.div` width: 978px; @@ -25,6 +36,7 @@ const ProfileWrapper = styled.div` function UserProfile() { const location = useLocation(); const dispatch = useDispatch(); + const isGitModEnabled = useGitModEnabled(); let initialTab = "general"; const tabs = [ @@ -39,7 +51,7 @@ function UserProfile() { tabs.push({ key: "gitConfig", title: "Git user config", - panelComponent: , + panelComponent: , icon: "git-branch", }); @@ -49,10 +61,16 @@ function UserProfile() { const [selectedTab, setSelectedTab] = useState(initialTab); - useEffect(() => { - // onMount Fetch Global config - dispatch(fetchGlobalGitConfigInit()); - }, []); + useEffect( + function fetchGlobalGitConfigOnInitEffect() { + if (isGitModEnabled) { + dispatch(fetchGitGlobalProfile()); + } else { + dispatch(fetchGlobalGitConfigInit()); + } + }, + [dispatch, isGitModEnabled], + ); return ( From 022ac38427ed8cde63cf7c6a466c813e856ec2ac Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Tue, 24 Dec 2024 02:17:53 +0530 Subject: [PATCH 088/143] chore: rm console --- app/client/src/git/components/ImportModal/index.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/client/src/git/components/ImportModal/index.tsx b/app/client/src/git/components/ImportModal/index.tsx index ff49a20c0910..2c50da713cee 100644 --- a/app/client/src/git/components/ImportModal/index.tsx +++ b/app/client/src/git/components/ImportModal/index.tsx @@ -33,8 +33,6 @@ function ImportModal({ workspaceId }: ImportModalProps) { [gitImport, workspaceId], ); - console.log({ isImportModalOpen }); - return ( Date: Tue, 24 Dec 2024 02:30:10 +0530 Subject: [PATCH 089/143] chore: adding import modal on cta --- .../src/git/components/ImportModal/index.tsx | 10 +++---- app/client/src/git/hooks/useImport.ts | 4 +-- app/client/src/git/index.ts | 1 + .../src/git/store/actions/gitImportActions.ts | 4 +-- app/client/src/pages/common/ImportModal.tsx | 27 ++++++++++++------- 5 files changed, 25 insertions(+), 21 deletions(-) diff --git a/app/client/src/git/components/ImportModal/index.tsx b/app/client/src/git/components/ImportModal/index.tsx index 2c50da713cee..8192fa9e88a7 100644 --- a/app/client/src/git/components/ImportModal/index.tsx +++ b/app/client/src/git/components/ImportModal/index.tsx @@ -5,11 +5,7 @@ import useImport from "git/hooks/useImport"; import useGlobalSSHKey from "git/hooks/useGlobalSSHKey"; import noop from "lodash/noop"; -interface ImportModalProps { - workspaceId: string; -} - -function ImportModal({ workspaceId }: ImportModalProps) { +function ImportModal() { const { gitImport, gitImportError, @@ -28,9 +24,9 @@ function ImportModal({ workspaceId }: ImportModalProps) { const onSubmit = useCallback( (params: GitImportRequestParams) => { - gitImport(workspaceId, { ...params }); + gitImport(params); }, - [gitImport, workspaceId], + [gitImport], ); return ( diff --git a/app/client/src/git/hooks/useImport.ts b/app/client/src/git/hooks/useImport.ts index a363ba45be3b..62069b888d68 100644 --- a/app/client/src/git/hooks/useImport.ts +++ b/app/client/src/git/hooks/useImport.ts @@ -13,8 +13,8 @@ export default function useImport() { const gitImportState = useSelector(selectGitImportState); const gitImport = useCallback( - (workspaceId: string, params: GitImportRequestParams) => { - dispatch(gitGlobalActions.gitImportInit({ workspaceId, ...params })); + (params: GitImportRequestParams) => { + dispatch(gitGlobalActions.gitImportInit(params)); }, [dispatch], ); diff --git a/app/client/src/git/index.ts b/app/client/src/git/index.ts index f451600a7407..6a7404220398 100644 --- a/app/client/src/git/index.ts +++ b/app/client/src/git/index.ts @@ -17,6 +17,7 @@ export { default as useGitConnected } from "./hooks/useConnected"; // actions import { gitGlobalActions } from "./store/gitGlobalSlice"; export const fetchGitGlobalProfile = gitGlobalActions.fetchGlobalProfileInit; +export const toggleGitImportModal = gitGlobalActions.toggleImportModal; // reducer export { gitReducer } from "./store"; diff --git a/app/client/src/git/store/actions/gitImportActions.ts b/app/client/src/git/store/actions/gitImportActions.ts index 637988ec380e..30e9c7417b2d 100644 --- a/app/client/src/git/store/actions/gitImportActions.ts +++ b/app/client/src/git/store/actions/gitImportActions.ts @@ -2,9 +2,7 @@ import type { PayloadAction } from "@reduxjs/toolkit"; import type { GitAsyncErrorPayload, GitGlobalReduxState } from "../types"; import type { GitImportRequestParams } from "git/requests/gitImportRequest.types"; -export interface GitImportInitPayload extends GitImportRequestParams { - workspaceId: string; -} +export interface GitImportInitPayload extends GitImportRequestParams {} export const gitImportInitAction = ( state: GitGlobalReduxState, diff --git a/app/client/src/pages/common/ImportModal.tsx b/app/client/src/pages/common/ImportModal.tsx index b19974788529..12cefc5dec8c 100644 --- a/app/client/src/pages/common/ImportModal.tsx +++ b/app/client/src/pages/common/ImportModal.tsx @@ -30,6 +30,8 @@ import { import useMessages from "ee/hooks/importModal/useMessages"; import useMethods from "ee/hooks/importModal/useMethods"; import { getIsAnvilLayoutEnabled } from "layoutSystems/anvil/integrations/selectors"; +import { useGitModEnabled } from "pages/Editor/gitSync/hooks/modHooks"; +import { toggleGitImportModal } from "git"; const TextWrapper = styled.div` padding: 0; @@ -203,6 +205,7 @@ function ImportModal(props: ImportModalProps) { toEditor = false, workspaceId, } = props; + const isGitModEnabled = useGitModEnabled(); const { mainDescription, title } = useMessages(); const { appFileToBeUploaded, @@ -223,15 +226,21 @@ function ImportModal(props: ImportModalProps) { setWorkspaceIdForImport({ editorId: editorId || "", workspaceId }), ); - dispatch( - setIsGitSyncModalOpen({ - isOpen: true, - tab: GitSyncModalTab.GIT_CONNECTION, - }), - ); - - // dispatch(setIsReconnectingDatasourcesModalOpen({ isOpen: true })); - }, []); + if (isGitModEnabled) { + dispatch( + toggleGitImportModal({ + open: true, + }), + ); + } else { + dispatch( + setIsGitSyncModalOpen({ + isOpen: true, + tab: GitSyncModalTab.GIT_CONNECTION, + }), + ); + } + }, [dispatch, editorId, isGitModEnabled, onClose, workspaceId]); useEffect(() => { // finished of importing application From 35ff365a2ebd28b9f1cfefdc9c7c7a5f8de03f30 Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Tue, 24 Dec 2024 03:11:02 +0530 Subject: [PATCH 090/143] feat: integrating with deploy btn --- .../appsmith/header/DeployLinkButton.tsx | 59 ++++++++++++------- .../DeployMenuItems/DeployMenuItemsView.tsx | 32 ++++++++++ .../git/components/DeployMenuItems/index.tsx | 11 ++++ app/client/src/git/index.ts | 4 +- .../src/pages/Editor/IDE/Header/index.tsx | 12 +++- 5 files changed, 94 insertions(+), 24 deletions(-) create mode 100644 app/client/src/git/components/DeployMenuItems/DeployMenuItemsView.tsx create mode 100644 app/client/src/git/components/DeployMenuItems/index.tsx diff --git a/app/client/src/components/designSystems/appsmith/header/DeployLinkButton.tsx b/app/client/src/components/designSystems/appsmith/header/DeployLinkButton.tsx index 4eca6a5eab18..91eea09ab4ab 100644 --- a/app/client/src/components/designSystems/appsmith/header/DeployLinkButton.tsx +++ b/app/client/src/components/designSystems/appsmith/header/DeployLinkButton.tsx @@ -1,5 +1,5 @@ import type { ReactNode } from "react"; -import React from "react"; +import React, { useCallback } from "react"; import { Menu, MenuItem, MenuContent, MenuTrigger } from "@appsmith/ads"; import { useSelector, useDispatch } from "react-redux"; import { setIsGitSyncModalOpen } from "actions/gitSyncActions"; @@ -13,7 +13,41 @@ import { Button } from "@appsmith/ads"; import { KBEditorMenuItem } from "ee/pages/Editor/KnowledgeBase/KBEditorMenuItem"; import { useHasConnectToGitPermission } from "pages/Editor/gitSync/hooks/gitPermissionHooks"; import { getIsAnvilEnabledInCurrentApplication } from "layoutSystems/anvil/integrations/selectors"; -import { useGitConnected } from "pages/Editor/gitSync/hooks/modHooks"; +import { + useGitConnected, + useGitModEnabled, +} from "pages/Editor/gitSync/hooks/modHooks"; +import { GitDeployMenuItems as GitDeployMenuItemsNew } from "git"; + +function GitDeployMenuItems() { + const isGitModEnabled = useGitModEnabled(); + + const dispatch = useDispatch(); + const goToGitConnectionPopup = useCallback(() => { + AnalyticsUtil.logEvent("GS_CONNECT_GIT_CLICK", { + source: "Deploy button", + }); + + dispatch( + setIsGitSyncModalOpen({ + isOpen: true, + tab: GitSyncModalTab.GIT_CONNECTION, + }), + ); + }, [dispatch]); + + return isGitModEnabled ? ( + + ) : ( + + {CONNECT_TO_GIT_OPTION()} + + ); +} interface Props { trigger: ReactNode; @@ -21,7 +55,6 @@ interface Props { } export const DeployLinkButton = (props: Props) => { - const dispatch = useDispatch(); const isGitConnected = useGitConnected(); const isConnectToGitPermitted = useHasConnectToGitPermission(); // We check if the current application is an Anvil application. @@ -29,18 +62,6 @@ export const DeployLinkButton = (props: Props) => { // as they donot yet work correctly with Anvil. const isAnvilEnabled = useSelector(getIsAnvilEnabledInCurrentApplication); - const goToGitConnectionPopup = () => { - AnalyticsUtil.logEvent("GS_CONNECT_GIT_CLICK", { - source: "Deploy button", - }); - dispatch( - setIsGitSyncModalOpen({ - isOpen: true, - tab: GitSyncModalTab.GIT_CONNECTION, - }), - ); - }; - return ( @@ -54,13 +75,7 @@ export const DeployLinkButton = (props: Props) => { {!isGitConnected && isConnectToGitPermitted && !isAnvilEnabled && ( - - {CONNECT_TO_GIT_OPTION()} - + )} void; +} + +function DeployMenuItemsView({ + toggleConnectModal = noop, +}: DeployMenuItemsViewProps) { + const handleClickOnConnect = useCallback(() => { + AnalyticsUtil.logEvent("GS_CONNECT_GIT_CLICK", { + source: "Deploy button", + }); + toggleConnectModal(true); + }, [toggleConnectModal]); + + return ( + + {createMessage(CONNECT_TO_GIT_OPTION)} + + ); +} + +export default DeployMenuItemsView; diff --git a/app/client/src/git/components/DeployMenuItems/index.tsx b/app/client/src/git/components/DeployMenuItems/index.tsx new file mode 100644 index 000000000000..de6c61f9af9b --- /dev/null +++ b/app/client/src/git/components/DeployMenuItems/index.tsx @@ -0,0 +1,11 @@ +import useConnect from "git/hooks/useConnect"; +import React from "react"; +import DeployMenuItemsView from "./DeployMenuItemsView"; + +function DeployMenuItems() { + const { toggleConnectModal } = useConnect(); + + return ; +} + +export default DeployMenuItems; diff --git a/app/client/src/git/index.ts b/app/client/src/git/index.ts index 6a7404220398..ed7707eac582 100644 --- a/app/client/src/git/index.ts +++ b/app/client/src/git/index.ts @@ -1,5 +1,5 @@ // enums -export { GitArtifactType } from "./constants/enums"; +export { GitArtifactType, GitOpsTab } from "./constants/enums"; // components export { default as GitContextProvider } from "./components/GitContextProvider"; @@ -8,11 +8,13 @@ export { default as GitImportModal } from "./components/ImportModal"; export { default as GitQuickActions } from "./components/QuickActions"; export { default as GitProtectedBranchCallout } from "./components/ProtectedBranchCallout"; export { default as GitGlobalProfile } from "./components/GlobalProfile"; +export { default as GitDeployMenuItems } from "./components/DeployMenuItems"; // hooks export { default as useGitCurrentBranch } from "./hooks/useCurrentBranch"; export { default as useGitProtectedMode } from "./hooks/useProtectedMode"; export { default as useGitConnected } from "./hooks/useConnected"; +export { default as useGitOps } from "./hooks/useOps"; // actions import { gitGlobalActions } from "./store/gitGlobalSlice"; diff --git a/app/client/src/pages/Editor/IDE/Header/index.tsx b/app/client/src/pages/Editor/IDE/Header/index.tsx index c4c05432a57a..882aa7e16513 100644 --- a/app/client/src/pages/Editor/IDE/Header/index.tsx +++ b/app/client/src/pages/Editor/IDE/Header/index.tsx @@ -78,9 +78,11 @@ import useLibraryHeaderTitle from "ee/pages/Editor/IDE/Header/useLibraryHeaderTi import { AppsmithLink } from "pages/Editor/AppsmithLink"; import { useGitConnected, + useGitModEnabled, useGitProtectedMode, } from "pages/Editor/gitSync/hooks/modHooks"; import { getIsPackageUpgrading } from "ee/selectors/packageSelectors"; +import { useGitOps } from "git"; const StyledDivider = styled(Divider)` height: 50%; @@ -168,6 +170,9 @@ const Header = () => { FEATURE_FLAG.license_private_embeds_enabled, ); + const isGitModEnabled = useGitModEnabled(); + const { toggleOpsModal } = useGitOps(); + const deployLink = useHref(viewerURL, { basePageId: currentPage?.basePageId, }); @@ -218,7 +223,12 @@ const Header = () => { const handleClickDeploy = useCallback(() => { if (isGitConnected) { - dispatch(showConnectGitModal()); + if (isGitModEnabled) { + toggleOpsModal(true); + } else { + dispatch(showConnectGitModal()); + } + AnalyticsUtil.logEvent("GS_DEPLOY_GIT_CLICK", { source: "Deploy button", }); From 1498ddc78657f26dca8b7ccbd8016b2b2109027f Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Tue, 24 Dec 2024 03:13:40 +0530 Subject: [PATCH 091/143] chore: fix git import modal --- app/client/src/ce/pages/Applications/index.tsx | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/app/client/src/ce/pages/Applications/index.tsx b/app/client/src/ce/pages/Applications/index.tsx index 6bd875fea98c..19b45abd74e1 100644 --- a/app/client/src/ce/pages/Applications/index.tsx +++ b/app/client/src/ce/pages/Applications/index.tsx @@ -136,18 +136,10 @@ import OldGitSyncModal from "pages/Editor/gitSync/GitSyncModal"; import { useGitModEnabled } from "pages/Editor/gitSync/hooks/modHooks"; import { GitImportModal as NewGitImportModal } from "git"; -interface GitImportModalProps { - workspaceId: string; -} - -function GitImportModal({ workspaceId }: GitImportModalProps) { +function GitImportModal() { const isGitModEnabled = useGitModEnabled(); - return isGitModEnabled ? ( - - ) : ( - - ); + return isGitModEnabled ? : ; } export const { cloudHosting } = getAppsmithConfigs(); @@ -971,7 +963,7 @@ export function ApplicationsSection(props: any) { isMobile={isMobile} > {workspacesListComponent} - + ); From bda63a5fc21ddabb0b5d2798b5b3ec66c112fa6c Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Tue, 24 Dec 2024 03:58:09 +0530 Subject: [PATCH 092/143] chore: putting gitapplicationProvider in better places --- app/client/src/ce/AppRouter.tsx | 5 +- .../pages/Editor/IDE/Header/DeployButton.tsx | 131 ++++++++++++++++++ .../src/pages/Editor/IDE/Header/index.tsx | 118 +--------------- app/client/src/pages/Editor/index.tsx | 45 +++--- 4 files changed, 164 insertions(+), 135 deletions(-) create mode 100644 app/client/src/pages/Editor/IDE/Header/DeployButton.tsx diff --git a/app/client/src/ce/AppRouter.tsx b/app/client/src/ce/AppRouter.tsx index 498433dc9282..0675d4ba7bc1 100644 --- a/app/client/src/ce/AppRouter.tsx +++ b/app/client/src/ce/AppRouter.tsx @@ -64,7 +64,6 @@ import { FEATURE_FLAG } from "ee/entities/FeatureFlag"; import CustomWidgetBuilderLoader from "pages/Editor/CustomWidgetBuilder/loader"; import { getIsConsolidatedPageLoading } from "selectors/ui"; import { useFeatureFlagOverride } from "utils/hooks/useFeatureFlagOverride"; -import GitApplicationContextProvider from "components/gitContexts/GitApplicationContextProvider"; export const SentryRoute = Sentry.withSentryRouting(Route); @@ -188,13 +187,13 @@ export default function AppRouter() { ) : ( - + <> - + )} diff --git a/app/client/src/pages/Editor/IDE/Header/DeployButton.tsx b/app/client/src/pages/Editor/IDE/Header/DeployButton.tsx new file mode 100644 index 000000000000..843da728dddf --- /dev/null +++ b/app/client/src/pages/Editor/IDE/Header/DeployButton.tsx @@ -0,0 +1,131 @@ +import { Button, Tooltip } from "@appsmith/ads"; +import { objectKeys } from "@appsmith/utils"; +import { showConnectGitModal } from "actions/gitSyncActions"; +import { publishApplication } from "ee/actions/applicationActions"; +import { getCurrentApplication } from "ee/selectors/applicationSelectors"; +import type { NavigationSetting } from "constants/AppConstants"; +import { + createMessage, + DEPLOY_BUTTON_TOOLTIP, + DEPLOY_MENU_OPTION, + PACKAGE_UPGRADING_ACTION_STATUS, +} from "ee/constants/messages"; +import { getIsPackageUpgrading } from "ee/selectors/packageSelectors"; +import AnalyticsUtil from "ee/utils/AnalyticsUtil"; +import { useGitOps, useGitProtectedMode } from "git"; +import { + useGitConnected, + useGitModEnabled, +} from "pages/Editor/gitSync/hooks/modHooks"; +import React, { useCallback } from "react"; +import { useDispatch, useSelector } from "react-redux"; +import { + getCurrentApplicationId, + getIsPublishingApplication, +} from "selectors/editorSelectors"; +import styled from "styled-components"; + +// This wrapper maintains pointer events for tooltips when the child button is disabled. +// Without this, disabled buttons won't trigger tooltips because they have pointer-events: none +const StyledTooltipTarget = styled.span` + display: inline-block; +`; + +function DeployButton() { + const applicationId = useSelector(getCurrentApplicationId); + const currentApplication = useSelector(getCurrentApplication); + const isPackageUpgrading = useSelector(getIsPackageUpgrading); + const isProtectedMode = useGitProtectedMode(); + const isDeployDisabled = isPackageUpgrading || isProtectedMode; + const isPublishing = useSelector(getIsPublishingApplication); + const isGitConnected = useGitConnected(); + const isGitModEnabled = useGitModEnabled(); + const { toggleOpsModal } = useGitOps(); + + const deployTooltipText = isPackageUpgrading + ? createMessage(PACKAGE_UPGRADING_ACTION_STATUS, "deploy this app") + : createMessage(DEPLOY_BUTTON_TOOLTIP); + + const dispatch = useDispatch(); + + const handlePublish = useCallback(() => { + if (applicationId) { + dispatch(publishApplication(applicationId)); + + const appName = currentApplication ? currentApplication.name : ""; + const pageCount = currentApplication?.pages?.length; + const navigationSettingsWithPrefix: Record< + string, + NavigationSetting[keyof NavigationSetting] + > = {}; + + if (currentApplication?.applicationDetail?.navigationSetting) { + const settingKeys = objectKeys( + currentApplication.applicationDetail.navigationSetting, + ) as Array; + + settingKeys.map((key: keyof NavigationSetting) => { + if (currentApplication?.applicationDetail?.navigationSetting?.[key]) { + const value: NavigationSetting[keyof NavigationSetting] = + currentApplication.applicationDetail.navigationSetting[key]; + + navigationSettingsWithPrefix[`navigationSetting_${key}`] = value; + } + }); + } + + AnalyticsUtil.logEvent("PUBLISH_APP", { + appId: applicationId, + appName, + pageCount, + ...navigationSettingsWithPrefix, + isPublic: !!currentApplication?.isPublic, + templateTitle: currentApplication?.forkedFromTemplateTitle, + }); + } + }, [applicationId, currentApplication, dispatch]); + + const handleClickDeploy = useCallback(() => { + if (isGitConnected) { + if (isGitModEnabled) { + toggleOpsModal(true); + } else { + dispatch(showConnectGitModal()); + } + + AnalyticsUtil.logEvent("GS_DEPLOY_GIT_CLICK", { + source: "Deploy button", + }); + } else { + handlePublish(); + } + }, [ + dispatch, + handlePublish, + isGitConnected, + isGitModEnabled, + toggleOpsModal, + ]); + + return ( + + + + + + ); +} + +export default DeployButton; diff --git a/app/client/src/pages/Editor/IDE/Header/index.tsx b/app/client/src/pages/Editor/IDE/Header/index.tsx index 882aa7e16513..c26b641ba40d 100644 --- a/app/client/src/pages/Editor/IDE/Header/index.tsx +++ b/app/client/src/pages/Editor/IDE/Header/index.tsx @@ -1,7 +1,6 @@ -import React, { useCallback, useState } from "react"; +import React, { useState } from "react"; import { Flex, - Tooltip, Divider, Modal, ModalContent, @@ -11,7 +10,6 @@ import { TabsList, Tab, TabPanel, - Button, Link, IDEHeader, IDEHeaderTitle, @@ -24,19 +22,15 @@ import { APPLICATION_INVITE, COMMUNITY_TEMPLATES, createMessage, - DEPLOY_BUTTON_TOOLTIP, - DEPLOY_MENU_OPTION, IN_APP_EMBED_SETTING, INVITE_TAB, HEADER_TITLES, - PACKAGE_UPGRADING_ACTION_STATUS, } from "ee/constants/messages"; import EditorName from "pages/Editor/EditorName"; import { getCurrentApplicationId, getCurrentPageId, getIsPageSaving, - getIsPublishingApplication, getPageById, getPageSavingError, } from "selectors/editorSelectors"; @@ -46,10 +40,7 @@ import { getIsErroredSavingAppName, getIsSavingAppName, } from "ee/selectors/applicationSelectors"; -import { - publishApplication, - updateApplication, -} from "ee/actions/applicationActions"; +import { updateApplication } from "ee/actions/applicationActions"; import { getCurrentAppWorkspace } from "ee/selectors/selectedWorkspaceSelectors"; import { Omnibar } from "pages/Editor/commons/Omnibar"; import ToggleModeButton from "pages/Editor/ToggleModeButton"; @@ -62,9 +53,6 @@ import DeployLinkButtonDialog from "components/designSystems/appsmith/header/Dep import { useFeatureFlag } from "utils/hooks/useFeatureFlag"; import { FEATURE_FLAG } from "ee/entities/FeatureFlag"; import { getAppsmithConfigs } from "ee/configs"; -import { showConnectGitModal } from "actions/gitSyncActions"; -import AnalyticsUtil from "ee/utils/AnalyticsUtil"; -import type { NavigationSetting } from "constants/AppConstants"; import { useHref } from "pages/Editor/utils"; import { viewerURL } from "ee/RouteBuilder"; import HelpBar from "components/editorComponents/GlobalSearch/HelpBar"; @@ -76,13 +64,8 @@ import { APPLICATIONS_URL } from "constants/routes"; import { useNavigationMenuData } from "../../EditorName/useNavigationMenuData"; import useLibraryHeaderTitle from "ee/pages/Editor/IDE/Header/useLibraryHeaderTitle"; import { AppsmithLink } from "pages/Editor/AppsmithLink"; -import { - useGitConnected, - useGitModEnabled, - useGitProtectedMode, -} from "pages/Editor/gitSync/hooks/modHooks"; -import { getIsPackageUpgrading } from "ee/selectors/packageSelectors"; -import { useGitOps } from "git"; +import DeployButton from "./DeployButton"; +import GitApplicationContextProvider from "components/gitContexts/GitApplicationContextProvider"; const StyledDivider = styled(Divider)` height: 50%; @@ -90,12 +73,6 @@ const StyledDivider = styled(Divider)` margin-right: 8px; `; -// This wrapper maintains pointer events for tooltips when the child button is disabled. -// Without this, disabled buttons won't trigger tooltips because they have pointer-events: none -const StyledTooltipTarget = styled.span` - display: inline-block; -`; - const { cloudHosting } = getAppsmithConfigs(); interface HeaderTitleProps { @@ -139,19 +116,11 @@ const Header = () => { const currentApplication = useSelector(getCurrentApplication); const isErroredSavingName = useSelector(getIsErroredSavingAppName); const applicationList = useSelector(getApplicationList); - const isProtectedMode = useGitProtectedMode(); - const isPackageUpgrading = useSelector(getIsPackageUpgrading); - const isPublishing = useSelector(getIsPublishingApplication); - const isGitConnected = useGitConnected(); const pageId = useSelector(getCurrentPageId) as string; const currentPage = useSelector(getPageById(pageId)); const appState = useCurrentAppState(); const isSaving = useSelector(getIsPageSaving); const pageSaveError = useSelector(getPageSavingError); - const isDeployDisabled = isPackageUpgrading || isProtectedMode; - const deployTooltipText = isPackageUpgrading - ? createMessage(PACKAGE_UPGRADING_ACTION_STATUS, "deploy this app") - : createMessage(DEPLOY_BUTTON_TOOLTIP); // states const [isPopoverOpen, setIsPopoverOpen] = useState(false); const [showModal, setShowModal] = useState(false); @@ -170,9 +139,6 @@ const Header = () => { FEATURE_FLAG.license_private_embeds_enabled, ); - const isGitModEnabled = useGitModEnabled(); - const { toggleOpsModal } = useGitOps(); - const deployLink = useHref(viewerURL, { basePageId: currentPage?.basePageId, }); @@ -184,61 +150,8 @@ const Header = () => { dispatch(updateApplication(id, data)); }; - const handlePublish = useCallback(() => { - if (applicationId) { - dispatch(publishApplication(applicationId)); - - const appName = currentApplication ? currentApplication.name : ""; - const pageCount = currentApplication?.pages?.length; - const navigationSettingsWithPrefix: Record< - string, - NavigationSetting[keyof NavigationSetting] - > = {}; - - if (currentApplication?.applicationDetail?.navigationSetting) { - const settingKeys = Object.keys( - currentApplication.applicationDetail.navigationSetting, - ) as Array; - - settingKeys.map((key: keyof NavigationSetting) => { - if (currentApplication?.applicationDetail?.navigationSetting?.[key]) { - const value: NavigationSetting[keyof NavigationSetting] = - currentApplication.applicationDetail.navigationSetting[key]; - - navigationSettingsWithPrefix[`navigationSetting_${key}`] = value; - } - }); - } - - AnalyticsUtil.logEvent("PUBLISH_APP", { - appId: applicationId, - appName, - pageCount, - ...navigationSettingsWithPrefix, - isPublic: !!currentApplication?.isPublic, - templateTitle: currentApplication?.forkedFromTemplateTitle, - }); - } - }, [applicationId, currentApplication, dispatch]); - - const handleClickDeploy = useCallback(() => { - if (isGitConnected) { - if (isGitModEnabled) { - toggleOpsModal(true); - } else { - dispatch(showConnectGitModal()); - } - - AnalyticsUtil.logEvent("GS_DEPLOY_GIT_CLICK", { - source: "Deploy button", - }); - } else { - handlePublish(); - } - }, [dispatch, handlePublish, isGitConnected]); - return ( - <> + }> @@ -348,30 +261,13 @@ const Header = () => { showModal={showPublishCommunityTemplateModal} />
- - - - - - +
- +
); }; diff --git a/app/client/src/pages/Editor/index.tsx b/app/client/src/pages/Editor/index.tsx index 20c950577d41..65d78f238046 100644 --- a/app/client/src/pages/Editor/index.tsx +++ b/app/client/src/pages/Editor/index.tsx @@ -54,6 +54,7 @@ import ReconfigureCDKeyModal from "ee/components/gitComponents/ReconfigureCDKeyM import DisableCDModal from "ee/components/gitComponents/DisableCDModal"; import RepoLimitExceededErrorModal from "./gitSync/RepoLimitExceededErrorModal"; import { useGitModEnabled } from "./gitSync/hooks/modHooks"; +import GitApplicationContextProvider from "components/gitContexts/GitApplicationContextProvider"; function GitModals() { const isGitModEnabled = useGitModEnabled(); @@ -208,27 +209,29 @@ class Editor extends Component { return ( -
- - - - {`${this.props.currentApplicationName} | Editor | Appsmith`} - - - - - - - - - - - - - - -
- + +
+ + + + {`${this.props.currentApplicationName} | Editor | Appsmith`} + + + + + + + + + + + + + + +
+ +
); } From a0a3d29e692cd5a1bcecdae332e2fd32e6ed70ed Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Tue, 24 Dec 2024 04:33:49 +0530 Subject: [PATCH 093/143] chore: fix connect issue --- .../ads/src/Icon/Icon.provider.tsx | 5 ++ .../ConflictErrorModalView.tsx | 16 ++----- .../OpsModal/TabDeploy/DeployPreview.tsx | 47 ++++++++++++------- .../OpsModal/TabDeploy/TabDeployView.tsx | 10 +++- 4 files changed, 50 insertions(+), 28 deletions(-) diff --git a/app/client/packages/design-system/ads/src/Icon/Icon.provider.tsx b/app/client/packages/design-system/ads/src/Icon/Icon.provider.tsx index 8db9b910c9b1..1d8789f0a392 100644 --- a/app/client/packages/design-system/ads/src/Icon/Icon.provider.tsx +++ b/app/client/packages/design-system/ads/src/Icon/Icon.provider.tsx @@ -1103,6 +1103,10 @@ const ContentTypeRaw = importSvg( async () => import("../__assets__/icons/ads/content-type-raw.svg"), ); +const CloudIconV2 = importSvg( + async () => import("../__assets__/icons/ads/cloudy-line.svg"), +); + import PlayIconPNG from "../__assets__/icons/control/play-icon.png"; function PlayIconPNGWrapper() { @@ -1177,6 +1181,7 @@ const ICON_LOOKUP = { "close-modal": CloseLineIcon, "close-x": CloseLineIcon, "cloud-off-line": CloudOfflineIcon, + "cloud-v2": CloudIconV2, "collapse-control": CollapseIcon, "column-freeze": ColumnFreeze, "column-unfreeze": SubtractIcon, diff --git a/app/client/src/git/components/ConflictErrorModal/ConflictErrorModalView.tsx b/app/client/src/git/components/ConflictErrorModal/ConflictErrorModalView.tsx index d59ff023af40..5090e39c7643 100644 --- a/app/client/src/git/components/ConflictErrorModal/ConflictErrorModalView.tsx +++ b/app/client/src/git/components/ConflictErrorModal/ConflictErrorModalView.tsx @@ -6,7 +6,7 @@ import { CONFLICTS_FOUND_WHILE_PULLING_CHANGES, } from "ee/constants/messages"; -import { Button } from "@appsmith/ads"; +import { Button, Flex } from "@appsmith/ads"; import noop from "lodash/noop"; import ConflictError from "../ConflictError"; @@ -62,18 +62,12 @@ function ConflictErrorModalView({ >
-
-
+ + {createMessage(CONFLICTS_FOUND_WHILE_PULLING_CHANGES)} -
+
+
diff --git a/app/client/src/git/components/OpsModal/TabDeploy/DeployPreview.tsx b/app/client/src/git/components/OpsModal/TabDeploy/DeployPreview.tsx index 79abbe1439dc..311019abdc24 100644 --- a/app/client/src/git/components/OpsModal/TabDeploy/DeployPreview.tsx +++ b/app/client/src/git/components/OpsModal/TabDeploy/DeployPreview.tsx @@ -1,4 +1,4 @@ -import React from "react"; +import React, { useCallback, useEffect, useState } from "react"; import styled from "styled-components"; import { useSelector } from "react-redux"; @@ -15,32 +15,47 @@ import SuccessTick from "pages/common/SuccessTick"; import { howMuchTimeBeforeText } from "utils/helpers"; import AnalyticsUtil from "ee/utils/AnalyticsUtil"; import { viewerURL } from "ee/RouteBuilder"; -import { Link, Text } from "@appsmith/ads"; -import { importSvg } from "@appsmith/ads-old"; +import { Icon, Link, Text } from "@appsmith/ads"; -const CloudyIcon = importSvg( - async () => import("assets/icons/ads/cloudy-line.svg"), -); +const StyledIcon = styled(Icon)` + svg { + width: 30px; + height: 30px; + } +`; const Container = styled.div` display: flex; flex: 1; flex-direction: row; gap: ${(props) => props.theme.spaces[6]}px; - - .cloud-icon { - stroke: var(--ads-v2-color-fg); - } `; -export default function DeployPreview() { - // ! case: should reset after timer - const showSuccess = false; +interface DeployPreviewProps { + isCommitSuccess: boolean; +} + +export default function DeployPreview({ isCommitSuccess }: DeployPreviewProps) { + const [showSuccess, setShowSuccess] = useState(false); + + useEffect( + function startTimerForCommitSuccessEffect() { + if (isCommitSuccess) { + setShowSuccess(true); + const timer = setTimeout(() => { + setShowSuccess(false); + }, 5000); + + return () => clearTimeout(timer); + } + }, + [isCommitSuccess], + ); const basePageId = useSelector(getCurrentBasePageId); const lastDeployedAt = useSelector(getApplicationLastDeployedAt); - const showDeployPreview = () => { + const showDeployPreview = useCallback(() => { AnalyticsUtil.logEvent("GS_LAST_DEPLOYED_PREVIEW_LINK_CLICK", { source: "GIT_DEPLOY_MODAL", }); @@ -49,7 +64,7 @@ export default function DeployPreview() { }); window.open(path, "_blank"); - }; + }, [basePageId]); const lastDeployedAtMsg = lastDeployedAt ? `${createMessage(LATEST_DP_SUBTITLE)} ${howMuchTimeBeforeText( @@ -66,7 +81,7 @@ export default function DeployPreview() { {showSuccess ? ( ) : ( - + )}
diff --git a/app/client/src/git/components/OpsModal/TabDeploy/TabDeployView.tsx b/app/client/src/git/components/OpsModal/TabDeploy/TabDeployView.tsx index d22c93f79b97..a2db0f28805d 100644 --- a/app/client/src/git/components/OpsModal/TabDeploy/TabDeployView.tsx +++ b/app/client/src/git/components/OpsModal/TabDeploy/TabDeployView.tsx @@ -108,6 +108,7 @@ function TabDeployView({ statusBehindCount = 0, statusIsClean = false, }: TabDeployViewProps) { + const [hasSubmitted, setHasSubmitted] = useState(false); const hasChangesToCommit = !statusIsClean; const commitInputRef = useRef(null); const [commitMessage, setCommitMessage] = useState( @@ -157,6 +158,10 @@ function TabDeployView({ ((pullRequired && !isConflicting) || (statusBehindCount > 0 && statusIsClean)); + const isCommitSuccess = useMemo(() => { + return hasSubmitted && !isCommitLoading; + }, [isCommitLoading, hasSubmitted]); + useEffect( function focusCommitInputEffect() { if (!commitInputDisabled && commitInputRef.current) { @@ -200,6 +205,7 @@ function TabDeployView({ }); if (currentBranch) { + setHasSubmitted(true); commit(commitMessage.trim()); } }, [commit, commitMessage, currentBranch]); @@ -353,7 +359,9 @@ function TabDeployView({ /> )} - {!pullRequired && !isConflicting && } + {!pullRequired && !isConflicting && ( + + )}
From 1f551942d1b46ace563788bb86543ef356eab083 Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Tue, 24 Dec 2024 04:37:22 +0530 Subject: [PATCH 094/143] chore: minor fixes --- app/client/src/git/sagas/disconnectSaga.ts | 2 +- .../src/pages/Editor/gitSync/components/DeployPreview.tsx | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/app/client/src/git/sagas/disconnectSaga.ts b/app/client/src/git/sagas/disconnectSaga.ts index 89fdbd090c29..bdd8bc063dbc 100644 --- a/app/client/src/git/sagas/disconnectSaga.ts +++ b/app/client/src/git/sagas/disconnectSaga.ts @@ -26,7 +26,7 @@ export default function* disconnectSaga(action: GitArtifactPayloadAction) { url.searchParams.delete(GIT_BRANCH_QUERY_KEY); history.push(url.toString().slice(url.origin.length)); yield put(gitArtifactActions.closeDisconnectModal({ artifactDef })); - // !case: why? + // ! case: why? // yield put(importAppViaGitStatusReset()); yield put( gitArtifactActions.toggleOpsModal({ diff --git a/app/client/src/pages/Editor/gitSync/components/DeployPreview.tsx b/app/client/src/pages/Editor/gitSync/components/DeployPreview.tsx index 68c5d609429b..9ead5d9d65c9 100644 --- a/app/client/src/pages/Editor/gitSync/components/DeployPreview.tsx +++ b/app/client/src/pages/Editor/gitSync/components/DeployPreview.tsx @@ -58,7 +58,6 @@ export default function DeployPreview(props: { showSuccess: boolean }) { : ""; return lastDeployedAt ? ( - // ! case: can use flex?
{props.showSuccess ? ( From a9a65c3e31e3b5b8cee414fe22ea4b81200ba4d5 Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Tue, 24 Dec 2024 04:48:59 +0530 Subject: [PATCH 095/143] chore: minor fixes for disconnect flow --- .../src/git/requests/disconnectRequest.types.ts | 5 ++--- app/client/src/git/sagas/disconnectSaga.ts | 11 ++++++++--- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/app/client/src/git/requests/disconnectRequest.types.ts b/app/client/src/git/requests/disconnectRequest.types.ts index 2cbf5969ccca..b1cd5827d951 100644 --- a/app/client/src/git/requests/disconnectRequest.types.ts +++ b/app/client/src/git/requests/disconnectRequest.types.ts @@ -1,7 +1,6 @@ import type { ApiResponse } from "api/types"; +import type { ApplicationPayload } from "entities/Application"; -export interface DisconnectResponseData { - [key: string]: string; -} +export interface DisconnectResponseData extends ApplicationPayload {} export type DisconnectResponse = ApiResponse; diff --git a/app/client/src/git/sagas/disconnectSaga.ts b/app/client/src/git/sagas/disconnectSaga.ts index bdd8bc063dbc..ef6315c25cd5 100644 --- a/app/client/src/git/sagas/disconnectSaga.ts +++ b/app/client/src/git/sagas/disconnectSaga.ts @@ -24,10 +24,15 @@ export default function* disconnectSaga(action: GitArtifactPayloadAction) { const url = new URL(window.location.href); url.searchParams.delete(GIT_BRANCH_QUERY_KEY); - history.push(url.toString().slice(url.origin.length)); + history.replace(url.toString().slice(url.origin.length)); + yield put(gitArtifactActions.unmount({ artifactDef })); + yield put( + gitArtifactActions.initGitForEditor({ + artifactDef, + artifact: response.data, + }), + ); yield put(gitArtifactActions.closeDisconnectModal({ artifactDef })); - // ! case: why? - // yield put(importAppViaGitStatusReset()); yield put( gitArtifactActions.toggleOpsModal({ artifactDef, From ad48cd9913d9b29800605b3f01c69bf444dc6e49 Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Tue, 24 Dec 2024 14:37:09 +0530 Subject: [PATCH 096/143] chore: passing unit tests --- .../pages/Editor/IDE/MainPane/useRoutes.tsx | 4 ++-- app/client/src/ce/reducers/index.tsx | 2 +- app/client/src/ce/sagas/PageSagas.tsx | 10 +++++---- app/client/src/ce/sagas/index.tsx | 2 +- app/client/src/git/index.ts | 6 ----- .../anvil/common/hooks/detachedWidgetHooks.ts | 4 ++-- .../common/hooks/useWidgetBorderStyles.ts | 4 ++-- .../anvil/editor/AnvilEditorWidgetOnion.tsx | 4 ++-- .../anvil/editor/hooks/useAnvilWidgetHover.ts | 4 ++-- .../sagas/LayoutElementPositionsSaga.ts | 4 ++-- .../components/zone/useZoneMinWidth.ts | 8 +++---- .../SectionSpaceDistributor.tsx | 4 ++-- .../anvil/viewer/AnvilViewerWidgetOnion.tsx | 4 ++-- .../autolayout/common/FlexComponent.tsx | 8 +++---- .../common/dropTarget/DropTargetComponent.tsx | 8 +++---- .../common/resizer/ModalResizableLayer.tsx | 8 +++---- .../common/resizer/ResizableComponent.tsx | 8 +++---- .../usePositionObserver.ts | 6 ++--- .../layoutSystems/common/widgetName/index.tsx | 4 ++-- .../common/autoHeightOverlay/index.tsx | 4 ++-- .../CanvasSelectionArena.tsx | 4 ++-- .../pages/AppViewer/Navigation/Sidebar.tsx | 8 +++---- .../pages/AppViewer/Navigation/TopInline.tsx | 8 +++---- app/client/src/pages/Editor/Canvas.tsx | 4 ++-- .../NavigationAdjustedPageViewer.tsx | 4 ++-- .../components/NavigationPreview.tsx | 4 ++-- .../components/WidgetEditorContentWrapper.tsx | 8 +++---- .../components/WidgetEditorNavigation.tsx | 6 ++--- .../Editor/commons/EditorWrapperContainer.tsx | 4 ++-- app/client/src/pages/Editor/index.tsx | 22 +++++++++---------- .../src/sagas/autoHeightSagas/helpers.ts | 4 ++-- .../src/selectors/debuggerSelectors.tsx | 4 ++-- app/client/src/selectors/editorSelectors.tsx | 15 ------------- app/client/src/selectors/gitModSelectors.ts | 15 +++++++++++++ .../src/selectors/widgetDragSelectors.ts | 8 +++---- app/client/src/selectors/widgetSelectors.ts | 4 ++-- .../utils/hooks/useAllowEditorDragToSelect.ts | 8 +++---- .../src/utils/hooks/useHoverToFocusWidget.ts | 4 ++-- .../widgets/ChartWidget/component/index.tsx | 4 ++-- .../widgets/CustomWidget/component/index.tsx | 4 ++-- .../widgets/IframeWidget/component/index.tsx | 4 ++-- app/client/src/widgets/withWidgetProps.tsx | 4 ++-- app/client/test/testUtils.tsx | 7 ++++++ 43 files changed, 123 insertions(+), 140 deletions(-) diff --git a/app/client/src/ce/pages/Editor/IDE/MainPane/useRoutes.tsx b/app/client/src/ce/pages/Editor/IDE/MainPane/useRoutes.tsx index cac3ae6f84a8..8f16afc63327 100644 --- a/app/client/src/ce/pages/Editor/IDE/MainPane/useRoutes.tsx +++ b/app/client/src/ce/pages/Editor/IDE/MainPane/useRoutes.tsx @@ -34,12 +34,12 @@ import DataSourceEditor from "pages/Editor/DataSourceEditor"; import DatasourceBlankState from "pages/Editor/DataSourceEditor/DatasourceBlankState"; import type { RouteProps } from "react-router"; import { useSelector } from "react-redux"; -import { combinedPreviewModeSelector } from "selectors/editorSelectors"; import { lazy, Suspense } from "react"; import React from "react"; import { retryPromise } from "utils/AppsmithUtils"; import Skeleton from "widgets/Skeleton"; +import { selectCombinedPreviewMode } from "selectors/gitModSelectors"; const FirstTimeUserOnboardingChecklist = lazy(async () => retryPromise( @@ -67,7 +67,7 @@ export interface RouteReturnType extends RouteProps { */ function useRoutes(path: string): RouteReturnType[] { - const isPreviewMode = useSelector(combinedPreviewModeSelector); + const isPreviewMode = useSelector(selectCombinedPreviewMode); return [ { diff --git a/app/client/src/ce/reducers/index.tsx b/app/client/src/ce/reducers/index.tsx index 6238302b826a..c260178b6856 100644 --- a/app/client/src/ce/reducers/index.tsx +++ b/app/client/src/ce/reducers/index.tsx @@ -77,8 +77,8 @@ import type { ActiveField } from "reducers/uiReducers/activeFieldEditorReducer"; import type { SelectedWorkspaceReduxState } from "ee/reducers/uiReducers/selectedWorkspaceReducer"; import type { ConsolidatedPageLoadState } from "reducers/uiReducers/consolidatedPageLoadReducer"; import type { BuildingBlocksReduxState } from "reducers/uiReducers/buildingBlockReducer"; -import { gitReducer } from "git"; import type { GitArtifactRootReduxState, GitGlobalReduxState } from "git"; +import { gitReducer } from "git/store"; export const reducerObject = { entities: entityReducer, diff --git a/app/client/src/ce/sagas/PageSagas.tsx b/app/client/src/ce/sagas/PageSagas.tsx index 08a8e1d173d1..18d42e1f235b 100644 --- a/app/client/src/ce/sagas/PageSagas.tsx +++ b/app/client/src/ce/sagas/PageSagas.tsx @@ -75,7 +75,6 @@ import { import { IncorrectBindingError, validateResponse } from "sagas/ErrorSagas"; import type { ApiResponse } from "api/ApiResponses"; import { - combinedPreviewModeSelector, getCurrentApplicationId, getCurrentBaseApplicationId, getCurrentLayoutId, @@ -150,7 +149,10 @@ import { getIsAnvilLayout } from "layoutSystems/anvil/integrations/selectors"; import { convertToBasePageIdSelector } from "selectors/pageListSelectors"; import type { Page } from "entities/Page"; import { ConsolidatedPageLoadApi } from "api"; -import { selectGitCurrentBranch } from "selectors/gitModSelectors"; +import { + selectCombinedPreviewMode, + selectGitCurrentBranch, +} from "selectors/gitModSelectors"; import { applicationArtifact } from "git/artifact-helpers/application"; export const checkIfMigrationIsNeeded = ( @@ -643,7 +645,7 @@ export function* saveLayoutSaga(action: ReduxAction<{ isRetry?: boolean }>) { try { const currentPageId: string = yield select(getCurrentPageId); const currentPage: Page = yield select(getPageById(currentPageId)); - const isPreviewMode: boolean = yield select(combinedPreviewModeSelector); + const isPreviewMode: boolean = yield select(selectCombinedPreviewMode); const appMode: APP_MODE | undefined = yield select(getAppMode); @@ -1407,7 +1409,7 @@ export function* setCanvasCardsStateSaga(action: ReduxAction) { } export function* setPreviewModeInitSaga(action: ReduxAction) { - const isPreviewMode: boolean = yield select(combinedPreviewModeSelector); + const isPreviewMode: boolean = yield select(selectCombinedPreviewMode); if (action.payload) { // we animate out elements and then move to the canvas diff --git a/app/client/src/ce/sagas/index.tsx b/app/client/src/ce/sagas/index.tsx index 1f7f79e90746..38d327ea913b 100644 --- a/app/client/src/ce/sagas/index.tsx +++ b/app/client/src/ce/sagas/index.tsx @@ -49,10 +49,10 @@ import communityTemplateSagas from "sagas/CommunityTemplatesSagas"; import anvilSagas from "layoutSystems/anvil/integrations/sagas"; import ideSagas from "sagas/IDESaga"; import sendSideBySideWidgetHoverAnalyticsEventSaga from "sagas/AnalyticsSaga"; -import { gitSagas } from "git"; /* Sagas that are registered by a module that is designed to be independent of the core platform */ import ternSagas from "sagas/TernSaga"; +import gitSagas from "git/sagas"; export const sagas = [ initSagas, diff --git a/app/client/src/git/index.ts b/app/client/src/git/index.ts index ed7707eac582..69773a8d989a 100644 --- a/app/client/src/git/index.ts +++ b/app/client/src/git/index.ts @@ -21,18 +21,12 @@ import { gitGlobalActions } from "./store/gitGlobalSlice"; export const fetchGitGlobalProfile = gitGlobalActions.fetchGlobalProfileInit; export const toggleGitImportModal = gitGlobalActions.toggleImportModal; -// reducer -export { gitReducer } from "./store"; - // selectors export { selectCurrentBranch as selectGitCurrentBranch, selectProtectedMode as selectGitProtectedMode, } from "./store/selectors/gitArtifactSelectors"; -// sagas -export { default as gitSagas } from "./sagas"; - // types export type { GitArtifactDef, diff --git a/app/client/src/layoutSystems/anvil/common/hooks/detachedWidgetHooks.ts b/app/client/src/layoutSystems/anvil/common/hooks/detachedWidgetHooks.ts index c3ad4a82bd8d..6bf86d26a55d 100644 --- a/app/client/src/layoutSystems/anvil/common/hooks/detachedWidgetHooks.ts +++ b/app/client/src/layoutSystems/anvil/common/hooks/detachedWidgetHooks.ts @@ -1,7 +1,6 @@ import { useWidgetBorderStyles } from "./useWidgetBorderStyles"; import { useDispatch, useSelector } from "react-redux"; import { useWidgetSelection } from "utils/hooks/useWidgetSelection"; -import { combinedPreviewModeSelector } from "selectors/editorSelectors"; import { SELECT_ANVIL_WIDGET_CUSTOM_EVENT } from "layoutSystems/anvil/utils/constants"; import log from "loglevel"; import { useEffect, useMemo } from "react"; @@ -9,6 +8,7 @@ import { getAnvilWidgetDOMId } from "layoutSystems/common/utils/LayoutElementPos import { getCurrentlyOpenAnvilDetachedWidgets } from "layoutSystems/anvil/integrations/modalSelectors"; import { getCanvasWidgetsStructure } from "ee/selectors/entitiesSelector"; import type { CanvasWidgetStructure } from "WidgetProvider/constants"; +import { selectCombinedPreviewMode } from "selectors/gitModSelectors"; /** * This hook is used to select and focus on a detached widget * As detached widgets are outside of the layout flow, we need to access the correct element in the DOM @@ -17,7 +17,7 @@ import type { CanvasWidgetStructure } from "WidgetProvider/constants"; */ export function useHandleDetachedWidgetSelect(widgetId: string) { const dispatch = useDispatch(); - const isPreviewMode = useSelector(combinedPreviewModeSelector); + const isPreviewMode = useSelector(selectCombinedPreviewMode); const className = getAnvilWidgetDOMId(widgetId); const element = document.querySelector(`.${className}`); diff --git a/app/client/src/layoutSystems/anvil/common/hooks/useWidgetBorderStyles.ts b/app/client/src/layoutSystems/anvil/common/hooks/useWidgetBorderStyles.ts index fea0cc19424c..1213f9134b3a 100644 --- a/app/client/src/layoutSystems/anvil/common/hooks/useWidgetBorderStyles.ts +++ b/app/client/src/layoutSystems/anvil/common/hooks/useWidgetBorderStyles.ts @@ -7,8 +7,8 @@ import { getWidgetsDistributingSpace, } from "layoutSystems/anvil/integrations/selectors"; import { useSelector } from "react-redux"; -import { combinedPreviewModeSelector } from "selectors/editorSelectors"; import { isWidgetFocused, isWidgetSelected } from "selectors/widgetSelectors"; +import { selectCombinedPreviewMode } from "selectors/gitModSelectors"; export function useWidgetBorderStyles(widgetId: string, widgetType: string) { /** Selectors */ @@ -32,7 +32,7 @@ export function useWidgetBorderStyles(widgetId: string, widgetType: string) { const widgetsEffectedBySpaceDistribution = useSelector( getWidgetsDistributingSpace, ); - const isPreviewMode = useSelector(combinedPreviewModeSelector); + const isPreviewMode = useSelector(selectCombinedPreviewMode); /** EO selectors */ diff --git a/app/client/src/layoutSystems/anvil/editor/AnvilEditorWidgetOnion.tsx b/app/client/src/layoutSystems/anvil/editor/AnvilEditorWidgetOnion.tsx index f5a6505a2be2..839c055f0f40 100644 --- a/app/client/src/layoutSystems/anvil/editor/AnvilEditorWidgetOnion.tsx +++ b/app/client/src/layoutSystems/anvil/editor/AnvilEditorWidgetOnion.tsx @@ -4,7 +4,7 @@ import type { BaseWidgetProps } from "widgets/BaseWidgetHOC/withBaseWidgetHOC"; import { AnvilWidgetComponent } from "../common/widgetComponent/AnvilWidgetComponent"; import { getWidgetSizeConfiguration } from "../utils/widgetUtils"; import { useSelector } from "react-redux"; -import { combinedPreviewModeSelector } from "selectors/editorSelectors"; +import { selectCombinedPreviewMode } from "selectors/gitModSelectors"; import { AnvilEditorFlexComponent } from "./AnvilEditorFlexComponent"; import { AnvilFlexComponent } from "../common/AnvilFlexComponent"; import { SKELETON_WIDGET_TYPE } from "constants/WidgetConstants"; @@ -25,7 +25,7 @@ import { SKELETON_WIDGET_TYPE } from "constants/WidgetConstants"; * @returns Enhanced Widget */ export const AnvilEditorWidgetOnion = (props: BaseWidgetProps) => { - const isPreviewMode = useSelector(combinedPreviewModeSelector); + const isPreviewMode = useSelector(selectCombinedPreviewMode); const { widgetSize, WidgetWrapper } = useMemo(() => { return { widgetSize: getWidgetSizeConfiguration(props.type, props, isPreviewMode), diff --git a/app/client/src/layoutSystems/anvil/editor/hooks/useAnvilWidgetHover.ts b/app/client/src/layoutSystems/anvil/editor/hooks/useAnvilWidgetHover.ts index abdb88561f68..e51d921bf1bd 100644 --- a/app/client/src/layoutSystems/anvil/editor/hooks/useAnvilWidgetHover.ts +++ b/app/client/src/layoutSystems/anvil/editor/hooks/useAnvilWidgetHover.ts @@ -2,7 +2,7 @@ import type { AppState } from "ee/reducers"; import { getAnvilSpaceDistributionStatus } from "layoutSystems/anvil/integrations/selectors"; import { useCallback, useEffect } from "react"; import { useSelector } from "react-redux"; -import { combinedPreviewModeSelector } from "selectors/editorSelectors"; +import { selectCombinedPreviewMode } from "selectors/gitModSelectors"; import { isWidgetFocused } from "selectors/widgetSelectors"; import { useWidgetSelection } from "utils/hooks/useWidgetSelection"; @@ -12,7 +12,7 @@ export const useAnvilWidgetHover = ( ) => { // Retrieve state from the Redux store const isFocused = useSelector(isWidgetFocused(widgetId)); - const isPreviewMode = useSelector(combinedPreviewModeSelector); + const isPreviewMode = useSelector(selectCombinedPreviewMode); const isDistributingSpace = useSelector(getAnvilSpaceDistributionStatus); const isDragging = useSelector( (state: AppState) => state.ui.widgetDragResize.isDragging, diff --git a/app/client/src/layoutSystems/anvil/integrations/sagas/LayoutElementPositionsSaga.ts b/app/client/src/layoutSystems/anvil/integrations/sagas/LayoutElementPositionsSaga.ts index a882919710b1..2cddcc974bc8 100644 --- a/app/client/src/layoutSystems/anvil/integrations/sagas/LayoutElementPositionsSaga.ts +++ b/app/client/src/layoutSystems/anvil/integrations/sagas/LayoutElementPositionsSaga.ts @@ -8,7 +8,7 @@ import log from "loglevel"; import type { AppState } from "ee/reducers"; import { ReduxActionTypes } from "ee/constants/ReduxActionConstants"; import { APP_MODE } from "entities/App"; -import { combinedPreviewModeSelector } from "selectors/editorSelectors"; +import { selectCombinedPreviewMode } from "selectors/gitModSelectors"; import { getAppMode } from "ee/selectors/entitiesSelector"; import type { RefObject } from "react"; import { getAnvilSpaceDistributionStatus } from "../selectors"; @@ -87,7 +87,7 @@ function* readAndUpdateLayoutElementPositions() { // The positions are used only in the editor, so we should not be running this saga // in the viewer or the preview mode. - const isPreviewMode: boolean = yield select(combinedPreviewModeSelector); + const isPreviewMode: boolean = yield select(selectCombinedPreviewMode); const appMode: APP_MODE = yield select(getAppMode); if (isPreviewMode || appMode === APP_MODE.PUBLISHED) { diff --git a/app/client/src/layoutSystems/anvil/layoutComponents/components/zone/useZoneMinWidth.ts b/app/client/src/layoutSystems/anvil/layoutComponents/components/zone/useZoneMinWidth.ts index fe49ee655230..c8ba600c5fb6 100644 --- a/app/client/src/layoutSystems/anvil/layoutComponents/components/zone/useZoneMinWidth.ts +++ b/app/client/src/layoutSystems/anvil/layoutComponents/components/zone/useZoneMinWidth.ts @@ -3,22 +3,20 @@ import { ChildrenMapContext } from "layoutSystems/anvil/context/childrenMapConte import type { WidgetProps } from "widgets/BaseWidget"; import { RenderModes } from "constants/WidgetConstants"; import { useSelector } from "react-redux"; -import { - combinedPreviewModeSelector, - getRenderMode, -} from "selectors/editorSelectors"; +import { getRenderMode } from "selectors/editorSelectors"; import type { SizeConfig } from "WidgetProvider/constants"; import { getWidgetSizeConfiguration } from "layoutSystems/anvil/utils/widgetUtils"; import type { CanvasWidgetsReduxState } from "reducers/entityReducers/canvasWidgetsReducer"; import { getWidgets } from "sagas/selectors"; import isObject from "lodash/isObject"; +import { selectCombinedPreviewMode } from "selectors/gitModSelectors"; export function useZoneMinWidth() { const childrenMap: Record = useContext(ChildrenMapContext); const widgets: CanvasWidgetsReduxState = useSelector(getWidgets); const renderMode: RenderModes = useSelector(getRenderMode); - const isPreviewMode: boolean = useSelector(combinedPreviewModeSelector); + const isPreviewMode: boolean = useSelector(selectCombinedPreviewMode); if (renderMode === RenderModes.CANVAS && !isPreviewMode) return "auto"; diff --git a/app/client/src/layoutSystems/anvil/sectionSpaceDistributor/SectionSpaceDistributor.tsx b/app/client/src/layoutSystems/anvil/sectionSpaceDistributor/SectionSpaceDistributor.tsx index fd719bfd1f6f..25e94d38d9e8 100644 --- a/app/client/src/layoutSystems/anvil/sectionSpaceDistributor/SectionSpaceDistributor.tsx +++ b/app/client/src/layoutSystems/anvil/sectionSpaceDistributor/SectionSpaceDistributor.tsx @@ -2,7 +2,7 @@ import { getLayoutElementPositions } from "layoutSystems/common/selectors"; import type { LayoutElementPosition } from "layoutSystems/common/types"; import React, { useMemo } from "react"; import { useSelector } from "react-redux"; -import { combinedPreviewModeSelector } from "selectors/editorSelectors"; +import { selectCombinedPreviewMode } from "selectors/gitModSelectors"; import type { WidgetLayoutProps } from "../utils/anvilTypes"; import { getWidgetByID } from "sagas/selectors"; import { getDefaultSpaceDistributed } from "./utils/spaceRedistributionSagaUtils"; @@ -113,7 +113,7 @@ export const SectionSpaceDistributor = ( props: SectionSpaceDistributorProps, ) => { const { zones } = props; - const isPreviewMode = useSelector(combinedPreviewModeSelector); + const isPreviewMode = useSelector(selectCombinedPreviewMode); const isWidgetSelectionBlocked = useSelector(getWidgetSelectionBlock); const isDragging = useSelector( (state) => state.ui.widgetDragResize.isDragging, diff --git a/app/client/src/layoutSystems/anvil/viewer/AnvilViewerWidgetOnion.tsx b/app/client/src/layoutSystems/anvil/viewer/AnvilViewerWidgetOnion.tsx index 99ca7dddf492..763785755918 100644 --- a/app/client/src/layoutSystems/anvil/viewer/AnvilViewerWidgetOnion.tsx +++ b/app/client/src/layoutSystems/anvil/viewer/AnvilViewerWidgetOnion.tsx @@ -5,7 +5,7 @@ import { AnvilWidgetComponent } from "../common/widgetComponent/AnvilWidgetCompo import type { SizeConfig } from "WidgetProvider/constants"; import { getWidgetSizeConfiguration } from "../utils/widgetUtils"; import { useSelector } from "react-redux"; -import { combinedPreviewModeSelector } from "selectors/editorSelectors"; +import { selectCombinedPreviewMode } from "selectors/gitModSelectors"; /** * AnvilViewerWidgetOnion @@ -20,7 +20,7 @@ import { combinedPreviewModeSelector } from "selectors/editorSelectors"; * @returns Enhanced Widget */ export const AnvilViewerWidgetOnion = (props: BaseWidgetProps) => { - const isPreviewMode = useSelector(combinedPreviewModeSelector); + const isPreviewMode = useSelector(selectCombinedPreviewMode); const widgetSize: SizeConfig = useMemo( () => getWidgetSizeConfiguration(props.type, props, isPreviewMode), [isPreviewMode, props.type], diff --git a/app/client/src/layoutSystems/autolayout/common/FlexComponent.tsx b/app/client/src/layoutSystems/autolayout/common/FlexComponent.tsx index 20edbf4ce0d8..334ca9fd95ec 100644 --- a/app/client/src/layoutSystems/autolayout/common/FlexComponent.tsx +++ b/app/client/src/layoutSystems/autolayout/common/FlexComponent.tsx @@ -4,10 +4,7 @@ import styled from "styled-components"; import { WIDGET_PADDING } from "constants/WidgetConstants"; import { useSelector } from "react-redux"; -import { - combinedPreviewModeSelector, - snipingModeSelector, -} from "selectors/editorSelectors"; +import { snipingModeSelector } from "selectors/editorSelectors"; import { getIsResizing } from "selectors/widgetSelectors"; import { useClickToSelectWidget } from "utils/hooks/useClickToSelectWidget"; import { usePositionedContainerZIndex } from "utils/hooks/usePositionedContainerZIndex"; @@ -16,6 +13,7 @@ import { RESIZE_BORDER_BUFFER } from "layoutSystems/common/resizer/common"; import { checkIsDropTarget } from "WidgetProvider/factory/helpers"; import type { FlexComponentProps } from "../../autolayout/utils/types"; import { useHoverToFocusWidget } from "utils/hooks/useHoverToFocusWidget"; +import { selectCombinedPreviewMode } from "selectors/gitModSelectors"; const FlexWidget = styled.div` position: relative; @@ -58,7 +56,7 @@ export function FlexComponent(props: FlexComponentProps) { )} t--widget-${props.widgetName.toLowerCase()}`, [props.parentId, props.widgetId, props.widgetType, props.widgetName], ); - const isPreviewMode = useSelector(combinedPreviewModeSelector); + const isPreviewMode = useSelector(selectCombinedPreviewMode); const isResizing = useSelector(getIsResizing); const widgetDimensionsViewCss = { diff --git a/app/client/src/layoutSystems/common/dropTarget/DropTargetComponent.tsx b/app/client/src/layoutSystems/common/dropTarget/DropTargetComponent.tsx index d1df63825448..fcb93c9205a6 100644 --- a/app/client/src/layoutSystems/common/dropTarget/DropTargetComponent.tsx +++ b/app/client/src/layoutSystems/common/dropTarget/DropTargetComponent.tsx @@ -21,10 +21,7 @@ import { } from "actions/autoHeightActions"; import { useDispatch } from "react-redux"; import { getDragDetails } from "sagas/selectors"; -import { - combinedPreviewModeSelector, - getOccupiedSpacesSelectorForContainer, -} from "selectors/editorSelectors"; +import { getOccupiedSpacesSelectorForContainer } from "selectors/editorSelectors"; import { getCanvasSnapRows } from "utils/WidgetPropsUtils"; import { useAutoHeightUIState } from "utils/hooks/autoHeightUIHooks"; import { useShowPropertyPane } from "utils/hooks/dragResizeHooks"; @@ -42,6 +39,7 @@ import { import DragLayerComponent from "./DragLayerComponent"; import Onboarding from "./OnBoarding"; import { isDraggingBuildingBlockToCanvas } from "selectors/buildingBlocksSelectors"; +import { selectCombinedPreviewMode } from "selectors/gitModSelectors"; export type DropTargetComponentProps = PropsWithChildren<{ snapColumnSpace: number; @@ -196,7 +194,7 @@ function useUpdateRows( export function DropTargetComponent(props: DropTargetComponentProps) { // Get if this is in preview mode. - const isPreviewMode = useSelector(combinedPreviewModeSelector); + const isPreviewMode = useSelector(selectCombinedPreviewMode); const isAppSettingsPaneWithNavigationTabOpen = useSelector( getIsAppSettingsPaneWithNavigationTabOpen, ); diff --git a/app/client/src/layoutSystems/common/resizer/ModalResizableLayer.tsx b/app/client/src/layoutSystems/common/resizer/ModalResizableLayer.tsx index 559556bbbf42..1a516b9623fe 100644 --- a/app/client/src/layoutSystems/common/resizer/ModalResizableLayer.tsx +++ b/app/client/src/layoutSystems/common/resizer/ModalResizableLayer.tsx @@ -19,11 +19,9 @@ import { } from "./ResizeStyledComponents"; import type { UIElementSize } from "./ResizableUtils"; import { useModalWidth } from "widgets/ModalWidget/component/useModalWidth"; -import { - combinedPreviewModeSelector, - snipingModeSelector, -} from "selectors/editorSelectors"; +import { snipingModeSelector } from "selectors/editorSelectors"; import { getWidgetSelectionBlock } from "../../../selectors/ui"; +import { selectCombinedPreviewMode } from "selectors/gitModSelectors"; const minSize = 100; /** @@ -101,7 +99,7 @@ export const ModalResizableLayer = ({ widgetType: "MODAL_WIDGET", }); }; - const isPreviewMode = useSelector(combinedPreviewModeSelector); + const isPreviewMode = useSelector(selectCombinedPreviewMode); const isSnipingMode = useSelector(snipingModeSelector); const isWidgetSelectionBlocked = useSelector(getWidgetSelectionBlock); const enableResizing = diff --git a/app/client/src/layoutSystems/common/resizer/ResizableComponent.tsx b/app/client/src/layoutSystems/common/resizer/ResizableComponent.tsx index f0336f382b87..fb5aca05d16f 100644 --- a/app/client/src/layoutSystems/common/resizer/ResizableComponent.tsx +++ b/app/client/src/layoutSystems/common/resizer/ResizableComponent.tsx @@ -17,10 +17,7 @@ import { FixedLayoutResizable } from "layoutSystems/fixedlayout/common/resizer/F import { SelectionRequestType } from "sagas/WidgetSelectUtils"; import { getIsAutoLayout } from "selectors/canvasSelectors"; import { getIsAppSettingsPaneWithNavigationTabOpen } from "selectors/appSettingsPaneSelectors"; -import { - combinedPreviewModeSelector, - snipingModeSelector, -} from "selectors/editorSelectors"; +import { snipingModeSelector } from "selectors/editorSelectors"; import { getParentToOpenSelector, isWidgetFocused, @@ -69,6 +66,7 @@ import { getAltBlockWidgetSelection, getWidgetSelectionBlock, } from "selectors/ui"; +import { selectCombinedPreviewMode } from "selectors/gitModSelectors"; export type ResizableComponentProps = WidgetProps & { paddingOffset: number; @@ -83,7 +81,7 @@ export const ResizableComponent = memo(function ResizableComponent( const isAutoLayout = useSelector(getIsAutoLayout); const Resizable = isAutoLayout ? AutoLayoutResizable : FixedLayoutResizable; const isSnipingMode = useSelector(snipingModeSelector); - const isPreviewMode = useSelector(combinedPreviewModeSelector); + const isPreviewMode = useSelector(selectCombinedPreviewMode); const isWidgetSelectionBlock = useSelector(getWidgetSelectionBlock); const isAltWidgetSelectionBlock = useSelector(getAltBlockWidgetSelection); const isAppSettingsPaneWithNavigationTabOpen: boolean = useSelector( diff --git a/app/client/src/layoutSystems/common/utils/LayoutElementPositionsObserver/usePositionObserver.ts b/app/client/src/layoutSystems/common/utils/LayoutElementPositionsObserver/usePositionObserver.ts index 1d5a9c38f354..9c981c66f397 100644 --- a/app/client/src/layoutSystems/common/utils/LayoutElementPositionsObserver/usePositionObserver.ts +++ b/app/client/src/layoutSystems/common/utils/LayoutElementPositionsObserver/usePositionObserver.ts @@ -3,7 +3,7 @@ import { useEffect } from "react"; import { positionObserver } from "."; import { APP_MODE } from "entities/App"; import { useSelector } from "react-redux"; -import { combinedPreviewModeSelector } from "selectors/editorSelectors"; +import { selectCombinedPreviewMode } from "selectors/gitModSelectors"; import { getAppMode } from "ee/selectors/entitiesSelector"; import { getAnvilLayoutDOMId, getAnvilWidgetDOMId } from "./utils"; import { LayoutComponentTypes } from "layoutSystems/anvil/utils/anvilTypes"; @@ -13,7 +13,7 @@ export function useObserveDetachedWidget(widgetId: string) { // We don't need the observer in preview mode or the published app // This is because the positions need to be observed only to enable // editor features - const isPreviewMode = useSelector(combinedPreviewModeSelector); + const isPreviewMode = useSelector(selectCombinedPreviewMode); const appMode = useSelector(getAppMode); if (isPreviewMode || appMode === APP_MODE.PUBLISHED) { @@ -54,7 +54,7 @@ export function usePositionObserver( }, ref: RefObject, ) { - const isPreviewMode = useSelector(combinedPreviewModeSelector); + const isPreviewMode = useSelector(selectCombinedPreviewMode); const appMode = useSelector(getAppMode); useEffect(() => { diff --git a/app/client/src/layoutSystems/common/widgetName/index.tsx b/app/client/src/layoutSystems/common/widgetName/index.tsx index bb8c265946e5..8d5770b995a0 100644 --- a/app/client/src/layoutSystems/common/widgetName/index.tsx +++ b/app/client/src/layoutSystems/common/widgetName/index.tsx @@ -8,7 +8,6 @@ import { SelectionRequestType } from "sagas/WidgetSelectUtils"; import { getIsAppSettingsPaneWithNavigationTabOpen } from "selectors/appSettingsPaneSelectors"; import { hideErrors } from "selectors/debuggerSelectors"; import { - combinedPreviewModeSelector, getIsAutoLayout, snipingModeSelector, } from "selectors/editorSelectors"; @@ -31,6 +30,7 @@ import { RESIZE_BORDER_BUFFER } from "layoutSystems/common/resizer/common"; import { Layers } from "constants/Layers"; import memoize from "micro-memoize"; import { NavigationMethod } from "utils/history"; +import { selectCombinedPreviewMode } from "selectors/gitModSelectors"; const WidgetTypes = WidgetFactory.widgetTypes; @@ -78,7 +78,7 @@ interface WidgetNameComponentProps { export function WidgetNameComponent(props: WidgetNameComponentProps) { const dispatch = useDispatch(); const isSnipingMode = useSelector(snipingModeSelector); - const isPreviewMode = useSelector(combinedPreviewModeSelector); + const isPreviewMode = useSelector(selectCombinedPreviewMode); const isAppSettingsPaneWithNavigationTabOpen = useSelector( getIsAppSettingsPaneWithNavigationTabOpen, ); diff --git a/app/client/src/layoutSystems/fixedlayout/common/autoHeightOverlay/index.tsx b/app/client/src/layoutSystems/fixedlayout/common/autoHeightOverlay/index.tsx index 89519283f7cb..48015d2efff1 100644 --- a/app/client/src/layoutSystems/fixedlayout/common/autoHeightOverlay/index.tsx +++ b/app/client/src/layoutSystems/fixedlayout/common/autoHeightOverlay/index.tsx @@ -3,7 +3,7 @@ import type { CSSProperties } from "react"; import React, { memo } from "react"; import { useSelector } from "react-redux"; import { getIsAppSettingsPaneWithNavigationTabOpen } from "selectors/appSettingsPaneSelectors"; -import { combinedPreviewModeSelector } from "selectors/editorSelectors"; +import { selectCombinedPreviewMode } from "selectors/gitModSelectors"; import type { WidgetProps } from "widgets/BaseWidget"; import AutoHeightOverlayWithStateContext from "./AutoHeightOverlayWithStateContext"; @@ -31,7 +31,7 @@ const AutoHeightOverlayContainer: React.FC = selectedWidgets, } = useSelector((state: AppState) => state.ui.widgetDragResize); - const isPreviewMode = useSelector(combinedPreviewModeSelector); + const isPreviewMode = useSelector(selectCombinedPreviewMode); const isAppSettingsPaneWithNavigationTabOpen = useSelector( getIsAppSettingsPaneWithNavigationTabOpen, ); diff --git a/app/client/src/layoutSystems/fixedlayout/editor/FixedLayoutCanvasArenas/CanvasSelectionArena.tsx b/app/client/src/layoutSystems/fixedlayout/editor/FixedLayoutCanvasArenas/CanvasSelectionArena.tsx index c0cf29167981..c299eaef18db 100644 --- a/app/client/src/layoutSystems/fixedlayout/editor/FixedLayoutCanvasArenas/CanvasSelectionArena.tsx +++ b/app/client/src/layoutSystems/fixedlayout/editor/FixedLayoutCanvasArenas/CanvasSelectionArena.tsx @@ -21,7 +21,6 @@ import { getIsDraggingForSelection, } from "selectors/canvasSelectors"; import { - combinedPreviewModeSelector, getCurrentApplicationLayout, getCurrentPageId, } from "selectors/editorSelectors"; @@ -31,6 +30,7 @@ import type { XYCord } from "layoutSystems/common/canvasArenas/ArenaTypes"; import { useCanvasDragToScroll } from "layoutSystems/common/canvasArenas/useCanvasDragToScroll"; import { StickyCanvasArena } from "layoutSystems/common/canvasArenas/StickyCanvasArena"; import { getWidgetSelectionBlock } from "../../../../selectors/ui"; +import { selectCombinedPreviewMode } from "selectors/gitModSelectors"; export interface SelectedArenaDimensions { top: number; @@ -71,7 +71,7 @@ export function CanvasSelectionArena({ (parentWidget && parentWidget.detachFromLayout) ); const appMode = useSelector(getAppMode); - const isPreviewMode = useSelector(combinedPreviewModeSelector); + const isPreviewMode = useSelector(selectCombinedPreviewMode); const isWidgetSelectionBlocked = useSelector(getWidgetSelectionBlock); const isAppSettingsPaneWithNavigationTabOpen = useSelector( getIsAppSettingsPaneWithNavigationTabOpen, diff --git a/app/client/src/pages/AppViewer/Navigation/Sidebar.tsx b/app/client/src/pages/AppViewer/Navigation/Sidebar.tsx index 3b6b80aa7328..5ad23ff2e567 100644 --- a/app/client/src/pages/AppViewer/Navigation/Sidebar.tsx +++ b/app/client/src/pages/AppViewer/Navigation/Sidebar.tsx @@ -12,10 +12,7 @@ import ShareButton from "./components/ShareButton"; import PrimaryCTA from "../PrimaryCTA"; import { useHref } from "pages/Editor/utils"; import { builderURL } from "ee/RouteBuilder"; -import { - combinedPreviewModeSelector, - getCurrentBasePageId, -} from "selectors/editorSelectors"; +import { getCurrentBasePageId } from "selectors/editorSelectors"; import type { User } from "constants/userConstants"; import SidebarProfileComponent from "./components/SidebarProfileComponent"; import CollapseButton from "./components/CollapseButton"; @@ -36,6 +33,7 @@ import MenuItemContainer from "./components/MenuItemContainer"; import BackToAppsButton from "./components/BackToAppsButton"; import { IDE_HEADER_HEIGHT } from "@appsmith/ads"; import { BOTTOM_BAR_HEIGHT } from "components/BottomBar/constants"; +import { selectCombinedPreviewMode } from "selectors/gitModSelectors"; interface SidebarProps { currentApplicationDetails?: ApplicationPayload; @@ -81,7 +79,7 @@ export function Sidebar(props: SidebarProps) { const isPinned = useSelector(getAppSidebarPinned); const [isOpen, setIsOpen] = useState(true); const { x } = useMouse(); - const isPreviewMode = useSelector(combinedPreviewModeSelector); + const isPreviewMode = useSelector(selectCombinedPreviewMode); const isAppSettingsPaneWithNavigationTabOpen = useSelector( getIsAppSettingsPaneWithNavigationTabOpen, ); diff --git a/app/client/src/pages/AppViewer/Navigation/TopInline.tsx b/app/client/src/pages/AppViewer/Navigation/TopInline.tsx index f15dd093ff21..af09e8497fd1 100644 --- a/app/client/src/pages/AppViewer/Navigation/TopInline.tsx +++ b/app/client/src/pages/AppViewer/Navigation/TopInline.tsx @@ -5,14 +5,12 @@ import MenuItem from "./components/MenuItem"; import { Container } from "./TopInline.styled"; import MenuItemContainer from "./components/MenuItemContainer"; import MoreDropdownButton from "./components/MoreDropdownButton"; -import { - combinedPreviewModeSelector, - getCanvasWidth, -} from "selectors/editorSelectors"; +import { getCanvasWidth } from "selectors/editorSelectors"; import { useSelector } from "react-redux"; import { getIsAppSettingsPaneWithNavigationTabOpen } from "selectors/appSettingsPaneSelectors"; import { throttle } from "lodash"; import type { NavigationProps } from "./constants"; +import { selectCombinedPreviewMode } from "selectors/gitModSelectors"; export function TopInline(props: NavigationProps) { const { currentApplicationDetails, pages } = props; @@ -23,7 +21,7 @@ export function TopInline(props: NavigationProps) { const maxMenuItemWidth = 220; const [maxMenuItemsThatCanFit, setMaxMenuItemsThatCanFit] = useState(0); const { width: screenWidth } = useWindowSizeHooks(); - const isPreviewMode = useSelector(combinedPreviewModeSelector); + const isPreviewMode = useSelector(selectCombinedPreviewMode); const isAppSettingsPaneWithNavigationTabOpen = useSelector( getIsAppSettingsPaneWithNavigationTabOpen, ); diff --git a/app/client/src/pages/Editor/Canvas.tsx b/app/client/src/pages/Editor/Canvas.tsx index 742e6d8a74b1..c34f2fc358c8 100644 --- a/app/client/src/pages/Editor/Canvas.tsx +++ b/app/client/src/pages/Editor/Canvas.tsx @@ -5,7 +5,7 @@ import * as Sentry from "@sentry/react"; import { useDispatch, useSelector } from "react-redux"; import type { CanvasWidgetStructure } from "WidgetProvider/constants"; import useWidgetFocus from "utils/hooks/useWidgetFocus"; -import { combinedPreviewModeSelector } from "selectors/editorSelectors"; +import { selectCombinedPreviewMode } from "selectors/gitModSelectors"; import { getSelectedAppTheme } from "selectors/appThemingSelectors"; import { getViewportClassName } from "layoutSystems/autolayout/utils/AutoLayoutUtils"; import { @@ -44,7 +44,7 @@ const Wrapper = styled.section<{ `; const Canvas = (props: CanvasProps) => { const { canvasWidth } = props; - const isPreviewMode = useSelector(combinedPreviewModeSelector); + const isPreviewMode = useSelector(selectCombinedPreviewMode); const isAppSettingsPaneWithNavigationTabOpen = useSelector( getIsAppSettingsPaneWithNavigationTabOpen, ); diff --git a/app/client/src/pages/Editor/WidgetsEditor/components/NavigationAdjustedPageViewer.tsx b/app/client/src/pages/Editor/WidgetsEditor/components/NavigationAdjustedPageViewer.tsx index 7ec7cdd62ec4..6eb0f1ff10a6 100644 --- a/app/client/src/pages/Editor/WidgetsEditor/components/NavigationAdjustedPageViewer.tsx +++ b/app/client/src/pages/Editor/WidgetsEditor/components/NavigationAdjustedPageViewer.tsx @@ -4,7 +4,7 @@ import { EditorState } from "ee/entities/IDE/constants"; import { useCurrentAppState } from "pages/Editor/IDE/hooks/useCurrentAppState"; import { getIsAppSettingsPaneWithNavigationTabOpen } from "selectors/appSettingsPaneSelectors"; import { useSelector } from "react-redux"; -import { combinedPreviewModeSelector } from "selectors/editorSelectors"; +import { selectCombinedPreviewMode } from "selectors/gitModSelectors"; import { PageViewWrapper } from "pages/AppViewer/AppPage"; import classNames from "classnames"; import { APP_MODE } from "entities/App"; @@ -27,7 +27,7 @@ import { getIsAnvilLayout } from "layoutSystems/anvil/integrations/selectors"; export const NavigationAdjustedPageViewer = (props: { children: ReactNode; }) => { - const isPreview = useSelector(combinedPreviewModeSelector); + const isPreview = useSelector(selectCombinedPreviewMode); const currentApplicationDetails = useSelector(getCurrentApplication); const isAppSidebarPinned = useSelector(getAppSidebarPinned); const sidebarWidth = useSelector(getSidebarWidth); diff --git a/app/client/src/pages/Editor/WidgetsEditor/components/NavigationPreview.tsx b/app/client/src/pages/Editor/WidgetsEditor/components/NavigationPreview.tsx index 0478d6f63439..8f2aa0e23c24 100644 --- a/app/client/src/pages/Editor/WidgetsEditor/components/NavigationPreview.tsx +++ b/app/client/src/pages/Editor/WidgetsEditor/components/NavigationPreview.tsx @@ -2,7 +2,7 @@ import type { LegacyRef } from "react"; import React, { forwardRef } from "react"; import classNames from "classnames"; import { useSelector } from "react-redux"; -import { combinedPreviewModeSelector } from "selectors/editorSelectors"; +import { selectCombinedPreviewMode } from "selectors/gitModSelectors"; import { Navigation } from "pages/AppViewer/Navigation"; import { useCurrentAppState } from "pages/Editor/IDE/hooks/useCurrentAppState"; import { EditorState } from "ee/entities/IDE/constants"; @@ -22,7 +22,7 @@ const NavigationPreview = forwardRef( const appState = useCurrentAppState(); const isAppSettingsPaneWithNavigationTabOpen = appState === EditorState.SETTINGS && isNavigationSelectedInSettings; - const isPreviewMode = useSelector(combinedPreviewModeSelector); + const isPreviewMode = useSelector(selectCombinedPreviewMode); return (
{ const allowDragToSelect = useAllowEditorDragToSelect(); const { isAutoHeightWithLimitsChanging } = useAutoHeightUIState(); const dispatch = useDispatch(); - const isCombinedPreviewMode = useSelector(combinedPreviewModeSelector); + const isCombinedPreviewMode = useSelector(selectCombinedPreviewMode); const handleWrapperClick = useCallback( (e) => { diff --git a/app/client/src/pages/Editor/WidgetsEditor/components/WidgetEditorNavigation.tsx b/app/client/src/pages/Editor/WidgetsEditor/components/WidgetEditorNavigation.tsx index 852c210685ee..d7b7d2869271 100644 --- a/app/client/src/pages/Editor/WidgetsEditor/components/WidgetEditorNavigation.tsx +++ b/app/client/src/pages/Editor/WidgetsEditor/components/WidgetEditorNavigation.tsx @@ -7,7 +7,7 @@ import { getIsAppSettingsPaneWithNavigationTabOpen, } from "selectors/appSettingsPaneSelectors"; import { useSelector } from "react-redux"; -import { combinedPreviewModeSelector } from "selectors/editorSelectors"; +import { selectCombinedPreviewMode } from "selectors/gitModSelectors"; import { getCurrentApplication } from "ee/selectors/applicationSelectors"; /** @@ -20,7 +20,7 @@ import { getCurrentApplication } from "ee/selectors/applicationSelectors"; export const useNavigationPreviewHeight = () => { const [navigationHeight, setNavigationHeight] = useState(0); const navigationPreviewRef = useRef(null); - const isPreviewMode = useSelector(combinedPreviewModeSelector); + const isPreviewMode = useSelector(selectCombinedPreviewMode); const appSettingsPaneContext = useSelector(getAppSettingsPaneContext); const currentApplicationDetails = useSelector(getCurrentApplication); @@ -54,7 +54,7 @@ type DivRef = React.Ref; */ export const WidgetEditorNavigation = forwardRef( (props, navigationPreviewRef: DivRef) => { - const isPreviewMode = useSelector(combinedPreviewModeSelector); + const isPreviewMode = useSelector(selectCombinedPreviewMode); const isNavigationSelectedInSettings = useSelector( getIsAppSettingsPaneWithNavigationTabOpen, ); diff --git a/app/client/src/pages/Editor/commons/EditorWrapperContainer.tsx b/app/client/src/pages/Editor/commons/EditorWrapperContainer.tsx index 92fab1972022..3b34d1beecd4 100644 --- a/app/client/src/pages/Editor/commons/EditorWrapperContainer.tsx +++ b/app/client/src/pages/Editor/commons/EditorWrapperContainer.tsx @@ -2,11 +2,11 @@ import React from "react"; import styled from "styled-components"; import classNames from "classnames"; import { useSelector } from "react-redux"; -import { combinedPreviewModeSelector } from "../../../selectors/editorSelectors"; import { IDE_HEADER_HEIGHT } from "@appsmith/ads"; import { BOTTOM_BAR_HEIGHT } from "../../../components/BottomBar/constants"; import { PROTECTED_CALLOUT_HEIGHT } from "../IDE/ProtectedCallout"; import { useGitProtectedMode } from "../gitSync/hooks/modHooks"; +import { selectCombinedPreviewMode } from "selectors/gitModSelectors"; interface EditorWrapperContainerProps { children: React.ReactNode; @@ -25,7 +25,7 @@ const Wrapper = styled.div<{ `; function EditorWrapperContainer({ children }: EditorWrapperContainerProps) { - const isCombinedPreviewMode = useSelector(combinedPreviewModeSelector); + const isCombinedPreviewMode = useSelector(selectCombinedPreviewMode); const isProtectedMode = useGitProtectedMode(); return ( diff --git a/app/client/src/pages/Editor/index.tsx b/app/client/src/pages/Editor/index.tsx index 65d78f238046..746b7ca56733 100644 --- a/app/client/src/pages/Editor/index.tsx +++ b/app/client/src/pages/Editor/index.tsx @@ -209,14 +209,14 @@ class Editor extends Component { return ( - -
- - - - {`${this.props.currentApplicationName} | Editor | Appsmith`} - - +
+ + + + {`${this.props.currentApplicationName} | Editor | Appsmith`} + + + @@ -229,9 +229,9 @@ class Editor extends Component { -
- - + +
+
); } diff --git a/app/client/src/sagas/autoHeightSagas/helpers.ts b/app/client/src/sagas/autoHeightSagas/helpers.ts index da276f65d769..3ac3086a9d53 100644 --- a/app/client/src/sagas/autoHeightSagas/helpers.ts +++ b/app/client/src/sagas/autoHeightSagas/helpers.ts @@ -11,7 +11,7 @@ import type { } from "reducers/entityReducers/canvasWidgetsReducer"; import { select } from "redux-saga/effects"; import { getWidgetMetaProps, getWidgets } from "sagas/selectors"; -import { combinedPreviewModeSelector } from "selectors/editorSelectors"; +import { selectCombinedPreviewMode } from "selectors/gitModSelectors"; import { getAppMode } from "ee/selectors/entitiesSelector"; import { isAutoHeightEnabledForWidget } from "widgets/WidgetUtils"; import { getCanvasHeightOffset } from "utils/WidgetSizeUtils"; @@ -20,7 +20,7 @@ import type { DataTree } from "entities/DataTree/dataTreeTypes"; import { getDataTree } from "selectors/dataTreeSelectors"; export function* shouldWidgetsCollapse() { - const isPreviewMode: boolean = yield select(combinedPreviewModeSelector); + const isPreviewMode: boolean = yield select(selectCombinedPreviewMode); const appMode: APP_MODE = yield select(getAppMode); return isPreviewMode || appMode === APP_MODE.PUBLISHED; diff --git a/app/client/src/selectors/debuggerSelectors.tsx b/app/client/src/selectors/debuggerSelectors.tsx index 89c2c46df479..624fae4f290f 100644 --- a/app/client/src/selectors/debuggerSelectors.tsx +++ b/app/client/src/selectors/debuggerSelectors.tsx @@ -11,8 +11,8 @@ import { isWidget, } from "ee/workers/Evaluation/evaluationUtils"; import { getDataTree } from "./dataTreeSelectors"; -import { combinedPreviewModeSelector } from "./editorSelectors"; import type { CanvasDebuggerState } from "reducers/uiReducers/debuggerReducer"; +import { selectCombinedPreviewMode } from "./gitModSelectors"; interface ErrorObejct { [k: string]: Log; @@ -169,7 +169,7 @@ export const getDebuggerOpen = (state: AppState) => state.ui.debugger.isOpen; export const showDebuggerFlag = createSelector( getDebuggerOpen, - combinedPreviewModeSelector, + selectCombinedPreviewMode, (isOpen, isPreview) => isOpen && !isPreview, ); diff --git a/app/client/src/selectors/editorSelectors.tsx b/app/client/src/selectors/editorSelectors.tsx index a37768af9b81..39bd1d46c1b6 100644 --- a/app/client/src/selectors/editorSelectors.tsx +++ b/app/client/src/selectors/editorSelectors.tsx @@ -49,8 +49,6 @@ import { getIsAnvilLayout } from "layoutSystems/anvil/integrations/selectors"; import { getCurrentApplication } from "ee/selectors/applicationSelectors"; import type { Page } from "entities/Page"; import { objectKeys } from "@appsmith/utils"; -import { selectGitProtectedMode } from "./gitModSelectors"; -import { applicationArtifact } from "git/artifact-helpers/application"; const getIsDraggingOrResizing = (state: AppState) => state.ui.widgetDragResize.isResizing || state.ui.widgetDragResize.isDragging; @@ -992,16 +990,3 @@ export const getGsheetToken = (state: AppState) => export const getGsheetProjectID = (state: AppState) => state.entities.datasources.gsheetProjectID; - -export const combinedPreviewModeSelector = createSelector( - previewModeSelector, - (state: AppState) => { - const baseApplicationId = getCurrentBaseApplicationId(state); - - return selectGitProtectedMode( - state, - applicationArtifact(baseApplicationId), - ); - }, - (isPreviewMode, isProtectedMode) => isPreviewMode || isProtectedMode, -); diff --git a/app/client/src/selectors/gitModSelectors.ts b/app/client/src/selectors/gitModSelectors.ts index dfd25de98870..3c24a42e3f34 100644 --- a/app/client/src/selectors/gitModSelectors.ts +++ b/app/client/src/selectors/gitModSelectors.ts @@ -9,6 +9,8 @@ import { selectGitProtectedMode as selectGitProtectedModeNew, type GitArtifactDef, } from "git"; +import { getCurrentBaseApplicationId } from "./editorSelectors"; +import { applicationArtifact } from "git/artifact-helpers/application"; export const selectGitModEnabled = createSelector( selectFeatureFlags, @@ -41,3 +43,16 @@ export function selectGitProtectedMode( return selectGitProtectedModeNew(state, artifactDef); } } + +export const selectCombinedPreviewMode = createSelector( + protectedModeSelector, + (state: AppState) => { + const baseApplicationId = getCurrentBaseApplicationId(state); + + return selectGitProtectedMode( + state, + applicationArtifact(baseApplicationId), + ); + }, + (isPreviewMode, isProtectedMode) => isPreviewMode || isProtectedMode, +); diff --git a/app/client/src/selectors/widgetDragSelectors.ts b/app/client/src/selectors/widgetDragSelectors.ts index 0a2b35eb7e1f..21d5848d5175 100644 --- a/app/client/src/selectors/widgetDragSelectors.ts +++ b/app/client/src/selectors/widgetDragSelectors.ts @@ -1,11 +1,9 @@ import type { AppState } from "ee/reducers"; import { createSelector } from "reselect"; import { getIsAppSettingsPaneWithNavigationTabOpen } from "./appSettingsPaneSelectors"; -import { - combinedPreviewModeSelector, - snipingModeSelector, -} from "./editorSelectors"; +import { snipingModeSelector } from "./editorSelectors"; import { getWidgetSelectionBlock } from "./ui"; +import { selectCombinedPreviewMode } from "./gitModSelectors"; export const getIsDragging = (state: AppState) => state.ui.widgetDragResize.isDragging; @@ -23,7 +21,7 @@ export const getShouldAllowDrag = createSelector( getIsResizing, getIsDragging, getIsDraggingDisabledInEditor, - combinedPreviewModeSelector, + selectCombinedPreviewMode, snipingModeSelector, getIsAppSettingsPaneWithNavigationTabOpen, getWidgetSelectionBlock, diff --git a/app/client/src/selectors/widgetSelectors.ts b/app/client/src/selectors/widgetSelectors.ts index 4d45777ef4c9..35d648da50bf 100644 --- a/app/client/src/selectors/widgetSelectors.ts +++ b/app/client/src/selectors/widgetSelectors.ts @@ -21,8 +21,8 @@ import { APP_MODE } from "entities/App"; import { getIsTableFilterPaneVisible } from "selectors/tableFilterSelectors"; import { getIsAutoHeightWithLimitsChanging } from "utils/hooks/autoHeightUIHooks"; import { getIsPropertyPaneVisible } from "./propertyPaneSelectors"; -import { combinedPreviewModeSelector } from "./editorSelectors"; import { getIsAnvilLayout } from "layoutSystems/anvil/integrations/selectors"; +import { selectCombinedPreviewMode } from "./gitModSelectors"; export const getIsDraggingOrResizing = (state: AppState) => state.ui.widgetDragResize.isResizing || state.ui.widgetDragResize.isDragging; @@ -186,7 +186,7 @@ export const shouldWidgetIgnoreClicksSelector = (widgetId: string) => { (state: AppState) => state.ui.widgetDragResize.isDragging, (state: AppState) => state.ui.canvasSelection.isDraggingForSelection, getAppMode, - combinedPreviewModeSelector, + selectCombinedPreviewMode, getIsAutoHeightWithLimitsChanging, getAltBlockWidgetSelection, ( diff --git a/app/client/src/utils/hooks/useAllowEditorDragToSelect.ts b/app/client/src/utils/hooks/useAllowEditorDragToSelect.ts index e074a099ac70..a09f5492d648 100644 --- a/app/client/src/utils/hooks/useAllowEditorDragToSelect.ts +++ b/app/client/src/utils/hooks/useAllowEditorDragToSelect.ts @@ -1,13 +1,11 @@ import type { AppState } from "ee/reducers"; -import { - snipingModeSelector, - combinedPreviewModeSelector, -} from "selectors/editorSelectors"; +import { snipingModeSelector } from "selectors/editorSelectors"; import { useSelector } from "react-redux"; import { getIsAppSettingsPaneWithNavigationTabOpen } from "selectors/appSettingsPaneSelectors"; import { getLayoutSystemType } from "selectors/layoutSystemSelectors"; import { LayoutSystemTypes } from "layoutSystems/types"; import { getWidgetSelectionBlock } from "../../selectors/ui"; +import { selectCombinedPreviewMode } from "selectors/gitModSelectors"; export const useAllowEditorDragToSelect = () => { // This state tells us whether a `ResizableComponent` is resizing @@ -42,7 +40,7 @@ export const useAllowEditorDragToSelect = () => { // True when any widget is dragging or resizing, including this one const isResizingOrDragging = !!isResizing || !!isDragging || !!isSelecting; const isSnipingMode = useSelector(snipingModeSelector); - const isPreviewMode = useSelector(combinedPreviewModeSelector); + const isPreviewMode = useSelector(selectCombinedPreviewMode); const isAppSettingsPaneWithNavigationTabOpen = useSelector( getIsAppSettingsPaneWithNavigationTabOpen, ); diff --git a/app/client/src/utils/hooks/useHoverToFocusWidget.ts b/app/client/src/utils/hooks/useHoverToFocusWidget.ts index 10e5f764f06e..a6cf7962de9a 100644 --- a/app/client/src/utils/hooks/useHoverToFocusWidget.ts +++ b/app/client/src/utils/hooks/useHoverToFocusWidget.ts @@ -2,7 +2,7 @@ import { useWidgetSelection } from "./useWidgetSelection"; import { useSelector } from "react-redux"; import { isWidgetFocused } from "selectors/widgetSelectors"; import { getAnvilSpaceDistributionStatus } from "layoutSystems/anvil/integrations/selectors"; -import { combinedPreviewModeSelector } from "selectors/editorSelectors"; +import { selectCombinedPreviewMode } from "selectors/gitModSelectors"; import type { AppState } from "ee/reducers"; import type React from "react"; import { useCurrentAppState } from "pages/Editor/IDE/hooks/useCurrentAppState"; @@ -35,7 +35,7 @@ export const useHoverToFocusWidget = ( const isResizingOrDragging = isResizing || isDragging; // This state tells us whether space redistribution is in process const isDistributingSpace = useSelector(getAnvilSpaceDistributionStatus); - const isPreviewMode = useSelector(combinedPreviewModeSelector); + const isPreviewMode = useSelector(selectCombinedPreviewMode); // When mouse is over this draggable const handleMouseOver = (e: React.MouseEvent) => { focusWidget && diff --git a/app/client/src/widgets/ChartWidget/component/index.tsx b/app/client/src/widgets/ChartWidget/component/index.tsx index 4ed693b142c3..f2a3280bd7a1 100644 --- a/app/client/src/widgets/ChartWidget/component/index.tsx +++ b/app/client/src/widgets/ChartWidget/component/index.tsx @@ -28,7 +28,7 @@ import { CustomEChartIFrameComponent } from "./CustomEChartIFrameComponent"; import type { AppState } from "ee/reducers"; import { connect } from "react-redux"; import { getWidgetPropsForPropertyPane } from "selectors/propertyPaneSelectors"; -import { combinedPreviewModeSelector } from "selectors/editorSelectors"; +import { selectCombinedPreviewMode } from "selectors/gitModSelectors"; import { getAppMode } from "ee/selectors/applicationSelectors"; import { APP_MODE } from "entities/App"; // Leaving this require here. Ref: https://stackoverflow.com/questions/41292559/could-not-find-a-declaration-file-for-module-module-name-path-to-module-nam/42505940#42505940 @@ -406,7 +406,7 @@ export const mapStateToProps = ( state: AppState, ownProps: ChartComponentProps, ) => { - const isPreviewMode = combinedPreviewModeSelector(state); + const isPreviewMode = selectCombinedPreviewMode(state); const appMode = getAppMode(state); return { diff --git a/app/client/src/widgets/CustomWidget/component/index.tsx b/app/client/src/widgets/CustomWidget/component/index.tsx index eb6740b48cd0..a3cf98d4afbb 100644 --- a/app/client/src/widgets/CustomWidget/component/index.tsx +++ b/app/client/src/widgets/CustomWidget/component/index.tsx @@ -19,7 +19,7 @@ import type { BoxShadow } from "components/designSystems/appsmith/WidgetStyleCon import type { Color } from "constants/Colors"; import { connect } from "react-redux"; import type { AppState } from "ee/reducers"; -import { combinedPreviewModeSelector } from "selectors/editorSelectors"; +import { selectCombinedPreviewMode } from "selectors/gitModSelectors"; import { getWidgetPropsForPropertyPane } from "selectors/propertyPaneSelectors"; import AnalyticsUtil from "ee/utils/AnalyticsUtil"; import { EVENTS } from "./customWidgetscript"; @@ -311,7 +311,7 @@ export const mapStateToProps = ( state: AppState, ownProps: CustomComponentProps, ) => { - const isPreviewMode = combinedPreviewModeSelector(state); + const isPreviewMode = selectCombinedPreviewMode(state); return { needsOverlay: diff --git a/app/client/src/widgets/IframeWidget/component/index.tsx b/app/client/src/widgets/IframeWidget/component/index.tsx index 1958ebd55e36..b16f5bdb2fcb 100644 --- a/app/client/src/widgets/IframeWidget/component/index.tsx +++ b/app/client/src/widgets/IframeWidget/component/index.tsx @@ -9,7 +9,7 @@ import { getAppMode } from "ee/selectors/applicationSelectors"; import { APP_MODE } from "entities/App"; import type { RenderMode } from "constants/WidgetConstants"; import { getAppsmithConfigs } from "ee/configs"; -import { combinedPreviewModeSelector } from "selectors/editorSelectors"; +import { selectCombinedPreviewMode } from "selectors/gitModSelectors"; interface IframeContainerProps { borderColor?: string; @@ -145,7 +145,7 @@ function IframeComponent(props: IframeComponentProps) { }, [srcDoc]); const appMode = useSelector(getAppMode); - const isPreviewMode = useSelector(combinedPreviewModeSelector); + const isPreviewMode = useSelector(selectCombinedPreviewMode); const selectedWidget = useSelector(getWidgetPropsForPropertyPane); return ( diff --git a/app/client/src/widgets/withWidgetProps.tsx b/app/client/src/widgets/withWidgetProps.tsx index 6eef5897bc3f..6e182b9b04a3 100644 --- a/app/client/src/widgets/withWidgetProps.tsx +++ b/app/client/src/widgets/withWidgetProps.tsx @@ -25,7 +25,6 @@ import { getMetaWidget, getIsAutoLayoutMobileBreakPoint, getCanvasWidth, - combinedPreviewModeSelector, } from "selectors/editorSelectors"; import { createCanvasWidget, @@ -52,6 +51,7 @@ import { getIsAnvilLayout } from "layoutSystems/anvil/integrations/selectors"; import { WidgetProfiler } from "./BaseWidgetHOC/WidgetProfiler"; import { getAppsmithConfigs } from "ee/configs"; import { endSpan, startRootSpan } from "UITelemetry/generateTraces"; +import { selectCombinedPreviewMode } from "selectors/gitModSelectors"; const { newRelic } = getAppsmithConfigs(); const WIDGETS_WITH_CHILD_WIDGETS = ["LIST_WIDGET", "FORM_WIDGET"]; @@ -72,7 +72,7 @@ function withWidgetProps(WrappedWidget: typeof BaseWidget) { } = props; const span = startRootSpan("withWidgetProps", { widgetType: type }); - const isPreviewMode = useSelector(combinedPreviewModeSelector); + const isPreviewMode = useSelector(selectCombinedPreviewMode); const canvasWidget = useSelector((state: AppState) => getWidget(state, widgetId), diff --git a/app/client/test/testUtils.tsx b/app/client/test/testUtils.tsx index 9b99d698bb90..0d57bddfc09a 100644 --- a/app/client/test/testUtils.tsx +++ b/app/client/test/testUtils.tsx @@ -49,9 +49,12 @@ interface State { } const setupState = (state?: State) => { let reduxStore = store; + window.history.pushState({}, "Appsmith", state?.url || "/"); + if (state && (state.initialState || state.featureFlags)) { reduxStore = testStore(state.initialState || {}); + if (state.featureFlags) { reduxStore.dispatch( fetchFeatureFlagsSuccess({ @@ -61,10 +64,12 @@ const setupState = (state?: State) => { ); } } + if (state && state.sagasToRun) { reduxStore = testStoreWithTestMiddleWare(reduxStore.getState()); testSagaMiddleware.run(() => rootSaga(state.sagasToRun)); } + const defaultTheme = getCurrentThemeDetails(reduxStore.getState()); return { reduxStore, defaultTheme }; @@ -76,6 +81,7 @@ const customRender = ( options?: Omit, ) => { const { defaultTheme, reduxStore } = setupState(state); + return render( @@ -92,6 +98,7 @@ const customRender = ( const hookWrapper = (state: State) => { return ({ children }: { children: ReactElement }) => { const { defaultTheme, reduxStore } = setupState(state); + return ( From e7c116c197be4731ec88524156cdbd4921240d6e Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Tue, 24 Dec 2024 17:11:09 +0530 Subject: [PATCH 097/143] chore: fixing connect flow --- .../uiReducers/applicationsReducer.tsx | 16 +++ .../src/git/ce/components/GitModals/index.tsx | 2 + .../ConnectSuccessModalView.tsx} | 105 +++++++++++------- .../index.tsx | 13 ++- app/client/src/git/index.ts | 4 + app/client/src/git/sagas/connectSaga.ts | 16 ++- .../src/git/store/actions/connectActions.ts | 24 ++-- 7 files changed, 116 insertions(+), 64 deletions(-) rename app/client/src/git/components/{ConnectSuccess/ConnectSuccessView.tsx => ConnectSuccessModal/ConnectSuccessModalView.tsx} (64%) rename app/client/src/git/components/{ConnectSuccess => ConnectSuccessModal}/index.tsx (61%) diff --git a/app/client/src/ce/reducers/uiReducers/applicationsReducer.tsx b/app/client/src/ce/reducers/uiReducers/applicationsReducer.tsx index dd2f5b5c4060..97830da22ff3 100644 --- a/app/client/src/ce/reducers/uiReducers/applicationsReducer.tsx +++ b/app/client/src/ce/reducers/uiReducers/applicationsReducer.tsx @@ -25,6 +25,8 @@ import { import produce from "immer"; import { isEmpty } from "lodash"; import type { ApplicationPayload } from "entities/Application"; +import { gitConnectSuccess, type GitConnectSuccessPayload } from "git"; +import type { PayloadAction } from "@reduxjs/toolkit"; export const initialState: ApplicationsReduxState = { isSavingAppName: false, @@ -744,6 +746,20 @@ export const handlers = { isSavingNavigationSetting: false, }; }, + // git + [gitConnectSuccess.type]: ( + state: ApplicationsReduxState, + action: PayloadAction, + ) => { + return { + ...state, + currentApplication: { + ...state.currentApplication, + gitApplicationMetadata: + action.payload.responseData.gitApplicationMetadata, + }, + }; + }, }; const applicationsReducer = createReducer(initialState, handlers); diff --git a/app/client/src/git/ce/components/GitModals/index.tsx b/app/client/src/git/ce/components/GitModals/index.tsx index a5fcb8c7be36..8bd094fa1ffe 100644 --- a/app/client/src/git/ce/components/GitModals/index.tsx +++ b/app/client/src/git/ce/components/GitModals/index.tsx @@ -1,5 +1,6 @@ import ConflictErrorModal from "git/components/ConflictErrorModal"; import ConnectModal from "git/components/ConnectModal"; +import ConnectSuccessModal from "git/components/ConnectSuccessModal"; import DisableAutocommitModal from "git/components/DisableAutocommitModal"; import DisconnectModal from "git/components/DisconnectModal"; import OpsModal from "git/components/OpsModal"; @@ -10,6 +11,7 @@ function GitModals() { return ( <> + diff --git a/app/client/src/git/components/ConnectSuccess/ConnectSuccessView.tsx b/app/client/src/git/components/ConnectSuccessModal/ConnectSuccessModalView.tsx similarity index 64% rename from app/client/src/git/components/ConnectSuccess/ConnectSuccessView.tsx rename to app/client/src/git/components/ConnectSuccessModal/ConnectSuccessModalView.tsx index bf07ce64402c..af8390a76321 100644 --- a/app/client/src/git/components/ConnectSuccess/ConnectSuccessView.tsx +++ b/app/client/src/git/components/ConnectSuccessModal/ConnectSuccessModalView.tsx @@ -17,13 +17,15 @@ import { Text, Link, Tooltip, + Modal, + ModalContent, } from "@appsmith/ads"; import React, { useCallback } from "react"; import styled from "styled-components"; import AnalyticsUtil from "ee/utils/AnalyticsUtil"; import { DOCS_BRANCH_PROTECTION_URL } from "constants/ThirdPartyConstants"; import noop from "lodash/noop"; -import type { GitSettingsTab } from "git/constants/enums"; +import { GitSettingsTab } from "git/constants/enums"; const TitleText = styled(Text)` flex: 1; @@ -51,15 +53,15 @@ function ConnectionSuccessTitle() { ); } -interface ConnectSuccessModalViewProps { +interface ConnectSuccessContentProps { repoName: string | null; defaultBranch: string | null; } -function ConnectSuccessModalView({ +function ConnectSuccessContent({ defaultBranch, repoName, -}: ConnectSuccessModalViewProps) { +}: ConnectSuccessContentProps) { return ( <>
@@ -112,67 +114,84 @@ function ConnectSuccessModalView({ ); } -export interface ConnectSuccessViewProps { +const StyledModalContent = styled(ModalContent)` + &&& { + width: 640px; + transform: none !important; + top: 100px; + left: calc(50% - 320px); + max-height: calc(100vh - 200px); + } +`; + +export interface ConnectSuccessModalViewProps { defaultBranch: string | null; + isConnectSuccessModalOpen: boolean; remoteUrl: string | null; repoName: string | null; - toggleModalOpen: (open: boolean) => void; + toggleConnectSuccessModal: (open: boolean) => void; toggleSettingsModal: ( open: boolean, tab?: keyof typeof GitSettingsTab, ) => void; } -function ConnectSuccessView({ - defaultBranch, +function ConnectSuccessModalView({ + defaultBranch = null, + isConnectSuccessModalOpen = false, remoteUrl = null, - repoName, - toggleModalOpen = noop, + repoName = null, + toggleConnectSuccessModal = noop, toggleSettingsModal = noop, -}: ConnectSuccessViewProps) { +}: ConnectSuccessModalViewProps) { const handleStartGit = useCallback(() => { - toggleModalOpen(false); + toggleConnectSuccessModal(false); AnalyticsUtil.logEvent("GS_START_USING_GIT", { repoUrl: remoteUrl, }); - }, [remoteUrl, toggleModalOpen]); + }, [remoteUrl, toggleConnectSuccessModal]); const handleOpenSettings = useCallback(() => { - toggleModalOpen(false); - toggleSettingsModal(true); + toggleConnectSuccessModal(false); + toggleSettingsModal(true, GitSettingsTab.Branch); AnalyticsUtil.logEvent("GS_OPEN_GIT_SETTINGS", { repoUrl: remoteUrl, }); - }, [remoteUrl, toggleModalOpen, toggleSettingsModal]); + }, [remoteUrl, toggleConnectSuccessModal, toggleSettingsModal]); return ( - <> - - - - - - - - - + + + + + + + + + + + + ); } -export default ConnectSuccessView; +export default ConnectSuccessModalView; diff --git a/app/client/src/git/components/ConnectSuccess/index.tsx b/app/client/src/git/components/ConnectSuccessModal/index.tsx similarity index 61% rename from app/client/src/git/components/ConnectSuccess/index.tsx rename to app/client/src/git/components/ConnectSuccessModal/index.tsx index a3db4d1dd4d6..c492e5aa4bb3 100644 --- a/app/client/src/git/components/ConnectSuccess/index.tsx +++ b/app/client/src/git/components/ConnectSuccessModal/index.tsx @@ -1,11 +1,11 @@ import React from "react"; -import ConnectSuccessView from "./ConnectSuccessView"; +import ConnectSuccessModalView from "./ConnectSuccessModalView"; import useMetadata from "git/hooks/useMetadata"; import useConnect from "git/hooks/useConnect"; import useSettings from "git/hooks/useSettings"; -function ConnectSuccess() { - const { toggleConnectSuccessModal } = useConnect(); +function ConnectSuccessModal() { + const { isConnectSuccessModalOpen, toggleConnectSuccessModal } = useConnect(); const { toggleSettingsModal } = useSettings(); const { metadata } = useMetadata(); @@ -15,14 +15,15 @@ function ConnectSuccess() { const defaultBranch = metadata?.defaultBranchName ?? null; return ( - ); } -export default ConnectSuccess; +export default ConnectSuccessModal; diff --git a/app/client/src/git/index.ts b/app/client/src/git/index.ts index 69773a8d989a..892ca77d7f43 100644 --- a/app/client/src/git/index.ts +++ b/app/client/src/git/index.ts @@ -21,6 +21,9 @@ import { gitGlobalActions } from "./store/gitGlobalSlice"; export const fetchGitGlobalProfile = gitGlobalActions.fetchGlobalProfileInit; export const toggleGitImportModal = gitGlobalActions.toggleImportModal; +import { gitArtifactActions } from "./store/gitArtifactSlice"; +export const gitConnectSuccess = gitArtifactActions.connectSuccess; + // selectors export { selectCurrentBranch as selectGitCurrentBranch, @@ -33,3 +36,4 @@ export type { GitArtifactRootReduxState, GitGlobalReduxState, } from "./store/types"; +export type { ConnectSuccessPayload as GitConnectSuccessPayload } from "./store/actions/connectActions"; diff --git a/app/client/src/git/sagas/connectSaga.ts b/app/client/src/git/sagas/connectSaga.ts index 76e94f246bd9..b6de0cdea53e 100644 --- a/app/client/src/git/sagas/connectSaga.ts +++ b/app/client/src/git/sagas/connectSaga.ts @@ -8,7 +8,7 @@ import { GitArtifactType, GitErrorCodes } from "../constants/enums"; import type { GitArtifactPayloadAction } from "../store/types"; import type { ConnectInitPayload } from "../store/actions/connectActions"; -import { call, put } from "redux-saga/effects"; +import { call, put, select } from "redux-saga/effects"; // Internal dependencies import { validateResponse } from "sagas/ErrorSagas"; @@ -17,6 +17,7 @@ import history from "utils/history"; import { addBranchParam } from "constants/routes"; import log from "loglevel"; import { captureException } from "@sentry/react"; +import { getCurrentPageId } from "selectors/editorSelectors"; export default function* connectSaga( action: GitArtifactPayloadAction, @@ -36,15 +37,18 @@ export default function* connectSaga( const isValidResponse: boolean = yield validateResponse(response, false); if (response && isValidResponse) { - yield put(gitArtifactActions.connectSuccess({ artifactDef })); + yield put( + gitArtifactActions.connectSuccess({ + artifactDef, + responseData: response.data, + }), + ); // needs to happen only when artifactType is application if (artifactDef.artifactType === GitArtifactType.Application) { - const { branchedPageId } = action.payload; + const pageId: string = yield select(getCurrentPageId); - if (branchedPageId) { - yield put(fetchPageAction(branchedPageId)); - } + yield put(fetchPageAction(pageId)); const branch = response.data?.gitApplicationMetadata?.branchName; diff --git a/app/client/src/git/store/actions/connectActions.ts b/app/client/src/git/store/actions/connectActions.ts index 84f7e3612ccc..9e5e2bcf10b1 100644 --- a/app/client/src/git/store/actions/connectActions.ts +++ b/app/client/src/git/store/actions/connectActions.ts @@ -1,10 +1,11 @@ import { createArtifactAction } from "../helpers/createArtifactAction"; -import type { GitAsyncErrorPayload } from "../types"; -import type { ConnectRequestParams } from "git/requests/connectRequest.types"; +import type { GitAsyncErrorPayload, GitAsyncSuccessPayload } from "../types"; +import type { + ConnectRequestParams, + ConnectResponseData, +} from "git/requests/connectRequest.types"; -export interface ConnectInitPayload extends ConnectRequestParams { - branchedPageId?: string; -} +export interface ConnectInitPayload extends ConnectRequestParams {} export const connectInitAction = createArtifactAction( (state) => { @@ -15,11 +16,16 @@ export const connectInitAction = createArtifactAction( }, ); -export const connectSuccessAction = createArtifactAction((state) => { - state.apiResponses.connect.loading = false; +export interface ConnectSuccessPayload + extends GitAsyncSuccessPayload {} - return state; -}); +export const connectSuccessAction = createArtifactAction( + (state) => { + state.apiResponses.connect.loading = false; + + return state; + }, +); export const connectErrorAction = createArtifactAction( (state, action) => { From a6926c9b7e6b3ff3e40e4d01753382b7b4b99c3c Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Tue, 24 Dec 2024 18:42:33 +0530 Subject: [PATCH 098/143] chore: fixing unit tests --- .../FocusStrategy/AppIDEFocusStrategy.ts | 8 +++-- .../ChooseGitProvider.test.tsx | 4 +-- app/client/src/git/hooks/useCurrentBranch.ts | 8 ++--- .../store/selectors/gitArtifactSelectors.ts | 9 ++--- .../src/pages/AppViewer/PrimaryCTA.test.tsx | 5 +++ .../Editor/IDE/ProtectedCallout.test.tsx | 33 ++----------------- app/client/src/pages/Editor/IDE/hooks.ts | 1 + .../pages/Editor/gitSync/hooks/modHooks.ts | 2 +- app/client/src/selectors/gitModSelectors.ts | 4 ++- .../ChartWidget/component/index.test.tsx | 5 +++ 10 files changed, 32 insertions(+), 47 deletions(-) diff --git a/app/client/src/ce/navigation/FocusStrategy/AppIDEFocusStrategy.ts b/app/client/src/ce/navigation/FocusStrategy/AppIDEFocusStrategy.ts index f9c2122b0ec3..7c35bbccc52a 100644 --- a/app/client/src/ce/navigation/FocusStrategy/AppIDEFocusStrategy.ts +++ b/app/client/src/ce/navigation/FocusStrategy/AppIDEFocusStrategy.ts @@ -90,8 +90,12 @@ const isPageChange = (prevPath: string, currentPath: string) => { export const createEditorFocusInfoKey = ( basePageId: string, - branch?: string | null, -) => `EDITOR_STATE.${basePageId}#${branch}`; + branch: string | null = null, +) => + branch + ? `EDITOR_STATE.${basePageId}#${branch}` + : `EDITOR_STATE.${basePageId}`; + export const createEditorFocusInfo = (basePageId: string, branch?: string) => ({ key: createEditorFocusInfoKey(basePageId, branch), entityInfo: { diff --git a/app/client/src/git/components/ConnectModal/ConnectInitialize/ChooseGitProvider.test.tsx b/app/client/src/git/components/ConnectModal/ConnectInitialize/ChooseGitProvider.test.tsx index 6b2a7ca4ab8f..8d536c71686d 100644 --- a/app/client/src/git/components/ConnectModal/ConnectInitialize/ChooseGitProvider.test.tsx +++ b/app/client/src/git/components/ConnectModal/ConnectInitialize/ChooseGitProvider.test.tsx @@ -213,11 +213,11 @@ describe("ChooseGitProvider Component", () => { }); it("respects canCreateNewArtifact and device conditions for links", () => { - // If canCreateNewArtifact is false, "Import via git" should not appear even if conditions are met + // If onOpenImport is null, "Import via git" should not appear even if conditions are met render( , ); diff --git a/app/client/src/git/hooks/useCurrentBranch.ts b/app/client/src/git/hooks/useCurrentBranch.ts index ddc7f96ebd5a..6358d6215272 100644 --- a/app/client/src/git/hooks/useCurrentBranch.ts +++ b/app/client/src/git/hooks/useCurrentBranch.ts @@ -1,8 +1,8 @@ -import { useGitContext } from "git/components/GitContextProvider"; +import { selectCurrentBranch } from "git/store/selectors/gitArtifactSelectors"; +import { useSelector } from "react-redux"; -// refactor to use branch from git metadata export default function useCurrentBranch() { - const { artifact } = useGitContext(); + const currentBranch = useSelector(selectCurrentBranch); - return artifact?.gitApplicationMetadata?.branchName ?? null; + return currentBranch; } diff --git a/app/client/src/git/store/selectors/gitArtifactSelectors.ts b/app/client/src/git/store/selectors/gitArtifactSelectors.ts index f9df157925fa..4514a9b5b324 100644 --- a/app/client/src/git/store/selectors/gitArtifactSelectors.ts +++ b/app/client/src/git/store/selectors/gitArtifactSelectors.ts @@ -109,12 +109,7 @@ export const selectConflictErrorModalOpen = ( // git branches -export const selectCurrentBranch = ( - state: GitRootState, - // need the arg to preserve type - // eslint-disable-next-line @typescript-eslint/no-unused-vars - artifactDef: GitArtifactDef, -) => { +export const selectCurrentBranch = (state: GitRootState) => { return ( state?.ui?.applications?.currentApplication?.gitApplicationMetadata ?.branchName ?? null @@ -216,7 +211,7 @@ export const selectProtectedMode = ( state: GitRootState, artifactDef: GitArtifactDef, ) => { - const currentBranch = selectCurrentBranch(state, artifactDef); + const currentBranch = selectCurrentBranch(state); const protectedBranches = selectFetchProtectedBranchesState( state, artifactDef, diff --git a/app/client/src/pages/AppViewer/PrimaryCTA.test.tsx b/app/client/src/pages/AppViewer/PrimaryCTA.test.tsx index 3b03a559fbfb..63b76d0e0fcc 100644 --- a/app/client/src/pages/AppViewer/PrimaryCTA.test.tsx +++ b/app/client/src/pages/AppViewer/PrimaryCTA.test.tsx @@ -7,6 +7,11 @@ import { lightTheme } from "selectors/themeSelectors"; import PrimaryCTA from "./PrimaryCTA"; import configureStore from "redux-mock-store"; +jest.mock("pages/Editor/gitSync/hooks/modHooks", () => ({ + ...jest.requireActual("pages/Editor/gitSync/hooks/modHooks"), + useGitProtectedMode: jest.fn(() => false), +})); + jest.mock("react-router", () => ({ ...jest.requireActual("react-router"), useHistory: () => ({ push: jest.fn() }), diff --git a/app/client/src/pages/Editor/IDE/ProtectedCallout.test.tsx b/app/client/src/pages/Editor/IDE/ProtectedCallout.test.tsx index 2a60c70f3f86..d735d5663d88 100644 --- a/app/client/src/pages/Editor/IDE/ProtectedCallout.test.tsx +++ b/app/client/src/pages/Editor/IDE/ProtectedCallout.test.tsx @@ -3,11 +3,11 @@ import { render } from "@testing-library/react"; import { merge } from "lodash"; import { Provider } from "react-redux"; import configureStore from "redux-mock-store"; -import IDE from "."; import { BrowserRouter } from "react-router-dom"; import "@testing-library/jest-dom"; import { ReduxActionTypes } from "ee/constants/ReduxActionConstants"; import store from "store"; +import ProtectedCallout from "./ProtectedCallout"; // TODO: Fix this the next time the file is edited // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -64,7 +64,7 @@ describe("Protected callout test cases", () => { const { getByTestId } = render( - + , ); @@ -72,33 +72,6 @@ describe("Protected callout test cases", () => { expect(getByTestId("t--git-protected-branch-callout")).toBeInTheDocument(); }); - it("should not render the protected view if branch is not protected", () => { - const store = getMockStore({ - ui: { - applications: { - currentApplication: { - gitApplicationMetadata: { - branchName: "branch-1", - }, - }, - }, - gitSync: { - protectedBranches: ["main"], - }, - }, - }); - const { queryByTestId } = render( - - - - - , - ); - - expect( - queryByTestId("t--git-protected-branch-callout"), - ).not.toBeInTheDocument(); - }); it("should unprotect only the current branch if clicked on unprotect cta", () => { const store = getMockStore({ ui: { @@ -117,7 +90,7 @@ describe("Protected callout test cases", () => { const { queryByTestId } = render( - + , ); diff --git a/app/client/src/pages/Editor/IDE/hooks.ts b/app/client/src/pages/Editor/IDE/hooks.ts index 0b522478648d..b1a6bba71bb8 100644 --- a/app/client/src/pages/Editor/IDE/hooks.ts +++ b/app/client/src/pages/Editor/IDE/hooks.ts @@ -98,6 +98,7 @@ export const useGetPageFocusUrl = (basePageId: string): string => { const [focusPageUrl, setFocusPageUrl] = useState(builderURL({ basePageId })); const branch = useGitCurrentBranch(); + const editorStateFocusInfo = useSelector((appState) => getCurrentFocusInfo(appState, createEditorFocusInfoKey(basePageId, branch)), ); diff --git a/app/client/src/pages/Editor/gitSync/hooks/modHooks.ts b/app/client/src/pages/Editor/gitSync/hooks/modHooks.ts index 86d44b700b87..e4d4b7fb4b7a 100644 --- a/app/client/src/pages/Editor/gitSync/hooks/modHooks.ts +++ b/app/client/src/pages/Editor/gitSync/hooks/modHooks.ts @@ -21,7 +21,7 @@ export function useGitModEnabled() { export function useGitCurrentBranch() { const isGitModEnabled = useGitModEnabled(); - const currentBranchOld = useSelector(getCurrentGitBranch); + const currentBranchOld = useSelector(getCurrentGitBranch) ?? null; const currentBranchNew = useGitCurrentBranchNew(); return isGitModEnabled ? currentBranchNew : currentBranchOld; diff --git a/app/client/src/selectors/gitModSelectors.ts b/app/client/src/selectors/gitModSelectors.ts index 3c24a42e3f34..f52184f08c9b 100644 --- a/app/client/src/selectors/gitModSelectors.ts +++ b/app/client/src/selectors/gitModSelectors.ts @@ -20,6 +20,8 @@ export const selectGitModEnabled = createSelector( export function selectGitCurrentBranch( state: AppState, + // need this to preserve interface + // eslint-disable-next-line @typescript-eslint/no-unused-vars artifactDef: GitArtifactDef, ) { const isGitModEnabled = selectGitModEnabled(state); @@ -27,7 +29,7 @@ export function selectGitCurrentBranch( if (isGitModEnabled) { return getCurrentGitBranch(state); } else { - return selectGitCurrentBranchNew(state, artifactDef); + return selectGitCurrentBranchNew(state); } } diff --git a/app/client/src/widgets/ChartWidget/component/index.test.tsx b/app/client/src/widgets/ChartWidget/component/index.test.tsx index 8c043acb36a3..ee53792993a8 100644 --- a/app/client/src/widgets/ChartWidget/component/index.test.tsx +++ b/app/client/src/widgets/ChartWidget/component/index.test.tsx @@ -22,6 +22,11 @@ import { APP_MODE } from "entities/App"; // eslint-disable-next-line @typescript-eslint/no-explicit-any let container: any; +jest.mock("selectors/gitModSelectors", () => ({ + ...jest.requireActual("selectors/gitModSelectors"), + selectCombinedPreviewMode: jest.fn(() => false), +})); + describe("Chart Widget", () => { const seriesData1: ChartData = { seriesName: "series1", From a2e48c95df0482ea3e9f6038a23608adebb22db1 Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Tue, 24 Dec 2024 18:57:00 +0530 Subject: [PATCH 099/143] chore: build failure --- app/client/src/git/hooks/useCurrentBranch.ts | 4 ++-- .../src/git/store/selectors/gitArtifactSelectors.ts | 9 +++++++-- app/client/src/selectors/gitModSelectors.ts | 4 +--- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/app/client/src/git/hooks/useCurrentBranch.ts b/app/client/src/git/hooks/useCurrentBranch.ts index 6358d6215272..797d8d598ba5 100644 --- a/app/client/src/git/hooks/useCurrentBranch.ts +++ b/app/client/src/git/hooks/useCurrentBranch.ts @@ -1,8 +1,8 @@ import { selectCurrentBranch } from "git/store/selectors/gitArtifactSelectors"; -import { useSelector } from "react-redux"; +import useArtifactSelector from "./useArtifactSelector"; export default function useCurrentBranch() { - const currentBranch = useSelector(selectCurrentBranch); + const currentBranch = useArtifactSelector(selectCurrentBranch); return currentBranch; } diff --git a/app/client/src/git/store/selectors/gitArtifactSelectors.ts b/app/client/src/git/store/selectors/gitArtifactSelectors.ts index 4514a9b5b324..58fa70624d7d 100644 --- a/app/client/src/git/store/selectors/gitArtifactSelectors.ts +++ b/app/client/src/git/store/selectors/gitArtifactSelectors.ts @@ -109,7 +109,12 @@ export const selectConflictErrorModalOpen = ( // git branches -export const selectCurrentBranch = (state: GitRootState) => { +export const selectCurrentBranch = ( + state: GitRootState, + // need this to preserve interface + // eslint-disable-next-line @typescript-eslint/no-unused-vars + artifactDef: GitArtifactDef, +) => { return ( state?.ui?.applications?.currentApplication?.gitApplicationMetadata ?.branchName ?? null @@ -211,7 +216,7 @@ export const selectProtectedMode = ( state: GitRootState, artifactDef: GitArtifactDef, ) => { - const currentBranch = selectCurrentBranch(state); + const currentBranch = selectCurrentBranch(state, artifactDef); const protectedBranches = selectFetchProtectedBranchesState( state, artifactDef, diff --git a/app/client/src/selectors/gitModSelectors.ts b/app/client/src/selectors/gitModSelectors.ts index f52184f08c9b..3c24a42e3f34 100644 --- a/app/client/src/selectors/gitModSelectors.ts +++ b/app/client/src/selectors/gitModSelectors.ts @@ -20,8 +20,6 @@ export const selectGitModEnabled = createSelector( export function selectGitCurrentBranch( state: AppState, - // need this to preserve interface - // eslint-disable-next-line @typescript-eslint/no-unused-vars artifactDef: GitArtifactDef, ) { const isGitModEnabled = selectGitModEnabled(state); @@ -29,7 +27,7 @@ export function selectGitCurrentBranch( if (isGitModEnabled) { return getCurrentGitBranch(state); } else { - return selectGitCurrentBranchNew(state); + return selectGitCurrentBranchNew(state, artifactDef); } } From 741d1f083732e0fa2eb1911e6efafab9ffcd33a1 Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Tue, 24 Dec 2024 22:24:19 +0530 Subject: [PATCH 100/143] chore: fixing unit test with mock --- app/client/src/pages/Editor/IDE/hooks.test.tsx | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/app/client/src/pages/Editor/IDE/hooks.test.tsx b/app/client/src/pages/Editor/IDE/hooks.test.tsx index 0a12538bf260..9e5e40d6e98f 100644 --- a/app/client/src/pages/Editor/IDE/hooks.test.tsx +++ b/app/client/src/pages/Editor/IDE/hooks.test.tsx @@ -6,6 +6,12 @@ import { useGetPageFocusUrl } from "./hooks"; // eslint-disable-next-line @typescript-eslint/no-restricted-imports import { createEditorFocusInfo } from "../../../ce/navigation/FocusStrategy/AppIDEFocusStrategy"; +const mockUseGitCurrentBranch = jest.fn(() => null); + +jest.mock("../gitSync/hooks/modHooks", () => ({ + useGitCurrentBranch: () => mockUseGitCurrentBranch(), +})); + describe("useGetPageFocusUrl", () => { const pages = PageFactory.buildList(4); @@ -42,6 +48,7 @@ describe("useGetPageFocusUrl", () => { const wrapper = hookWrapper({ initialState: state }); it("works for JS focus history", () => { + mockUseGitCurrentBranch.mockReturnValue(null); const { result } = renderHook(() => useGetPageFocusUrl(pages[0].pageId), { wrapper, }); @@ -83,10 +90,13 @@ describe("useGetPageFocusUrl", () => { it("returns correct state when branches exist", () => { const branch = "featureBranch"; + + mockUseGitCurrentBranch.mockReturnValue(branch); const page1FocusHistoryWithBranch = createEditorFocusInfo( pages[0].pageId, branch, ); + const state = getIDETestState({ pages, focusHistory: { From 10a43259b39b44c2ddaa669d2242a8632d20f068 Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Tue, 24 Dec 2024 23:47:36 +0530 Subject: [PATCH 101/143] chore: fixing status comp --- .../applicationStatusTransformer.ts | 143 +++++++++++++++++- .../components/GitContextProvider/index.tsx | 2 +- .../StatusChanges/StatusChangesView.tsx | 16 +- .../components/StatusChanges/StatusLoader.tsx | 10 +- .../components/StatusChanges/StatusTree.tsx | 29 ++-- .../src/git/components/StatusChanges/types.ts | 5 + .../git/requests/fetchStatusRequest.types.ts | 1 + 7 files changed, 181 insertions(+), 25 deletions(-) create mode 100644 app/client/src/git/components/StatusChanges/types.ts diff --git a/app/client/src/git/artifact-helpers/application/applicationStatusTransformer.ts b/app/client/src/git/artifact-helpers/application/applicationStatusTransformer.ts index 9ac95d9c424e..1aa9f2dc4f28 100644 --- a/app/client/src/git/artifact-helpers/application/applicationStatusTransformer.ts +++ b/app/client/src/git/artifact-helpers/application/applicationStatusTransformer.ts @@ -1,6 +1,11 @@ import type { FetchStatusResponseData } from "git/requests/fetchStatusRequest.types"; import { objectKeys } from "@appsmith/utils"; -import type { StatusTreeStruct } from "git/components/StatusChanges/StatusTree"; +import { + createMessage, + NOT_PUSHED_YET, + TRY_TO_PULL, +} from "ee/constants/messages"; +import type { StatusTreeStruct } from "git/components/StatusChanges/types"; const ICON_LOOKUP = { query: "query", @@ -8,19 +13,29 @@ const ICON_LOOKUP = { page: "page-line", datasource: "database-2-line", jsLib: "package", + settings: "settings-v3", + theme: "sip-line", + remote: "git-commit", + package: "package", + module: "package", + moduleInstance: "package", }; interface TreeNodeDef { subject: string; verb: string; type: keyof typeof ICON_LOOKUP; + extra?: string; } function createTreeNode(nodeDef: TreeNodeDef) { - return { - icon: ICON_LOOKUP[nodeDef.type], - message: `${nodeDef.subject} ${nodeDef.verb}`, - }; + let message = `${nodeDef.subject} ${nodeDef.verb}`; + + if (nodeDef.extra) { + message += ` ${nodeDef.extra}`; + } + + return { icon: ICON_LOOKUP[nodeDef.type], message }; } function determineVerbForDefs(defs: TreeNodeDef[]) { @@ -45,7 +60,11 @@ function createTreeNodeGroup(nodeDefs: TreeNodeDef[], subject: string) { return { icon: ICON_LOOKUP[nodeDefs[0].type], message: `${nodeDefs.length} ${subject} ${determineVerbForDefs(nodeDefs)}`, - children: nodeDefs.map(createTreeNode), + children: nodeDefs + .sort((a, b) => + a.subject.localeCompare(b.subject, undefined, { sensitivity: "base" }), + ) + .map(createTreeNode), }; } @@ -125,6 +144,10 @@ function statusPageTransformer(status: FetchStatusResponseData) { tree.push({ ...createTreeNode(pageDef), children }); }); + tree.sort((a, b) => + a.message.localeCompare(b.message, undefined, { sensitivity: "base" }), + ); + objectKeys(pageDefLookup).forEach((page) => { if (!pageEntityDefLookup[page]) { tree.push(createTreeNode(pageDefLookup[page])); @@ -186,13 +209,121 @@ function statusJsLibTransformer(status: FetchStatusResponseData) { return tree; } +function statusRemoteCountTransformer(status: FetchStatusResponseData) { + const { aheadCount, behindCount } = status; + const tree = [] as StatusTreeStruct[]; + + if (behindCount > 0) { + tree.push( + createTreeNode({ + subject: `${behindCount} commit${behindCount > 1 ? "s" : ""}`, + verb: "behind", + type: "remote", + extra: createMessage(TRY_TO_PULL), + }), + ); + } + + if (aheadCount > 0) { + tree.push( + createTreeNode({ + subject: `${aheadCount} commit${aheadCount > 1 ? "s" : ""}`, + verb: "ahead", + type: "remote", + extra: createMessage(NOT_PUSHED_YET), + }), + ); + } + + return tree; +} + +function statusSettingsTransformer(status: FetchStatusResponseData) { + const { modified } = status; + const tree = [] as StatusTreeStruct[]; + + if (modified.includes("application.json")) { + tree.push( + createTreeNode({ + subject: "Application settings", + verb: "modified", + type: "settings", + }), + ); + } + + return tree; +} + +function statusThemeTransformer(status: FetchStatusResponseData) { + const { modified } = status; + const tree = [] as StatusTreeStruct[]; + + if (modified.includes("theme.json")) { + tree.push( + createTreeNode({ + subject: "Theme", + verb: "modified", + type: "theme", + }), + ); + } + + return tree; +} + +function statusPackagesTransformer(status: FetchStatusResponseData) { + const { + modifiedModuleInstances = 0, + modifiedModules = 0, + modifiedPackages = 0, + } = status; + const tree = [] as StatusTreeStruct[]; + + if (modifiedPackages > 0) { + tree.push( + createTreeNode({ + subject: `${modifiedPackages} package${modifiedPackages > 1 ? "s" : ""}`, + verb: "modified", + type: "package", + }), + ); + } + + if (modifiedModules > 0) { + tree.push( + createTreeNode({ + subject: `${modifiedModules} module${modifiedModules > 1 ? "s" : ""}`, + verb: "modified", + type: "module", + }), + ); + } + + if (modifiedModuleInstances > 0) { + tree.push( + createTreeNode({ + subject: `${modifiedModuleInstances} module instance${modifiedPackages > 1 ? "s" : ""}`, + verb: "modified", + type: "moduleInstance", + }), + ); + } + + return tree; +} + export default function applicationStatusTransformer( status: FetchStatusResponseData, ) { const tree = [ + ...statusRemoteCountTransformer(status), ...statusPageTransformer(status), ...statusDatasourceTransformer(status), ...statusJsLibTransformer(status), + ...statusSettingsTransformer(status), + ...statusThemeTransformer(status), + ...statusPackagesTransformer(status), ] as StatusTreeStruct[]; return tree; diff --git a/app/client/src/git/components/GitContextProvider/index.tsx b/app/client/src/git/components/GitContextProvider/index.tsx index 388bbb95d9bb..89736de113eb 100644 --- a/app/client/src/git/components/GitContextProvider/index.tsx +++ b/app/client/src/git/components/GitContextProvider/index.tsx @@ -2,9 +2,9 @@ import React, { createContext, useCallback, useContext, useMemo } from "react"; import type { GitArtifactType } from "git/constants/enums"; import type { ApplicationPayload } from "entities/Application"; import type { FetchStatusResponseData } from "git/requests/fetchStatusRequest.types"; -import type { StatusTreeStruct } from "../StatusChanges/StatusTree"; import { useDispatch } from "react-redux"; import type { GitArtifactDef } from "git/store/types"; +import type { StatusTreeStruct } from "../StatusChanges/types"; export interface GitContextValue { artifactDef: GitArtifactDef | null; diff --git a/app/client/src/git/components/StatusChanges/StatusChangesView.tsx b/app/client/src/git/components/StatusChanges/StatusChangesView.tsx index c3768c0d866c..f8e6f0c41dfa 100644 --- a/app/client/src/git/components/StatusChanges/StatusChangesView.tsx +++ b/app/client/src/git/components/StatusChanges/StatusChangesView.tsx @@ -1,14 +1,19 @@ import type { FetchStatusResponseData } from "git/requests/fetchStatusRequest.types"; import React, { useMemo } from "react"; -import type { StatusTreeStruct } from "./StatusTree"; import StatusTree from "./StatusTree"; -import { Text } from "@appsmith/ads"; +import { Callout, Text } from "@appsmith/ads"; import { createMessage } from "@appsmith/ads-old"; import { CHANGES_SINCE_LAST_DEPLOYMENT, FETCH_GIT_STATUS, } from "ee/constants/messages"; -import StatusLoader from "pages/Editor/gitSync/components/StatusLoader"; +import StatusLoader from "./StatusLoader"; +import type { StatusTreeStruct } from "./types"; +import styled from "styled-components"; + +const CalloutContainer = styled.div` + margin-top: 16px; +`; const noopStatusTransformer = () => null; @@ -49,6 +54,11 @@ export default function StatusChangesView({ {createMessage(CHANGES_SINCE_LAST_DEPLOYMENT)} + {status.migrationMessage ? ( + + {status.migrationMessage} + + ) : null}
); } diff --git a/app/client/src/git/components/StatusChanges/StatusLoader.tsx b/app/client/src/git/components/StatusChanges/StatusLoader.tsx index bc0427bd6521..9026b75b38fa 100644 --- a/app/client/src/git/components/StatusChanges/StatusLoader.tsx +++ b/app/client/src/git/components/StatusChanges/StatusLoader.tsx @@ -6,16 +6,18 @@ const LoaderWrapper = styled.div` display: flex; flex-direction: row; align-items: center; - margin-top: ${(props) => `${props.theme.spaces[3]}px`}; + margin-bottom: 8px; +`; + +const LoaderText = styled(Text)` + margin-left: 8px; `; function StatusLoader({ loaderMsg }: { loaderMsg: string }) { return ( - - {loaderMsg} - + {loaderMsg} ); } diff --git a/app/client/src/git/components/StatusChanges/StatusTree.tsx b/app/client/src/git/components/StatusChanges/StatusTree.tsx index 289d2d28b796..437163d394df 100644 --- a/app/client/src/git/components/StatusChanges/StatusTree.tsx +++ b/app/client/src/git/components/StatusChanges/StatusTree.tsx @@ -7,12 +7,17 @@ import { Text, } from "@appsmith/ads"; import clsx from "clsx"; +import styled from "styled-components"; +import type { StatusTreeStruct } from "./types"; -export interface StatusTreeStruct { - icon: string; - message: string; - children?: StatusTreeStruct[]; -} +const StyledCollapsible = styled(Collapsible)` + gap: 0; +`; + +const StyledCollapsibleHeader = styled(CollapsibleHeader)` + padding-top: 0; + padding-bottom: 0; +`; interface StatusTreeNodeProps { icon: string; @@ -43,29 +48,31 @@ interface SingleStatusTreeProps { function SingleStatusTree({ depth = 1, tree }: SingleStatusTreeProps) { if (!tree) return null; + const noEmphasis = depth > 1 && !tree.children; + if (!tree.children) { return ( 2} + noEmphasis={noEmphasis} /> ); } return ( - - + + - + {tree.children.map((child, index) => ( ))} - + ); } diff --git a/app/client/src/git/components/StatusChanges/types.ts b/app/client/src/git/components/StatusChanges/types.ts new file mode 100644 index 000000000000..61a8e074714b --- /dev/null +++ b/app/client/src/git/components/StatusChanges/types.ts @@ -0,0 +1,5 @@ +export interface StatusTreeStruct { + icon: string; + message: string; + children?: StatusTreeStruct[]; +} diff --git a/app/client/src/git/requests/fetchStatusRequest.types.ts b/app/client/src/git/requests/fetchStatusRequest.types.ts index c4400688b794..feb064d3618d 100644 --- a/app/client/src/git/requests/fetchStatusRequest.types.ts +++ b/app/client/src/git/requests/fetchStatusRequest.types.ts @@ -24,6 +24,7 @@ export interface FetchStatusResponseData { modifiedDatasources: number; modifiedJSLibs: number; modifiedJSObjects: number; + modifiedPackages: number; modifiedModuleInstances: number; modifiedModules: number; modifiedPages: number; From 5c46d3215c8fbc9a8f35bf753d2ec93ef9ef049a Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Tue, 24 Dec 2024 23:57:46 +0530 Subject: [PATCH 102/143] fix: fixing when ff is off --- app/client/src/git/store/selectors/gitArtifactSelectors.ts | 6 ++---- app/client/src/selectors/gitModSelectors.ts | 3 +-- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/app/client/src/git/store/selectors/gitArtifactSelectors.ts b/app/client/src/git/store/selectors/gitArtifactSelectors.ts index 58fa70624d7d..5bf8267df889 100644 --- a/app/client/src/git/store/selectors/gitArtifactSelectors.ts +++ b/app/client/src/git/store/selectors/gitArtifactSelectors.ts @@ -217,10 +217,8 @@ export const selectProtectedMode = ( artifactDef: GitArtifactDef, ) => { const currentBranch = selectCurrentBranch(state, artifactDef); - const protectedBranches = selectFetchProtectedBranchesState( - state, - artifactDef, - ).value; + const protectedBranches = + selectFetchProtectedBranchesState(state, artifactDef)?.value ?? []; return protectedBranches?.includes(currentBranch ?? "") ?? false; }; diff --git a/app/client/src/selectors/gitModSelectors.ts b/app/client/src/selectors/gitModSelectors.ts index 3c24a42e3f34..8e84a543198b 100644 --- a/app/client/src/selectors/gitModSelectors.ts +++ b/app/client/src/selectors/gitModSelectors.ts @@ -14,8 +14,7 @@ import { applicationArtifact } from "git/artifact-helpers/application"; export const selectGitModEnabled = createSelector( selectFeatureFlags, - // (featureFlags) => featureFlags.release_git_modularisation_enabled ?? false, - () => true, + (featureFlags) => featureFlags.release_git_modularisation_enabled ?? false, ); export function selectGitCurrentBranch( From 0b57faee393cfeec117eeb8c6a1af8d2a925ce93 Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Wed, 25 Dec 2024 00:22:08 +0530 Subject: [PATCH 103/143] chore: fix typo --- .../application/applicationStatusTransformer.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/client/src/git/artifact-helpers/application/applicationStatusTransformer.ts b/app/client/src/git/artifact-helpers/application/applicationStatusTransformer.ts index 1aa9f2dc4f28..b803cddfea66 100644 --- a/app/client/src/git/artifact-helpers/application/applicationStatusTransformer.ts +++ b/app/client/src/git/artifact-helpers/application/applicationStatusTransformer.ts @@ -303,7 +303,7 @@ function statusPackagesTransformer(status: FetchStatusResponseData) { if (modifiedModuleInstances > 0) { tree.push( createTreeNode({ - subject: `${modifiedModuleInstances} module instance${modifiedPackages > 1 ? "s" : ""}`, + subject: `${modifiedModuleInstances} module instance${modifiedModuleInstances > 1 ? "s" : ""}`, verb: "modified", type: "moduleInstance", }), From 059417b58022270dcb68e71e7fc2406966e3a8cf Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Wed, 25 Dec 2024 00:48:02 +0530 Subject: [PATCH 104/143] chore: fixing unit tests --- .../src/ce/pages/Applications/CreateNewAppsOption.test.tsx | 4 ++++ .../src/components/editorComponents/ApiResponseView.test.tsx | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/app/client/src/ce/pages/Applications/CreateNewAppsOption.test.tsx b/app/client/src/ce/pages/Applications/CreateNewAppsOption.test.tsx index 180268afb6a9..06940dc36fcc 100644 --- a/app/client/src/ce/pages/Applications/CreateNewAppsOption.test.tsx +++ b/app/client/src/ce/pages/Applications/CreateNewAppsOption.test.tsx @@ -9,6 +9,10 @@ import CreateNewAppsOption from "./CreateNewAppsOption"; import { BrowserRouter as Router } from "react-router-dom"; import { unitTestBaseMockStore } from "layoutSystems/common/dropTarget/unitTestUtils"; +jest.mock("selectors/gitModSelectors", () => ({ + selectCombinedPreviewMode: jest.fn(() => false), +})); + const defaultStoreState = { ...unitTestBaseMockStore, tenant: { diff --git a/app/client/src/components/editorComponents/ApiResponseView.test.tsx b/app/client/src/components/editorComponents/ApiResponseView.test.tsx index 11601be68554..9ad68895e52f 100644 --- a/app/client/src/components/editorComponents/ApiResponseView.test.tsx +++ b/app/client/src/components/editorComponents/ApiResponseView.test.tsx @@ -17,6 +17,10 @@ jest.mock("./EntityBottomTabs", () => ({ default: () =>
, })); +jest.mock("selectors/gitModSelectors", () => ({ + selectCombinedPreviewMode: jest.fn(() => false), +})); + const mockStore = configureStore([]); const storeState = { From 034a91d9d593b30eb1eead319ae083c2f1f3dbfe Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Wed, 25 Dec 2024 02:21:53 +0530 Subject: [PATCH 105/143] chore: fixing tests --- app/client/cypress/support/Pages/GitSync.ts | 155 ++++++++++++------ .../ConnectModal/ConnectInitialize/index.tsx | 2 +- .../ConnectSuccessModalView.tsx | 8 +- .../git/components/OpsModal/OpsModalView.tsx | 2 +- .../components/QuickActions/BranchButton.tsx | 3 +- .../components/QuickActions/ConnectButton.tsx | 2 +- .../QuickActions/QuickActionButton.test.tsx | 14 +- .../QuickActions/QuickActionButton.tsx | 39 +++-- .../QuickActions/QuickActionsView.tsx | 12 +- 9 files changed, 147 insertions(+), 90 deletions(-) diff --git a/app/client/cypress/support/Pages/GitSync.ts b/app/client/cypress/support/Pages/GitSync.ts index 47f2e8cf70a1..a9ccee6c0a13 100644 --- a/app/client/cypress/support/Pages/GitSync.ts +++ b/app/client/cypress/support/Pages/GitSync.ts @@ -69,55 +69,51 @@ export class GitSync { public _disconnectGitBtn = "[data-testid='t--git-disconnect-btn']"; public _mergeLoader = "[data-testid='t--git-merge-loader']"; - OpenGitSyncModal() { - this.agHelper.GetNClick(this._connectGitBottomBar); - this.agHelper.AssertElementVisibility(this._gitSyncModal); + // git mod + public locators = { + quickActionConnectBtn: "[data-testid='t--git-quick-actions-connect']", + quickActionsCommitBtn: "[data-testid='t--git-quick-actions-commit'] button", + quickActionsPullBtn: "[data-testid='t--git-quick-actions-pull'] button", + quickActionsBranchBtn: "[data-testid='t--git-quick-actions-branch']", + quickActionsMergeBtn: "[data-testid='t--git-quick-actions-merge']", + quickActionsSettingsBtn: "[data-testid='t--git-quick-actions-settings']", + connectModal: "[data-testid='t--git-connect-modal']", + connectModalCloseBtn: + "//div[@data-testid='t--git-sync-modal']//button[@aria-label='Close']", + connectModalNextBtn: "[data-testid='t--git-connect-next']", + connectSuccessModal: "[data-testid='t--git-con-success-modal']", + connectSuccessModalCloseBtn: + "//div[@data-testid='t--git-success-modal']//button[@aria-label='Close']", + connectSuccessStartUsingBtn: + "[data-testid='t--git-con-success-start-using']", + connectSuccessOpenSettingsBtn: + "[data-testid='t--git-con-success-open-settings']", + opsModal: "[data-testid='t--git-ops-modal']", + opsModalCloseBtn: + "//div[@data-testid='t--git-ops-modal']//button[@aria-label='Close']", + }; + + public OpenConnectModal() { + this.agHelper.GetNClick(this.locators.quickActionConnectBtn); + this.agHelper.AssertElementVisibility(this.locators.connectModal); } - CloseGitSyncModal() { - this.agHelper.GetNClick(this._closeGitSyncModal); - this.agHelper.AssertElementAbsence(this._gitSyncModal); + public CloseConnectModal() { + this.agHelper.GetNClick(this.locators.connectModalCloseBtn); + this.agHelper.AssertElementAbsence(this.locators.connectModal); } - OpenGitSettingsModal(tabName: "GENERAL" | "BRANCH" | "CD" = "GENERAL") { - this.agHelper.GetNClick(this._bottomSettingsBtn); - this.agHelper.AssertElementVisibility(this._gitSettingsModal); - if (tabName !== "GENERAL") { - this.agHelper.GetNClick(`[data-testid='t--tab-${tabName}']`); - } + public OpenOpsModal() { + this.agHelper.GetNClick(this.locators.opsModal); + this.agHelper.AssertElementVisibility(this.locators.opsModal); } - CloseGitSettingsModal() { - this.agHelper.GetNClick(this._closeGitSettingsModal); - this.agHelper.AssertElementAbsence(this._gitSettingsModal); - } - - GetCurrentBranchName() { - return this.agHelper.GetText(this._branchButton, "text", 0); - } - - public CreateTestGiteaRepo(repo: string, privateFlag = false) { - cy.request({ - method: "POST", - url: `${this.dataManager.GIT_API_BASE}/api/v1/git/repos`, - body: { - name: repo, - private: privateFlag, - }, - }); + public CloseOpsModal() { + this.agHelper.GetNClick(this.locators.opsModalCloseBtn); + this.agHelper.AssertElementAbsence(this.locators.opsModal); } - private providerRadioOthers = "[data-testid='t--git-provider-radio-others']"; - private existingEmptyRepoYes = "[data-testid='t--existing-empty-repo-yes']"; - private gitConnectNextBtn = "[data-testid='t--git-connect-next-button']"; - private remoteUrlInput = "[data-testid='git-connect-remote-url-input']"; - private addedDeployKeyCheckbox = - "[data-testid='t--added-deploy-key-checkbox']"; - private startUsingGitButton = - "[data-testid='t--git-success-modal-start-using-git-cta']"; - private existingRepoCheckbox = "[data-testid='t--existing-repo-checkbox']"; - - CreateNConnectToGit( + public CreateNConnectToGit( repoName = "Repo", assertConnect = true, privateFlag = false, @@ -139,11 +135,11 @@ export class GitSync { `branches-${repoName}`, ); - this.OpenGitSyncModal(); + this.OpenConnectModal(); this.agHelper.GetNClick(this.providerRadioOthers); this.agHelper.GetNClick(this.existingEmptyRepoYes); - this.agHelper.GetNClick(this.gitConnectNextBtn); + this.agHelper.GetNClick(this.locators.connectModalNextBtn); this.agHelper.AssertAttribute( this.remoteUrlInput, "placeholder", @@ -153,7 +149,7 @@ export class GitSync { this.remoteUrlInput, `${this.dataManager.GIT_CLONE_URL}/${repoName}.git`, ); - this.agHelper.GetNClick(this.gitConnectNextBtn); + this.agHelper.GetNClick(this.locators.connectModalNextBtn); this.agHelper.GenerateUUID(); cy.get("@guid").then((uid) => { @@ -175,12 +171,16 @@ export class GitSync { }); }); this.agHelper.GetNClick(this.addedDeployKeyCheckbox, 0, true); - this.agHelper.GetNClick(this.gitConnectNextBtn); + this.agHelper.GetNClick(this.locators.connectModalNextBtn); if (assertConnect) { this.assertHelper.AssertNetworkStatus("@connectGitLocalRepo"); - this.agHelper.GetNClick(this.startUsingGitButton); - this.agHelper.AssertElementExist(this._bottomBarCommit, 0, 30000); + this.agHelper.GetNClick(this.locators.connectSuccessStartUsingBtn); + this.agHelper.AssertElementExist( + this.locators.quickActionsCommitBtn, + 0, + 30000, + ); } cy.wrap(repoName).as("gitRepoName"); @@ -200,7 +200,7 @@ export class GitSync { this.agHelper.GetNClick(this.providerRadioOthers); this.agHelper.GetNClick(this.existingRepoCheckbox, 0, true); - this.agHelper.GetNClick(this.gitConnectNextBtn); + this.agHelper.GetNClick(this.locators.connectModalNextBtn); this.agHelper.AssertAttribute( this.remoteUrlInput, "placeholder", @@ -210,7 +210,7 @@ export class GitSync { this.remoteUrlInput, `${this.dataManager.GIT_CLONE_URL}/${repoName}.git`, ); - this.agHelper.GetNClick(this.gitConnectNextBtn); + this.agHelper.GetNClick(this.locators.connectModalNextBtn); this.agHelper.GenerateUUID(); cy.get("@guid").then((uid) => { @@ -233,13 +233,62 @@ export class GitSync { }); }); this.agHelper.GetNClick(this.addedDeployKeyCheckbox, 0, true); - this.agHelper.GetNClick(this.gitConnectNextBtn); + this.agHelper.GetNClick(this.locators.connectModalNextBtn); if (assertConnect) { this.assertHelper.AssertNetworkStatus("@importFromGit", 201); } } + // old git + + // OpenGitSyncModal() { + // this.agHelper.AssertElementVisibility(this._gitSyncModal); + // } + + // CloseGitSyncModal() { + // this.agHelper.GetNClick(this._closeGitSyncModal); + // this.agHelper.AssertElementAbsence(this._gitSyncModal); + // } + + OpenGitSettingsModal(tabName: "GENERAL" | "BRANCH" | "CD" = "GENERAL") { + this.agHelper.GetNClick(this._bottomSettingsBtn); + this.agHelper.AssertElementVisibility(this._gitSettingsModal); + if (tabName !== "GENERAL") { + this.agHelper.GetNClick(`[data-testid='t--tab-${tabName}']`); + } + } + + CloseGitSettingsModal() { + this.agHelper.GetNClick(this._closeGitSettingsModal); + this.agHelper.AssertElementAbsence(this._gitSettingsModal); + } + + GetCurrentBranchName() { + return this.agHelper.GetText(this._branchButton, "text", 0); + } + + public CreateTestGiteaRepo(repo: string, privateFlag = false) { + cy.request({ + method: "POST", + url: `${this.dataManager.GIT_API_BASE}/api/v1/git/repos`, + body: { + name: repo, + private: privateFlag, + }, + }); + } + + private providerRadioOthers = "[data-testid='t--git-provider-radio-others']"; + private existingEmptyRepoYes = "[data-testid='t--existing-empty-repo-yes']"; + private gitConnectNextBtn = "[data-testid='t--git-connect-next-button']"; + private remoteUrlInput = "[data-testid='git-connect-remote-url-input']"; + private addedDeployKeyCheckbox = + "[data-testid='t--added-deploy-key-checkbox']"; + private startUsingGitButton = + "[data-testid='t--git-success-modal-start-using-git-cta']"; + private existingRepoCheckbox = "[data-testid='t--existing-repo-checkbox']"; + public clearBranchProtection() { this.agHelper.GetNClick(this._bottomSettingsBtn); this.agHelper.GetNClick(this._settingsTabBranch); @@ -388,7 +437,7 @@ export class GitSync { Cypress.env("MESSAGES").MERGED_SUCCESSFULLY(), "be.visible", ); - this.CloseGitSyncModal(); + this.CloseOpsModal(); } OpenRepositoryAndVerify() { @@ -413,7 +462,7 @@ export class GitSync { }); } - this.CloseGitSyncModal(); + this.CloseOpsModal(); } public DiscardChanges() { @@ -451,7 +500,7 @@ export class GitSync { true, ); } - this.CloseGitSyncModal(); + this.CloseOpsModal(); } public AssertBranchName(branch: string) { diff --git a/app/client/src/git/components/ConnectModal/ConnectInitialize/index.tsx b/app/client/src/git/components/ConnectModal/ConnectInitialize/index.tsx index 72ba9d797c1d..e73d3d250fec 100644 --- a/app/client/src/git/components/ConnectModal/ConnectInitialize/index.tsx +++ b/app/client/src/git/components/ConnectModal/ConnectInitialize/index.tsx @@ -256,7 +256,7 @@ function ConnectInitialize({ )} {!isSubmitLoading && ( + + ); + })} + + + + + ); +} + +export default RepoLimitErrorModalView; diff --git a/app/client/src/git/components/RepoLimitErrorModal/index.tsx b/app/client/src/git/components/RepoLimitErrorModal/index.tsx new file mode 100644 index 000000000000..47a3c46f8181 --- /dev/null +++ b/app/client/src/git/components/RepoLimitErrorModal/index.tsx @@ -0,0 +1,27 @@ +import React from "react"; +import RepoLimitErrorModalView from "./RepoLimitErrorModalView"; +import { useGitContext } from "../GitContextProvider"; +import useRepoLimitError from "git/hooks/useRepoLimitError"; +import useDisconnect from "git/hooks/useDisconnect"; + +function RepoLimitErrorModal() { + const { artifacts, fetchArtifacts, workspace } = useGitContext(); + const { isRepoLimitErrorModalOpen, toggleRepoLimitErrorModal } = + useRepoLimitError(); + const { openDisconnectModal } = useDisconnect(); + + const workspaceName = workspace?.name ?? null; + + return ( + + ); +} + +export default RepoLimitErrorModal; diff --git a/app/client/src/git/hooks/useDisconnect.ts b/app/client/src/git/hooks/useDisconnect.ts index 42fd878319fd..7df6fb5af127 100644 --- a/app/client/src/git/hooks/useDisconnect.ts +++ b/app/client/src/git/hooks/useDisconnect.ts @@ -1,17 +1,17 @@ import { useGitContext } from "git/components/GitContextProvider"; import { gitArtifactActions } from "git/store/gitArtifactSlice"; import { + selectDisconnectArtifactDef, selectDisconnectArtifactName, - selectDisconnectBaseArtifactId, selectDisconnectState, } from "git/store/selectors/gitArtifactSelectors"; import { useCallback } from "react"; import { useDispatch } from "react-redux"; import useArtifactSelector from "./useArtifactSelector"; +import type { GitArtifactDef } from "git/store/types"; export default function useDisconnect() { - const { artifact, artifactDef } = useGitContext(); - const artifactName = artifact?.name ?? ""; + const { artifactDef } = useGitContext(); const dispatch = useDispatch(); @@ -27,21 +27,28 @@ export default function useDisconnect() { } }, [artifactDef, dispatch]); - const disconnectBaseArtifactId = useArtifactSelector( - selectDisconnectBaseArtifactId, + const disconnectArtifactDef = useArtifactSelector( + selectDisconnectArtifactDef, ); const disconnectArtifactName = useArtifactSelector( selectDisconnectArtifactName, ); - const openDisconnectModal = useCallback(() => { - if (artifactDef) { - dispatch( - gitArtifactActions.openDisconnectModal({ artifactDef, artifactName }), - ); - } - }, [artifactDef, artifactName, dispatch]); + const openDisconnectModal = useCallback( + (targetArtifactDef: GitArtifactDef, targetArtifactName: string) => { + if (artifactDef) { + dispatch( + gitArtifactActions.openDisconnectModal({ + artifactDef, + targetArtifactDef, + targetArtifactName, + }), + ); + } + }, + [artifactDef, dispatch], + ); const closeDisconnectModal = useCallback(() => { if (artifactDef) { @@ -53,8 +60,8 @@ export default function useDisconnect() { isDisconnectLoading: disconnectState?.loading ?? false, disconnectError: disconnectState?.error ?? null, disconnect, - isDisconnectModalOpen: !!disconnectBaseArtifactId, - disconnectBaseArtifactId, + isDisconnectModalOpen: !!disconnectArtifactDef, + disconnectArtifactDef, disconnectArtifactName, openDisconnectModal, closeDisconnectModal, diff --git a/app/client/src/git/hooks/useRepoLimitError.ts b/app/client/src/git/hooks/useRepoLimitError.ts new file mode 100644 index 000000000000..7f70a55d4582 --- /dev/null +++ b/app/client/src/git/hooks/useRepoLimitError.ts @@ -0,0 +1,18 @@ +import { gitGlobalActions } from "git/store/gitGlobalSlice"; +import { selectRepoLimitErrorModalOpen } from "git/store/selectors/gitGlobalSelectors"; +import { useDispatch, useSelector } from "react-redux"; + +export default function useRepoLimitError() { + const dispatch = useDispatch(); + + const repoLimitErrorModalOpen = useSelector(selectRepoLimitErrorModalOpen); + + const toggleRepoLimitErrorModal = (open: boolean) => { + dispatch(gitGlobalActions.toggleRepoLimitErrorModal({ open })); + }; + + return { + isRepoLimitErrorModalOpen: repoLimitErrorModalOpen ?? false, + toggleRepoLimitErrorModal, + }; +} diff --git a/app/client/src/git/sagas/commitSaga.ts b/app/client/src/git/sagas/commitSaga.ts index 7ebcb70b9a71..f5540395eebc 100644 --- a/app/client/src/git/sagas/commitSaga.ts +++ b/app/client/src/git/sagas/commitSaga.ts @@ -13,6 +13,7 @@ import type { GitArtifactPayloadAction } from "../store/types"; // internal dependencies import { validateResponse } from "sagas/ErrorSagas"; +import { gitGlobalActions } from "git/store/gitGlobalSlice"; export default function* commitSaga( action: GitArtifactPayloadAction, @@ -51,8 +52,7 @@ export default function* commitSaga( if (error.code === GitErrorCodes.REPO_LIMIT_REACHED) { yield put( - gitArtifactActions.toggleRepoLimitErrorModal({ - artifactDef, + gitGlobalActions.toggleRepoLimitErrorModal({ open: true, }), ); diff --git a/app/client/src/git/sagas/connectSaga.ts b/app/client/src/git/sagas/connectSaga.ts index b6de0cdea53e..59a21ab22f7d 100644 --- a/app/client/src/git/sagas/connectSaga.ts +++ b/app/client/src/git/sagas/connectSaga.ts @@ -18,6 +18,7 @@ import { addBranchParam } from "constants/routes"; import log from "loglevel"; import { captureException } from "@sentry/react"; import { getCurrentPageId } from "selectors/editorSelectors"; +import { gitGlobalActions } from "git/store/gitGlobalSlice"; export default function* connectSaga( action: GitArtifactPayloadAction, @@ -83,8 +84,7 @@ export default function* connectSaga( if (GitErrorCodes.REPO_LIMIT_REACHED === error.code) { yield put( - gitArtifactActions.toggleRepoLimitErrorModal({ - artifactDef, + gitGlobalActions.toggleRepoLimitErrorModal({ open: true, }), ); diff --git a/app/client/src/git/sagas/disconnectSaga.ts b/app/client/src/git/sagas/disconnectSaga.ts index ef6315c25cd5..ef6788b9ca11 100644 --- a/app/client/src/git/sagas/disconnectSaga.ts +++ b/app/client/src/git/sagas/disconnectSaga.ts @@ -5,52 +5,57 @@ import { GIT_BRANCH_QUERY_KEY } from "git/constants/misc"; import disconnectRequest from "git/requests/disconnectRequest"; import type { DisconnectResponse } from "git/requests/disconnectRequest.types"; import { gitArtifactActions } from "git/store/gitArtifactSlice"; -import type { GitArtifactPayloadAction } from "git/store/types"; +import { selectDisconnectArtifactDef } from "git/store/selectors/gitArtifactSelectors"; +import type { GitArtifactDef, GitArtifactPayloadAction } from "git/store/types"; import log from "loglevel"; -import { call, put } from "redux-saga/effects"; +import { call, put, select } from "redux-saga/effects"; import { validateResponse } from "sagas/ErrorSagas"; import history from "utils/history"; export default function* disconnectSaga(action: GitArtifactPayloadAction) { const { artifactDef } = action.payload; + const disconnectArtifactDef: GitArtifactDef = yield select( + selectDisconnectArtifactDef, + artifactDef, + ); let response: DisconnectResponse | undefined; try { - response = yield call(disconnectRequest, artifactDef.baseArtifactId); + response = yield call( + disconnectRequest, + disconnectArtifactDef.baseArtifactId, + ); const isValidResponse: boolean = yield validateResponse(response); if (response && isValidResponse) { yield put(gitArtifactActions.disconnectSuccess({ artifactDef })); - const url = new URL(window.location.href); - url.searchParams.delete(GIT_BRANCH_QUERY_KEY); - history.replace(url.toString().slice(url.origin.length)); - yield put(gitArtifactActions.unmount({ artifactDef })); - yield put( - gitArtifactActions.initGitForEditor({ - artifactDef, - artifact: response.data, - }), - ); - yield put(gitArtifactActions.closeDisconnectModal({ artifactDef })); - yield put( - gitArtifactActions.toggleOpsModal({ - artifactDef, - open: false, - tab: GitOpsTab.Deploy, - }), - ); - yield put(fetchAllApplicationsOfWorkspace()); + if (artifactDef.baseArtifactId === disconnectArtifactDef.baseArtifactId) { + const url = new URL(window.location.href); - // ! case: why? - // if (applicationId !== application?.id) { - // yield put( - // setIsGitSyncModalOpen({ - // isOpen: true, - // tab: GitSyncModalTab.GIT_CONNECTION, - // }), - // ); - // } + url.searchParams.delete(GIT_BRANCH_QUERY_KEY); + history.replace(url.toString().slice(url.origin.length)); + yield put(gitArtifactActions.unmount({ artifactDef })); + yield put( + gitArtifactActions.initGitForEditor({ + artifactDef, + artifact: response.data, + }), + ); + yield put(gitArtifactActions.closeDisconnectModal({ artifactDef })); + yield put( + gitArtifactActions.toggleOpsModal({ + artifactDef, + open: false, + tab: GitOpsTab.Deploy, + }), + ); + yield put(fetchAllApplicationsOfWorkspace()); + } else { + yield put( + gitArtifactActions.toggleConnectModal({ artifactDef, open: true }), + ); + } } } catch (e) { if (response && response.responseMeta.error) { diff --git a/app/client/src/git/sagas/generateSSHKeySaga.ts b/app/client/src/git/sagas/generateSSHKeySaga.ts index afbccf24b2e6..2749cada0dd6 100644 --- a/app/client/src/git/sagas/generateSSHKeySaga.ts +++ b/app/client/src/git/sagas/generateSSHKeySaga.ts @@ -7,6 +7,7 @@ import type { } from "git/requests/generateSSHKeyRequest.types"; import type { GenerateSSHKeyInitPayload } from "git/store/actions/generateSSHKeyActions"; import { gitArtifactActions } from "git/store/gitArtifactSlice"; +import { gitGlobalActions } from "git/store/gitGlobalSlice"; import type { GitArtifactPayloadAction } from "git/store/types"; import log from "loglevel"; import { call, put } from "redux-saga/effects"; @@ -44,8 +45,7 @@ export function* generateSSHKeySaga( if (GitErrorCodes.REPO_LIMIT_REACHED === error.code) { yield put( - gitArtifactActions.toggleRepoLimitErrorModal({ - artifactDef, + gitGlobalActions.toggleRepoLimitErrorModal({ open: true, }), ); diff --git a/app/client/src/git/store/actions/repoLimitErrorModalActions.ts b/app/client/src/git/store/actions/repoLimitErrorModalActions.ts index a2c96bac7721..51fd7c3212b9 100644 --- a/app/client/src/git/store/actions/repoLimitErrorModalActions.ts +++ b/app/client/src/git/store/actions/repoLimitErrorModalActions.ts @@ -1,14 +1,17 @@ -import { createArtifactAction } from "../helpers/createArtifactAction"; +import type { PayloadAction } from "@reduxjs/toolkit"; +import type { GitGlobalReduxState } from "../types"; -interface ToggleRepoLimitModalActionPayload { +interface ToggleRepoLimitModalPayload { open: boolean; } -export const toggleRepoLimitErrorModalAction = - createArtifactAction((state, action) => { - const { open } = action.payload; +export const toggleRepoLimitErrorModalAction = ( + state: GitGlobalReduxState, + action: PayloadAction, +) => { + const { open } = action.payload; - state.ui.repoLimitErrorModalOpen = open; + state.repoLimitErrorModalOpen = open; - return state; - }); + return state; +}; diff --git a/app/client/src/git/store/actions/uiActions.ts b/app/client/src/git/store/actions/uiActions.ts index 162382c3b876..486a391f8917 100644 --- a/app/client/src/git/store/actions/uiActions.ts +++ b/app/client/src/git/store/actions/uiActions.ts @@ -1,6 +1,6 @@ import type { GitOpsTab, GitSettingsTab } from "git/constants/enums"; import { createArtifactAction } from "../helpers/createArtifactAction"; -import type { GitGlobalReduxState } from "../types"; +import type { GitArtifactDef, GitGlobalReduxState } from "../types"; import type { PayloadAction } from "@reduxjs/toolkit"; // connect modal @@ -47,20 +47,24 @@ export const toggleImportModalAction = ( // disconnect modal export interface OpenDisconnectModalPayload { - artifactName: string; + targetArtifactDef: GitArtifactDef; + targetArtifactName: string; } export const openDisconnectModalAction = createArtifactAction((state, action) => { state.ui.disconnectBaseArtifactId = - action.payload.artifactDef.baseArtifactId; - state.ui.disconnectArtifactName = action.payload.artifactName; + action.payload.targetArtifactDef.baseArtifactId; + state.ui.disconnectArtifactType = + action.payload.targetArtifactDef.artifactType; + state.ui.disconnectArtifactName = action.payload.targetArtifactName; return state; }); export const closeDisconnectModalAction = createArtifactAction((state) => { state.ui.disconnectBaseArtifactId = null; + state.ui.disconnectArtifactType = null; state.ui.disconnectArtifactName = null; return state; @@ -130,19 +134,6 @@ export const toggleBranchPopupAction = createArtifactAction( ); // error modals -interface ToggleRepoLimitModalPayload { - open: boolean; -} - -export const toggleRepoLimitErrorModalAction = - createArtifactAction((state, action) => { - const { open } = action.payload; - - state.ui.repoLimitErrorModalOpen = open; - - return state; - }); - interface ToggleConflictErrorModalPayload { open: boolean; } diff --git a/app/client/src/git/store/gitArtifactSlice.ts b/app/client/src/git/store/gitArtifactSlice.ts index 15bbb4de65d2..fcf638666551 100644 --- a/app/client/src/git/store/gitArtifactSlice.ts +++ b/app/client/src/git/store/gitArtifactSlice.ts @@ -57,7 +57,6 @@ import { toggleConnectModalAction, toggleOpsModalAction, toggleSettingsModalAction, - toggleRepoLimitErrorModalAction, toggleConflictErrorModalAction, openDisconnectModalAction, closeDisconnectModalAction, @@ -167,7 +166,6 @@ export const gitArtifactSlice = createSlice({ toggleConnectSuccessModal: toggleConnectSuccessModalAction, openDisconnectModal: openDisconnectModalAction, closeDisconnectModal: closeDisconnectModalAction, - toggleRepoLimitErrorModal: toggleRepoLimitErrorModalAction, // git ops commitInit: commitInitAction, diff --git a/app/client/src/git/store/gitGlobalSlice.ts b/app/client/src/git/store/gitGlobalSlice.ts index 4a26f5d6132f..3d38b14aa492 100644 --- a/app/client/src/git/store/gitGlobalSlice.ts +++ b/app/client/src/git/store/gitGlobalSlice.ts @@ -22,6 +22,7 @@ import { fetchGlobalSSHKeySuccessAction, resetGlobalSSHKeyAction, } from "./actions/fetchGlobalSSHKeyActions"; +import { toggleRepoLimitErrorModalAction } from "./actions/repoLimitErrorModalActions"; export const gitGlobalSlice = createSlice({ name: "git/config", @@ -41,6 +42,7 @@ export const gitGlobalSlice = createSlice({ gitImportSuccess: gitImportSuccessAction, gitImportError: gitImportErrorAction, toggleImportModal: toggleImportModalAction, + toggleRepoLimitErrorModal: toggleRepoLimitErrorModalAction, }, }); diff --git a/app/client/src/git/store/helpers/initialState.ts b/app/client/src/git/store/helpers/initialState.ts index 382833be2782..665e26601190 100644 --- a/app/client/src/git/store/helpers/initialState.ts +++ b/app/client/src/git/store/helpers/initialState.ts @@ -14,6 +14,7 @@ const gitArtifactInitialUIState: GitArtifactUIReduxState = { connectModalOpen: false, connectSuccessModalOpen: false, disconnectBaseArtifactId: null, + disconnectArtifactType: null, disconnectArtifactName: null, branchPopupOpen: false, checkoutDestBranch: null, @@ -24,7 +25,6 @@ const gitArtifactInitialUIState: GitArtifactUIReduxState = { autocommitDisableModalOpen: false, autocommitPolling: false, conflictErrorModalOpen: false, - repoLimitErrorModalOpen: false, // EE ...gitArtifactUIInitialStateExtended, }; @@ -154,4 +154,5 @@ export const gitGlobalInitialState: GitGlobalReduxState = { error: null, }, isImportModalOpen: false, + repoLimitErrorModalOpen: false, }; diff --git a/app/client/src/git/store/selectors/gitArtifactSelectors.ts b/app/client/src/git/store/selectors/gitArtifactSelectors.ts index 5bf8267df889..70ba37ed7ca8 100644 --- a/app/client/src/git/store/selectors/gitArtifactSelectors.ts +++ b/app/client/src/git/store/selectors/gitArtifactSelectors.ts @@ -51,10 +51,19 @@ export const selectDisconnectState = ( artifactDef: GitArtifactDef, ) => selectGitArtifact(state, artifactDef)?.apiResponses.disconnect; -export const selectDisconnectBaseArtifactId = ( +export const selectDisconnectArtifactDef = ( state: GitRootState, artifactDef: GitArtifactDef, -) => selectGitArtifact(state, artifactDef)?.ui.disconnectBaseArtifactId; +) => { + const baseArtifactId = selectGitArtifact(state, artifactDef)?.ui + .disconnectBaseArtifactId; + const artifactType = selectGitArtifact(state, artifactDef)?.ui + .disconnectArtifactType; + + if (!baseArtifactId || !artifactType) return null; + + return { baseArtifactId, artifactType }; +}; export const selectDisconnectArtifactName = ( state: GitRootState, diff --git a/app/client/src/git/store/selectors/gitGlobalSelectors.ts b/app/client/src/git/store/selectors/gitGlobalSelectors.ts index 1d1fdb555d0c..57e5c5123036 100644 --- a/app/client/src/git/store/selectors/gitGlobalSelectors.ts +++ b/app/client/src/git/store/selectors/gitGlobalSelectors.ts @@ -19,3 +19,6 @@ export const selectGitImportState = (state: GitRootState) => export const selectFetchGlobalSSHKeyState = (state: GitRootState) => selectGitGlobal(state).globalSSHKey; + +export const selectRepoLimitErrorModalOpen = (state: GitRootState) => + selectGitGlobal(state).repoLimitErrorModalOpen; diff --git a/app/client/src/git/store/types.ts b/app/client/src/git/store/types.ts index 90a2e72998a5..77393c0f71b5 100644 --- a/app/client/src/git/store/types.ts +++ b/app/client/src/git/store/types.ts @@ -18,6 +18,7 @@ import type { GitArtifactUIReduxState as GitArtifactUIReduxStateExtended, } from "git/ee/store/types"; import type { FetchGlobalSSHKeyResponseData } from "git/requests/fetchGlobalSSHKeyRequest.types"; +import type { ApplicationPayload } from "entities/Application"; export interface GitApiError extends ApiResponseError { errorType?: string; @@ -65,6 +66,7 @@ export interface GitArtifactUIReduxState connectModalOpen: boolean; connectSuccessModalOpen: boolean; disconnectBaseArtifactId: string | null; + disconnectArtifactType: keyof typeof GitArtifactType | null; disconnectArtifactName: string | null; branchPopupOpen: boolean; checkoutDestBranch: string | null; @@ -75,9 +77,10 @@ export interface GitArtifactUIReduxState autocommitDisableModalOpen: boolean; autocommitPolling: boolean; conflictErrorModalOpen: boolean; - repoLimitErrorModalOpen: boolean; } +export type GitArtifact = ApplicationPayload; + export interface GitArtifactDef { artifactType: keyof typeof GitArtifactType; baseArtifactId: string; @@ -94,6 +97,7 @@ export interface GitGlobalReduxState { globalSSHKey: GitAsyncState; // ui isImportModalOpen: boolean; + repoLimitErrorModalOpen: boolean; } export type GitArtifactRootReduxState = Record< From 8124d0c8846f62ae8e5f9227340cca2616b0dde2 Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Sat, 28 Dec 2024 17:52:25 +0530 Subject: [PATCH 117/143] chore: updating locators --- .../Git/GitImport/GitImport_spec.js | 1 - .../Git/GitImport/ImportEmptyRepo_spec.js | 2 - .../Git/GitSync/DeleteBranch_spec.js | 2 - .../Git/GitSync/DisconnectGit_spec.js | 4 +- .../Git/GitSync/GitSyncGitBugs_spec.js | 1 - .../Git/GitSync/GitSyncedApps_spec.js | 8 +- .../Git/GitSync/MergeViaRemote_spec.ts | 1 - .../ClientSide/Git/GitSync/Merge_spec.js | 1 - .../ClientSide/Git/GitSync/PreConnect_spec.ts | 1 - .../RepoLimitExceededErrorModal_spec.js | 21 ++-- .../Git/GitSync/SwitchBranches_spec.js | 25 ++-- .../GitwithCustomJSLibrary_spec.js | 9 +- .../Git/GitWithTheming/GitWithTheming_spec.js | 35 ------ .../ForkTemplateToGitConnectedApp.js | 3 +- .../cypress/support/Objects/CommonLocators.ts | 1 + app/client/cypress/support/Pages/GitSync.ts | 13 +- app/client/cypress/support/gitSync.js | 116 +----------------- .../RepoLimitErrorModalView.tsx | 4 +- 18 files changed, 52 insertions(+), 196 deletions(-) diff --git a/app/client/cypress/e2e/Regression/ClientSide/Git/GitImport/GitImport_spec.js b/app/client/cypress/e2e/Regression/ClientSide/Git/GitImport/GitImport_spec.js index ed8af6b90850..6127bbceeeb3 100644 --- a/app/client/cypress/e2e/Regression/ClientSide/Git/GitImport/GitImport_spec.js +++ b/app/client/cypress/e2e/Regression/ClientSide/Git/GitImport/GitImport_spec.js @@ -1,4 +1,3 @@ -import gitSyncLocators from "../../../../../locators/gitSyncLocators"; import homePageLocators from "../../../../../locators/HomePage"; import reconnectDatasourceModal from "../../../../../locators/ReconnectLocators"; const datasourceEditor = require("../../../../../locators/DatasourcesEditor.json"); diff --git a/app/client/cypress/e2e/Regression/ClientSide/Git/GitImport/ImportEmptyRepo_spec.js b/app/client/cypress/e2e/Regression/ClientSide/Git/GitImport/ImportEmptyRepo_spec.js index 826a131f2782..360b66135381 100644 --- a/app/client/cypress/e2e/Regression/ClientSide/Git/GitImport/ImportEmptyRepo_spec.js +++ b/app/client/cypress/e2e/Regression/ClientSide/Git/GitImport/ImportEmptyRepo_spec.js @@ -1,5 +1,3 @@ -import homePage from "../../../../../locators/HomePage"; -import gitSyncLocators from "../../../../../locators/gitSyncLocators"; import * as _ from "../../../../../support/Objects/ObjectsCore"; describe( diff --git a/app/client/cypress/e2e/Regression/ClientSide/Git/GitSync/DeleteBranch_spec.js b/app/client/cypress/e2e/Regression/ClientSide/Git/GitSync/DeleteBranch_spec.js index 6fb86a4ddb94..bd5fd100cb07 100644 --- a/app/client/cypress/e2e/Regression/ClientSide/Git/GitSync/DeleteBranch_spec.js +++ b/app/client/cypress/e2e/Regression/ClientSide/Git/GitSync/DeleteBranch_spec.js @@ -1,5 +1,3 @@ -import gitSyncLocators from "../../../../../locators/gitSyncLocators"; - import { agHelper, gitSync } from "../../../../../support/Objects/ObjectsCore"; import { PageLeftPane, diff --git a/app/client/cypress/e2e/Regression/ClientSide/Git/GitSync/DisconnectGit_spec.js b/app/client/cypress/e2e/Regression/ClientSide/Git/GitSync/DisconnectGit_spec.js index a1a4fa8f581a..ce059d89d93f 100644 --- a/app/client/cypress/e2e/Regression/ClientSide/Git/GitSync/DisconnectGit_spec.js +++ b/app/client/cypress/e2e/Regression/ClientSide/Git/GitSync/DisconnectGit_spec.js @@ -95,7 +95,9 @@ describe( cy.get(_.gitSync.locators.disconnectModalInput).type( `{selectAll}${name}`, ); - cy.get(_.gitSync.locators.disconnectModalRevokeBtn).should("be.enabled"); + cy.get(_.gitSync.locators.disconnectModalRevokeBtn).should( + "be.enabled", + ); }); // disconnecting validation diff --git a/app/client/cypress/e2e/Regression/ClientSide/Git/GitSync/GitSyncGitBugs_spec.js b/app/client/cypress/e2e/Regression/ClientSide/Git/GitSync/GitSyncGitBugs_spec.js index 1682f4f893d1..c13f977a555e 100644 --- a/app/client/cypress/e2e/Regression/ClientSide/Git/GitSync/GitSyncGitBugs_spec.js +++ b/app/client/cypress/e2e/Regression/ClientSide/Git/GitSync/GitSyncGitBugs_spec.js @@ -1,4 +1,3 @@ -import gitSyncLocators from "../../../../../locators/gitSyncLocators"; const commonlocators = require("../../../../../locators/commonlocators.json"); import homePageLocators from "../../../../../locators/HomePage"; import { diff --git a/app/client/cypress/e2e/Regression/ClientSide/Git/GitSync/GitSyncedApps_spec.js b/app/client/cypress/e2e/Regression/ClientSide/Git/GitSync/GitSyncedApps_spec.js index b2e5348eeb7e..8116112064fd 100644 --- a/app/client/cypress/e2e/Regression/ClientSide/Git/GitSync/GitSyncedApps_spec.js +++ b/app/client/cypress/e2e/Regression/ClientSide/Git/GitSync/GitSyncedApps_spec.js @@ -2,14 +2,10 @@ import EditorNavigation, { EntityType, PageLeftPane, PagePaneSegment, - AppSidebar, - AppSidebarButton, } from "../../../../../support/Pages/EditorNavigation"; const generatePage = require("../../../../../locators/GeneratePage.json"); -const apiwidget = require("../../../../../locators/apiWidgetslocator.json"); const dynamicInputLocators = require("../../../../../locators/DynamicInput.json"); -import gitSyncLocators from "../../../../../locators/gitSyncLocators"; import homePageLocators from "../../../../../locators/HomePage"; import datasource from "../../../../../locators/DatasourcesEditor.json"; import widgetsPage from "../../../../../locators/Widgets.json"; @@ -371,7 +367,7 @@ describe( cy.get(gitSync.locators.opsCommitInput) .should("be.disabled") .and("have.text", "No changes to commit"); - gitSync.CloseOpsModal(); + gitSync.CloseOpsModal(); }); it("7. Switch to tempBranch , Clone the Child_Page, change it's visiblity to hidden and deploy, merge to master", () => { @@ -447,7 +443,7 @@ describe( cy.get(homePageLocators.workspaceImportAppOption).click({ force: true }); cy.get(".t--import-json-card").next().click(); // import application from git - cy.importAppFromGit(repoName); + // cy.importAppFromGit(repoName); // verify page order remains same as in orignal app PageList.ShowList(); cy.get(".t--entity-item").eq(1).contains("crudpage_1"); diff --git a/app/client/cypress/e2e/Regression/ClientSide/Git/GitSync/MergeViaRemote_spec.ts b/app/client/cypress/e2e/Regression/ClientSide/Git/GitSync/MergeViaRemote_spec.ts index 3a7c62274d1f..9042c3ca0787 100644 --- a/app/client/cypress/e2e/Regression/ClientSide/Git/GitSync/MergeViaRemote_spec.ts +++ b/app/client/cypress/e2e/Regression/ClientSide/Git/GitSync/MergeViaRemote_spec.ts @@ -1,4 +1,3 @@ -import gitSyncLocators from "../../../../../locators/gitSyncLocators"; import * as _ from "../../../../../support/Objects/ObjectsCore"; import { PageLeftPane, diff --git a/app/client/cypress/e2e/Regression/ClientSide/Git/GitSync/Merge_spec.js b/app/client/cypress/e2e/Regression/ClientSide/Git/GitSync/Merge_spec.js index edccb0120f0c..2c6d89b8c33d 100644 --- a/app/client/cypress/e2e/Regression/ClientSide/Git/GitSync/Merge_spec.js +++ b/app/client/cypress/e2e/Regression/ClientSide/Git/GitSync/Merge_spec.js @@ -1,4 +1,3 @@ -import gitSyncLocators from "../../../../../locators/gitSyncLocators"; import commonLocators from "../../../../../locators/commonlocators.json"; import * as _ from "../../../../../support/Objects/ObjectsCore"; diff --git a/app/client/cypress/e2e/Regression/ClientSide/Git/GitSync/PreConnect_spec.ts b/app/client/cypress/e2e/Regression/ClientSide/Git/GitSync/PreConnect_spec.ts index 377d528c4918..8413b49839b6 100644 --- a/app/client/cypress/e2e/Regression/ClientSide/Git/GitSync/PreConnect_spec.ts +++ b/app/client/cypress/e2e/Regression/ClientSide/Git/GitSync/PreConnect_spec.ts @@ -1,6 +1,5 @@ import homePage from "../../../../../locators/HomePage"; import * as _ from "../../../../../support/Objects/ObjectsCore"; -import gitSyncLocators from "../../../../../locators/gitSyncLocators"; describe( "Pre git connection spec:", diff --git a/app/client/cypress/e2e/Regression/ClientSide/Git/GitSync/RepoLimitExceededErrorModal_spec.js b/app/client/cypress/e2e/Regression/ClientSide/Git/GitSync/RepoLimitExceededErrorModal_spec.js index 06410257d951..11c9c8144e61 100644 --- a/app/client/cypress/e2e/Regression/ClientSide/Git/GitSync/RepoLimitExceededErrorModal_spec.js +++ b/app/client/cypress/e2e/Regression/ClientSide/Git/GitSync/RepoLimitExceededErrorModal_spec.js @@ -1,4 +1,3 @@ -import gitSyncLocators from "../../../../../locators/gitSyncLocators"; import { gitSync, agHelper, @@ -79,10 +78,7 @@ describe( cy.get(gitSync.locators.repoLimitErrorModal).contains( Cypress.env("MESSAGES").CONTACT_SUPPORT_TO_UPGRADE(), ); - cy.get(gitSyncLocators.gitModalLink).should( - "contain.text", - "Contact support", - ); + cy.get(locators._link).should("contain.text", "Contact support"); cy.get(gitSync.locators.repoLimitErrorModal).contains( Cypress.env("MESSAGES").REVOKE_CAUSE_APPLICATION_BREAK(), ); @@ -94,15 +90,20 @@ describe( windowOpenSpy.restore(); }); }); - cy.get(gitSyncLocators.gitModalLink).contains("Learn more").click(); + cy.get(locators._link).contains("Learn more").click(); - cy.get(gitSyncLocators.connectedApplication).should("have.length", 3); - cy.get(gitSyncLocators.diconnectLink).first().click(); + cy.get(gitSync.locators.repoLimitErrorModalArtifactList).should( + "have.length", + 3, + ); + cy.get(gitSync.locators.repoLimitErrorModalDisconnectLink) + .first() + .click(); cy.get(gitSync.locators.repoLimitErrorModal).should("not.exist"); - cy.get(gitSyncLocators.disconnectGitModal).should("exist"); + cy.get(gitSync.locators.disconnectModal).should("exist"); - cy.get(gitSyncLocators.closeGitSyncModal).click(); + cy.get(gitSync.locators.disconnectModalCloseBtn).click(); cy.get(gitSync.locators.repoLimitErrorModal).should("not.exist"); } }); diff --git a/app/client/cypress/e2e/Regression/ClientSide/Git/GitSync/SwitchBranches_spec.js b/app/client/cypress/e2e/Regression/ClientSide/Git/GitSync/SwitchBranches_spec.js index e07a41f13f8d..9fcda49e9d04 100644 --- a/app/client/cypress/e2e/Regression/ClientSide/Git/GitSync/SwitchBranches_spec.js +++ b/app/client/cypress/e2e/Regression/ClientSide/Git/GitSync/SwitchBranches_spec.js @@ -1,5 +1,4 @@ import commonLocators from "../../../../../locators/commonlocators.json"; -import gitSyncLocators from "../../../../../locators/gitSyncLocators"; import { agHelper, @@ -52,20 +51,20 @@ describe( // validate of the branch name const hypenBranchName = "hypen-branch-name"; - cy.get(gitSyncLocators.branchSearchInput).type( + cy.get(gitSync.locators.branchSearchInput).type( `{selectall}${hypenBranchName}`, ); agHelper.AssertAttribute( - gitSyncLocators.branchSearchInput, + gitSync.locators.branchSearchInput, "value", "hypen-branch-name", ); const specialBranchName = "special&branch-name~@#$%^&*()_+={}[]><,."; - cy.get(gitSyncLocators.branchSearchInput).type( + cy.get(gitSync.locators.branchSearchInput).type( `{selectall}${specialBranchName}`, ); agHelper.AssertAttribute( - gitSyncLocators.branchSearchInput, + gitSync.locators.branchSearchInput, "value", "special_branch-name_____________________", ); @@ -206,7 +205,7 @@ describe( // rename branch API missing in TED. // cy.renameBranchViaGithubApi(repoName, tempBranch, tempBranchRenamed); cy.get(gitSync.locators.quickActionsBranchBtn).click(); - cy.get(gitSyncLocators.branchSearchInput).type( + cy.get(gitSync.locators.branchSearchInput).type( `{selectall}${tempBranch}`, ); const tempBranchRegex = new RegExp(`^${tempBranch}$`); @@ -215,7 +214,7 @@ describe( `^origin/${tempBranchRenamed}$`, ); cy.get(gitSync.locators.branchItem).contains(tempBranchRegex); - cy.get(gitSyncLocators.syncBranches).click(); + cy.get(gitSync.locators.branchSyncBtn).click(); cy.get(gitSync.locators.branchItem) .contains(tempBranchRegex) .should("exist"); @@ -239,7 +238,7 @@ describe( //cy.createGitBranch(childBranchKey); PageList.AddNewPage(); cy.get(gitSync.locators.quickActionsBranchBtn).click({ force: true }); - cy.get(gitSyncLocators.branchSearchInput).type("{selectall}master"); + cy.get(gitSync.locators.branchSearchInput).type("{selectall}master"); cy.wait(400); cy.get(gitSync.locators.branchItem).contains("master").click(); cy.wait(4000); @@ -264,26 +263,26 @@ describe( childBKey = branName; cy.get(gitSync.locators.quickActionsBranchBtn).click(); - cy.get(gitSyncLocators.branchSearchInput).type( + cy.get(gitSync.locators.branchSearchInput).type( `{selectall}${parentBKey.slice(0, 3)}`, ); cy.get(gitSync.locators.branchItem).contains(parentBKey); - cy.get(gitSyncLocators.branchSearchInput).type( + cy.get(gitSync.locators.branchSearchInput).type( `{selectall}${childBKey.slice(0, 3)}`, ); cy.get(gitSync.locators.branchItem).contains(childBKey); - cy.get(gitSyncLocators.branchSearchInput).type( + cy.get(gitSync.locators.branchSearchInput).type( `{selectall}${branchQueryKey}`, ); cy.get(gitSync.locators.branchItem).contains(childBKey); cy.get(gitSync.locators.branchItem).contains(parentBKey); - cy.get(gitSyncLocators.branchSearchInput).type(`{selectall}abcde`); + cy.get(gitSync.locators.branchSearchInput).type(`{selectall}abcde`); cy.get(gitSync.locators.branchItem).should("not.exist"); - cy.get(gitSyncLocators.branchSearchInput).clear(); + cy.get(gitSync.locators.branchSearchInput).clear(); cy.get(gitSync.locators.branchItem).contains(childBKey); cy.get(gitSync.locators.branchItem).contains(parentBKey); }); diff --git a/app/client/cypress/e2e/Regression/ClientSide/Git/GitWithJSLibrary/GitwithCustomJSLibrary_spec.js b/app/client/cypress/e2e/Regression/ClientSide/Git/GitWithJSLibrary/GitwithCustomJSLibrary_spec.js index fec3529256ba..7b12a1bc60b9 100644 --- a/app/client/cypress/e2e/Regression/ClientSide/Git/GitWithJSLibrary/GitwithCustomJSLibrary_spec.js +++ b/app/client/cypress/e2e/Regression/ClientSide/Git/GitWithJSLibrary/GitwithCustomJSLibrary_spec.js @@ -1,5 +1,4 @@ import HomePage from "../../../../../locators/HomePage"; -import gitSyncLocators from "../../../../../locators/gitSyncLocators"; import { agHelper, homePage, @@ -71,7 +70,7 @@ describe( cy.get(gitSync.locators.quickActionsCommitBtn).click(); cy.get(gitSync.locators.opsCommitInput).should("be.disabled"); cy.get(gitSync.locators.opsCommitBtn).should("be.disabled"); - cy.get(gitSyncLocators.closeGitSyncModal).click(); + gitSync.CloseOpsModal(); AppSidebar.navigate(AppSidebarButton.Editor); // swtich to master, verify no uncommitted changes cy.switchGitBranch("master"); @@ -79,7 +78,7 @@ describe( cy.get(gitSync.locators.quickActionsCommitBtn).click(); cy.get(gitSync.locators.opsCommitInput).should("be.disabled"); cy.get(gitSync.locators.opsCommitBtn).should("be.disabled"); - cy.get(gitSyncLocators.closeGitSyncModal).click(); + gitSync.CloseOpsModal(); }); it("3. Merge custom js lib changes from child branch to master, verify changes are merged", () => { @@ -95,9 +94,9 @@ describe( cy.get(gitSync.locators.opsCommitInput).type("Initial Commit"); cy.get(gitSync.locators.opsCommitBtn).click(); agHelper.AssertElementExist(gitSync.locators.quickActionsPullBtn); - cy.get(gitSyncLocators.closeGitSyncModal).click(); + gitSync.CloseOpsModal(); cy.merge(mainBranch); - cy.get(gitSyncLocators.closeGitSyncModal).click(); + gitSync.CloseOpsModal(); AppSidebar.navigate(AppSidebarButton.Editor); // verify custom js library is present in master branch cy.switchGitBranch(mainBranch); diff --git a/app/client/cypress/e2e/Regression/ClientSide/Git/GitWithTheming/GitWithTheming_spec.js b/app/client/cypress/e2e/Regression/ClientSide/Git/GitWithTheming/GitWithTheming_spec.js index 6856f6ed38a2..f7f527cea337 100644 --- a/app/client/cypress/e2e/Regression/ClientSide/Git/GitWithTheming/GitWithTheming_spec.js +++ b/app/client/cypress/e2e/Regression/ClientSide/Git/GitWithTheming/GitWithTheming_spec.js @@ -111,41 +111,6 @@ describe( cy.get(commonlocators.backToEditor).click(); cy.wait(2000); }); - // commenting test until bug is closed - /*it("Bug #14645 Custom themes are not getting copied for create branch", function() { - cy.xpath("(//button[@type='button'])").should( - "have.css", - "background-color", - backgroudColorChildBranch, - ); - cy.switchGitBranch("master"); - cy.xpath("(//button[@type='button'])").should( - "have.css", - "background-color", - backgroudColorMaster, - ); - // delete tempBranch - cy.get(gitSync.locators.quickActionsBranchBtn).click(); - cy.get(gitSync.locators.branchItem) - .eq(1) - .trigger("mouseenter") - .within(() => { - cy.get(gitSync.locators.branchItemMenuBtn).click(); - cy.get(gitSyncLocators.gitBranchDelete).click(); - }); - cy.wait("@deleteBranch").should( - "have.nested.property", - "response.body.responseMeta.status", - 200, - ); - cy.get(gitSync.locators.branchCloseBtn).click(); - // verify the app doesnt crash - cy.xpath("(//button[@type='button'])").should( - "have.css", - "background-color", - backgroudColorMaster, - ); - }); */ after(() => { //clean up diff --git a/app/client/cypress/e2e/Regression/ClientSide/Templates/ForkTemplateToGitConnectedApp.js b/app/client/cypress/e2e/Regression/ClientSide/Templates/ForkTemplateToGitConnectedApp.js index b7112dbde01f..fac4503bb35a 100644 --- a/app/client/cypress/e2e/Regression/ClientSide/Templates/ForkTemplateToGitConnectedApp.js +++ b/app/client/cypress/e2e/Regression/ClientSide/Templates/ForkTemplateToGitConnectedApp.js @@ -1,5 +1,4 @@ import template from "../../../../locators/TemplatesLocators.json"; -import gitSyncLocators from "../../../../locators/gitSyncLocators"; import widgetLocators from "../../../../locators/Widgets.json"; let repoName; let newWorkspaceName; @@ -92,7 +91,7 @@ describe( cy.get(gitSync.locators.opsCommitInput).type("Initial Commit"); cy.get(gitSync.locators.opsCommitBtn).click(); _.agHelper.AssertElementExist(_.gitSync.locators.quickActionsPullBtn); - cy.get(gitSyncLocators.closeGitSyncModal).click(); + _.gitSync.CloseOpsModal(); }); }); diff --git a/app/client/cypress/support/Objects/CommonLocators.ts b/app/client/cypress/support/Objects/CommonLocators.ts index ebf4f547697e..547b14681d9a 100644 --- a/app/client/cypress/support/Objects/CommonLocators.ts +++ b/app/client/cypress/support/Objects/CommonLocators.ts @@ -7,6 +7,7 @@ export class CommonLocators { _chevronDown = "span[contains(@class, 'bp3-icon-chevron-down')]"; _loading = "#loading"; _animationSpnner = ".bp3-spinner-animation"; + _link = ".ads-v2-link"; _btnSpinner = ".ads-v2-spinner"; _sidebar = ".t--sidebar"; _queryName = ".editor-tab.active > .ads-v2-text"; diff --git a/app/client/cypress/support/Pages/GitSync.ts b/app/client/cypress/support/Pages/GitSync.ts index a18ac47bf04d..c1fecf5c9ac5 100644 --- a/app/client/cypress/support/Pages/GitSync.ts +++ b/app/client/cypress/support/Pages/GitSync.ts @@ -11,7 +11,8 @@ export class GitSync { public locators = { quickActionConnectBtn: "[data-testid='t--git-quick-actions-connect']", quickActionsCommitBtn: "[data-testid='t--git-quick-actions-commit'] button", - quickActionsCommitCount: "[data-testid='t--git-quick-actions-commit-count']", + quickActionsCommitCount: + "[data-testid='t--git-quick-actions-commit-count']", quickActionsPullBtn: "[data-testid='t--git-quick-actions-pull'] button", quickActionsBranchBtn: "[data-testid='t--git-quick-actions-branch']", quickActionsMergeBtn: "[data-testid='t--git-quick-actions-merge']", @@ -36,12 +37,14 @@ export class GitSync { importExistingRepoCheckbox: "[data-testid='t--git-import-existing-repo-checkbox']", disconnectModal: "[data-testid='t--git-disconnect-modal']", - disconnectModalCloseBtn: "//div[@data-testid='t--git-disconnect-modal']//button[@aria-label='Close']", + disconnectModalCloseBtn: + "//div[@data-testid='t--git-disconnect-modal']//button[@aria-label='Close']", disconnectModalInput: "[data-testid='t--git-disconnect-modal-input']", disconnectModalBackBtn: "[data-testid='t--git-disconnect-modal-back-btn']", disconnectModalRevokeBtn: "[data-testid='t--git-disconnect-modal-revoke-btn']", - disconnectModalLearnMoreLink: "[data-testid='t--git-disconnect-learn-more']", + disconnectModalLearnMoreLink: + "[data-testid='t--git-disconnect-learn-more']", connectSuccessModal: "[data-testid='t--git-con-success-modal']", connectSuccessModalCloseBtn: "//div[@data-testid='t--git-success-modal']//button[@aria-label='Close']", @@ -80,6 +83,10 @@ export class GitSync { autocommitLoader: "[data-testid='t--git-autocommit-loader']", conflictErrorOpenRepo: "[data-testid='t--git-conflict-error-open-repo']", repoLimitErrorModal: "[data-testid='t--git-repo-limit-error-modal']", + repoLimitErrorModalConnectedArtifact: + "[data-testid='t--git-repo-limit-error-connected-artifact']", + repoLimitErrorModalDisconnectLink: + "[data-testid='t--git-repo-limit-error-disconnect-link']", deployMenuConnect: "[data-testid='t--git-deploy-menu-connect']", }; diff --git a/app/client/cypress/support/gitSync.js b/app/client/cypress/support/gitSync.js index f6729032999d..33aa93c8a713 100644 --- a/app/client/cypress/support/gitSync.js +++ b/app/client/cypress/support/gitSync.js @@ -5,7 +5,6 @@ import { AppSidebar } from "./Pages/EditorNavigation"; require("cy-verify-downloads").addCustomCommand(); require("cypress-file-upload"); -import gitSyncLocators from "../locators/gitSyncLocators"; import homePage from "../locators/HomePage"; import { ObjectsRegistry } from "./Objects/Registry"; const gitSync = ObjectsRegistry.GitSync; @@ -39,8 +38,8 @@ Cypress.Commands.add("latestDeployPreview", () => { Cypress.Commands.add("createGitBranch", (branch) => { agHelper.AssertElementVisibility(gitSync.locators.quickActionsPullBtn); cy.get(gitSync.locators.quickActionsBranchBtn).click({ force: true }); - agHelper.AssertElementVisibility(gitSyncLocators.branchSearchInput); - agHelper.ClearNType(gitSyncLocators.branchSearchInput, `${branch}`); + agHelper.AssertElementVisibility(gitSync.locators.branchSearchInput); + agHelper.ClearNType(gitSync.locators.branchSearchInput, `${branch}`); // increasing timeout to reduce flakyness cy.get(".ads-v2-spinner", { timeout: Cypress.config().pageLoadTimeout, @@ -55,8 +54,8 @@ Cypress.Commands.add("createGitBranch", (branch) => { Cypress.Commands.add("switchGitBranch", (branch, expectError) => { agHelper.AssertElementVisibility(gitSync.locators.quickActionsPullBtn); cy.get(gitSync.locators.quickActionsBranchBtn).click({ force: true }); - agHelper.AssertElementVisibility(gitSyncLocators.branchSearchInput); - agHelper.ClearNType(gitSyncLocators.branchSearchInput, `${branch}`); + agHelper.AssertElementVisibility(gitSync.locators.branchSearchInput); + agHelper.ClearNType(gitSync.locators.branchSearchInput, `${branch}`); cy.get(gitSync.locators.branchItem).contains(branch).click(); if (!expectError) { // increasing timeout to reduce flakyness @@ -92,7 +91,7 @@ Cypress.Commands.add("commitAndPush", (assertFailure) => { }); } - cy.get(gitSyncLocators.closeGitSyncModal).click(); + gitSync.CloseOpsModal(); }); Cypress.Commands.add("merge", (destinationBranch) => { @@ -102,7 +101,7 @@ Cypress.Commands.add("merge", (destinationBranch) => { cy.intercept("GET", "/api/v1/git/branch/app/*").as(`gitBranches`); - cy.get(gitSyncLocators.bottomBarMergeButton).click({ force: true }); + cy.get(gitSync.locators.quickActionsMergeBtn).click({ force: true }); //cy.wait(6000); // wait for git status call to finish /*cy.wait("@gitStatus").should( "have.nested.property", @@ -139,61 +138,6 @@ Cypress.Commands.add("merge", (destinationBranch) => { }); }); -Cypress.Commands.add( - "importAppFromGit", - (repo, assertConnectFailure, failureMessage) => { - const testEmail = "test@test.com"; - const testUsername = "testusername"; - - cy.intercept("GET", "api/v1/git/import/keys?keyType=ECDSA").as( - `generateKey-${repo}`, - ); - cy.get(gitSyncLocators.gitRepoInput).type( - `${dataManager.GIT_CLONE_URL}/${repo}.git`, - ); - cy.get(gitSyncLocators.generateDeployKeyBtn).click(); - cy.wait(`@generateKey-${repo}`).then((result) => { - const key = result.response.body.data.publicKey.trimEnd(); - cy.request({ - method: "POST", - url: `${dataManager.GIT_API_BASE}/api/v1/git/keys/${repo}`, - body: { - title: "key1", - key, - read_only: false, - }, - }); - - cy.get(gitSyncLocators.useGlobalGitConfig).click({ force: true }); - - cy.get(gitSyncLocators.gitConfigNameInput).type( - `{selectall}${testUsername}`, - ); - cy.get(gitSyncLocators.gitConfigEmailInput).type( - `{selectall}${testEmail}`, - ); - // click on the connect button and verify - cy.get(gitSyncLocators.connectSubmitBtn).click(); - - if (!assertConnectFailure) { - // check for connect success - cy.wait("@importFromGit").should( - "have.nested.property", - "response.body.responseMeta.status", - 201, - ); - } else { - cy.wait("@importFromGit").then((interception) => { - const status = interception.response.body.responseMeta.status; - const message = interception.response.body.responseMeta.error.message; - expect(status).to.be.gte(400); - expect(message).to.contain(failureMessage); - }); - } - }); - }, -); - Cypress.Commands.add("gitDiscardChanges", () => { cy.get(gitSync.locators.quickActionsCommitBtn).click(); cy.get(gitSync.locators.opsDiscardBtn).should("be.visible"); @@ -214,51 +158,3 @@ Cypress.Commands.add("gitDiscardChanges", () => { "not.exist", ); }); - -Cypress.Commands.add( - "regenerateSSHKey", - (repo, generateKey = true, protocol = "ECDSA") => { - let generatedKey; - cy.get(gitSync.locators.quickActionsCommitBtn).click(); - cy.get("[data-testid=t--tab-GIT_CONNECTION]").click(); - cy.wait(2000); - cy.get(gitSyncLocators.SSHKeycontextmenu).eq(2).click(); - if (protocol === "ECDSA") { - cy.get(gitSyncLocators.regenerateSSHKeyECDSA).click(); - } else if (protocol === "RSA") { - cy.get(gitSyncLocators.regenerateSSHKeyRSA).click(); - } - cy.contains(Cypress.env("MESSAGES").REGENERATE_KEY_CONFIRM_MESSAGE()); - cy.xpath(gitSyncLocators.confirmButton).click(); - if (protocol === "ECDSA") { - cy.intercept("POST", "/api/v1/applications/ssh-keypair/*").as( - `generateKey-${repo}`, - ); - } else if (protocol === "RSA") { - cy.intercept("POST", "/api/v1/applications/ssh-keypair/*?keyType=RSA").as( - `generateKey-${repo}-RSA`, - ); - } - - if (generateKey) { - if (protocol === "ECDSA") { - cy.wait(`@generateKey-${repo}`).then((result) => { - const key = result.response.body.data.publicKey.trimEnd(); - cy.request({ - method: "POST", - url: `${dataManager.GIT_API_BASE}/api/v1/repos/Cypress/${repo}/keys`, - body: { - title: "key1", - key, - read_only: false, - }, - }); - - cy.get(gitSyncLocators.closeGitSyncModal); - }); - } else if (protocol === "RSA") { - // doesn't work with github - } - } - }, -); diff --git a/app/client/src/git/components/RepoLimitErrorModal/RepoLimitErrorModalView.tsx b/app/client/src/git/components/RepoLimitErrorModal/RepoLimitErrorModalView.tsx index d79958411808..d1f75c544c0e 100644 --- a/app/client/src/git/components/RepoLimitErrorModal/RepoLimitErrorModalView.tsx +++ b/app/client/src/git/components/RepoLimitErrorModal/RepoLimitErrorModalView.tsx @@ -189,7 +189,7 @@ function RepoLimitErrorModalView({ return (
@@ -203,7 +203,7 @@ function RepoLimitErrorModalView({
{isConflicting ? : null} - {showMergeSuccessIndicator ? : null} + {isMergeSuccess ? : null} {isMergeLoading ? ( - {!showMergeSuccessIndicator && showMergeButton ? ( + {!isMergeSuccess && showMergeButton ? (