From 2099fceffa441fb30a315612c90087cb43511e88 Mon Sep 17 00:00:00 2001 From: Rudraprasad Das Date: Thu, 21 Nov 2024 16:03:05 +0700 Subject: [PATCH] feat: git mod - package details and redux slice (#36989) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Description Introduces a new yarn package for git. Includes the yarn package files, redux slice and relevant redux actions Fixes #36808 Fixes #36809 Fixes #36810 This is not integrated into the monolith. So, this doesn't directly impact the product yet ## Automation /ok-to-test tags="@tag.Git" ### :mag: Cypress test results > [!TIP] > 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉 > Workflow run: > Commit: 02c38bff6be96f3572100f348f12c15ea94ae971 > Cypress dashboard. > Tags: `@tag.Git` > Spec: >
Wed, 23 Oct 2024 19:42:30 UTC ## Communication Should the DevRel and Marketing teams inform users about this change? - [ ] Yes - [ ] No ## Summary by CodeRabbit ## Release Notes - **New Features** - Introduced the `@appsmith/git` package for Git-related functionality. - Added a new `GitTest` component for testing purposes. - Implemented multiple actions for managing Git operations, including commit, connection, branch fetching, metadata fetching, status fetching, and pull actions. - Created a Redux slice for managing Git artifact state. - **Documentation** - Added TypeScript types and interfaces for better state management within the Git context. - Introduced ESLint configuration for consistent code quality across the package. These updates enhance the application's Git capabilities and improve state management, providing a more robust user experience. --- app/client/packages/git/.eslintrc.json | 3 + app/client/packages/git/package.json | 15 +++++ .../packages/git/src/actions/commitActions.ts | 26 +++++++ .../git/src/actions/connectActions.ts | 26 +++++++ .../git/src/actions/fetchBranchesActions.ts | 29 ++++++++ .../git/src/actions/fetchMetadataActions.ts | 29 ++++++++ .../git/src/actions/fetchStatusActions.ts | 29 ++++++++ .../helpers/createSingleArtifactAction.ts | 63 +++++++++++++++++ .../packages/git/src/actions/mountActions.ts | 28 ++++++++ .../packages/git/src/actions/pullActions.ts | 26 +++++++ .../git/src/components/connect/GitTest.tsx | 7 ++ .../git/src/store/gitArtifactSlice.ts | 67 +++++++++++++++++++ app/client/packages/git/src/store/index.ts | 0 app/client/packages/git/src/types.ts | 35 ++++++++++ app/client/packages/git/tsconfig.json | 4 ++ app/client/yarn.lock | 64 +++++++++++++++++- 16 files changed, 448 insertions(+), 3 deletions(-) create mode 100644 app/client/packages/git/.eslintrc.json create mode 100644 app/client/packages/git/package.json create mode 100644 app/client/packages/git/src/actions/commitActions.ts create mode 100644 app/client/packages/git/src/actions/connectActions.ts create mode 100644 app/client/packages/git/src/actions/fetchBranchesActions.ts create mode 100644 app/client/packages/git/src/actions/fetchMetadataActions.ts create mode 100644 app/client/packages/git/src/actions/fetchStatusActions.ts create mode 100644 app/client/packages/git/src/actions/helpers/createSingleArtifactAction.ts create mode 100644 app/client/packages/git/src/actions/mountActions.ts create mode 100644 app/client/packages/git/src/actions/pullActions.ts create mode 100644 app/client/packages/git/src/components/connect/GitTest.tsx create mode 100644 app/client/packages/git/src/store/gitArtifactSlice.ts create mode 100644 app/client/packages/git/src/store/index.ts create mode 100644 app/client/packages/git/src/types.ts create mode 100644 app/client/packages/git/tsconfig.json diff --git a/app/client/packages/git/.eslintrc.json b/app/client/packages/git/.eslintrc.json new file mode 100644 index 0000000000..b6652ce70c --- /dev/null +++ b/app/client/packages/git/.eslintrc.json @@ -0,0 +1,3 @@ +{ + "extends": ["../../.eslintrc.base.json"] +} diff --git a/app/client/packages/git/package.json b/app/client/packages/git/package.json new file mode 100644 index 0000000000..9bfcf578a7 --- /dev/null +++ b/app/client/packages/git/package.json @@ -0,0 +1,15 @@ +{ + "name": "@appsmith/git", + "description": "This package contains all the git related functionality for Appsmith UI", + "private": true, + "version": "1.0.0", + "main": "src/index.ts", + "scripts": { + "lint": "yarn g:lint", + "prettier": "yarn g:prettier", + "test:unit": "yarn g:jest --passWithNoTests" + }, + "dependencies": { + "@reduxjs/toolkit": "^2.3.0" + } +} diff --git a/app/client/packages/git/src/actions/commitActions.ts b/app/client/packages/git/src/actions/commitActions.ts new file mode 100644 index 0000000000..700866c830 --- /dev/null +++ b/app/client/packages/git/src/actions/commitActions.ts @@ -0,0 +1,26 @@ +import { createSingleArtifactAction } from "./helpers/createSingleArtifactAction"; +import type { GitArtifactPayloadAction } from "../types"; + +export const commitInitAction = createSingleArtifactAction((state) => { + state.commit.loading = true; + state.commit.error = null; + + return state; +}); + +export const commitSuccessAction = createSingleArtifactAction((state) => { + state.commit.loading = false; + + return state; +}); + +export const commitErrorAction = createSingleArtifactAction( + (state, action: GitArtifactPayloadAction<{ error: string }>) => { + const { error } = action.payload; + + state.commit.loading = false; + state.commit.error = error; + + return state; + }, +); diff --git a/app/client/packages/git/src/actions/connectActions.ts b/app/client/packages/git/src/actions/connectActions.ts new file mode 100644 index 0000000000..6a306cbd03 --- /dev/null +++ b/app/client/packages/git/src/actions/connectActions.ts @@ -0,0 +1,26 @@ +import { createSingleArtifactAction } from "./helpers/createSingleArtifactAction"; +import type { GitArtifactPayloadAction } from "../types"; + +export const connectInitAction = createSingleArtifactAction((state) => { + state.connect.loading = true; + state.connect.error = null; + + return state; +}); + +export const connectSuccessAction = createSingleArtifactAction((state) => { + state.connect.loading = false; + + return state; +}); + +export const connectErrorAction = createSingleArtifactAction( + (state, action: GitArtifactPayloadAction<{ error: string }>) => { + const { error } = action.payload; + + state.connect.loading = false; + state.connect.error = error; + + return state; + }, +); diff --git a/app/client/packages/git/src/actions/fetchBranchesActions.ts b/app/client/packages/git/src/actions/fetchBranchesActions.ts new file mode 100644 index 0000000000..fc073348d5 --- /dev/null +++ b/app/client/packages/git/src/actions/fetchBranchesActions.ts @@ -0,0 +1,29 @@ +import type { GitArtifactPayloadAction, GitBranches } from "../types"; +import { createSingleArtifactAction } from "./helpers/createSingleArtifactAction"; + +export const fetchBranchesInitAction = createSingleArtifactAction((state) => { + state.branches.loading = true; + state.branches.error = null; + + return state; +}); + +export const fetchBranchesSuccessAction = createSingleArtifactAction( + (state, action: GitArtifactPayloadAction<{ branches: GitBranches }>) => { + state.branches.loading = false; + state.branches.value = action.payload.branches; + + return state; + }, +); + +export const fetchBranchesErrorAction = createSingleArtifactAction( + (state, action: GitArtifactPayloadAction<{ error: string }>) => { + const { error } = action.payload; + + state.branches.loading = false; + state.branches.error = error; + + return state; + }, +); diff --git a/app/client/packages/git/src/actions/fetchMetadataActions.ts b/app/client/packages/git/src/actions/fetchMetadataActions.ts new file mode 100644 index 0000000000..d7b46dd255 --- /dev/null +++ b/app/client/packages/git/src/actions/fetchMetadataActions.ts @@ -0,0 +1,29 @@ +import type { GitArtifactPayloadAction, GitMetadata } from "../types"; +import { createSingleArtifactAction } from "./helpers/createSingleArtifactAction"; + +export const fetchMetadataInitAction = createSingleArtifactAction((state) => { + state.metadata.loading = true; + state.metadata.error = null; + + return state; +}); + +export const fetchMetadataSuccessAction = createSingleArtifactAction( + (state, action: GitArtifactPayloadAction<{ metadata: GitMetadata }>) => { + state.metadata.loading = false; + state.metadata.value = action.payload.metadata; + + return state; + }, +); + +export const fetchMetadataErrorAction = createSingleArtifactAction( + (state, action: GitArtifactPayloadAction<{ error: string }>) => { + const { error } = action.payload; + + state.metadata.loading = false; + state.metadata.error = error; + + return state; + }, +); diff --git a/app/client/packages/git/src/actions/fetchStatusActions.ts b/app/client/packages/git/src/actions/fetchStatusActions.ts new file mode 100644 index 0000000000..dcecbd91c0 --- /dev/null +++ b/app/client/packages/git/src/actions/fetchStatusActions.ts @@ -0,0 +1,29 @@ +import type { GitArtifactPayloadAction, GitStatus } from "../types"; +import { createSingleArtifactAction } from "./helpers/createSingleArtifactAction"; + +export const fetchStatusInitAction = createSingleArtifactAction((state) => { + state.status.loading = true; + state.status.error = null; + + return state; +}); + +export const fetchStatusSuccessAction = createSingleArtifactAction( + (state, action: GitArtifactPayloadAction<{ status: GitStatus }>) => { + state.status.loading = false; + state.status.value = action.payload.status; + + return state; + }, +); + +export const fetchStatusErrorAction = createSingleArtifactAction( + (state, action: GitArtifactPayloadAction<{ error: string }>) => { + const { error } = action.payload; + + state.status.loading = false; + state.status.error = error; + + return state; + }, +); diff --git a/app/client/packages/git/src/actions/helpers/createSingleArtifactAction.ts b/app/client/packages/git/src/actions/helpers/createSingleArtifactAction.ts new file mode 100644 index 0000000000..3ad93734c6 --- /dev/null +++ b/app/client/packages/git/src/actions/helpers/createSingleArtifactAction.ts @@ -0,0 +1,63 @@ +import type { + GitArtifactPayloadAction, + GitArtifactReduxState, + GitSingleArtifactReduxState, +} from "../../types"; + +type SingleArtifactStateCb = ( + singleArtifactState: GitSingleArtifactReduxState, + action: GitArtifactPayloadAction, +) => GitSingleArtifactReduxState; + +export const gitSingleArtifactInitialState: GitSingleArtifactReduxState = { + metadata: { + value: null, + loading: false, + error: null, + }, + connect: { + loading: false, + error: null, + }, + branches: { + value: null, + loading: false, + error: null, + }, + status: { + value: null, + loading: false, + error: null, + }, + commit: { + loading: false, + error: null, + }, + pull: { + loading: false, + error: null, + }, +}; + +export const createSingleArtifactAction = ( + singleArtifactStateCb: SingleArtifactStateCb, +) => { + return ( + state: GitArtifactReduxState, + action: GitArtifactPayloadAction, + ) => { + const { artifactType, baseArtifactId } = action.payload; + + state[artifactType] ??= {}; + state[artifactType][baseArtifactId] ??= gitSingleArtifactInitialState; + + const singleArtifactState = state[artifactType][baseArtifactId]; + + state[artifactType][baseArtifactId] = singleArtifactStateCb( + singleArtifactState, + action, + ); + + return state; + }; +}; diff --git a/app/client/packages/git/src/actions/mountActions.ts b/app/client/packages/git/src/actions/mountActions.ts new file mode 100644 index 0000000000..a4ee3d372d --- /dev/null +++ b/app/client/packages/git/src/actions/mountActions.ts @@ -0,0 +1,28 @@ +import type { PayloadAction } from "@reduxjs/toolkit"; +import type { GitArtifactBasePayload, GitArtifactReduxState } from "../types"; +import { gitSingleArtifactInitialState } from "./helpers/createSingleArtifactAction"; + +// ! This might be removed later + +export const mountAction = ( + state: GitArtifactReduxState, + action: PayloadAction, +) => { + const { artifactType, baseArtifactId } = action.payload; + + state[artifactType] ??= {}; + state[artifactType][baseArtifactId] ??= gitSingleArtifactInitialState; + + return state; +}; + +export const unmountAction = ( + state: GitArtifactReduxState, + action: PayloadAction, +) => { + const { artifactType, baseArtifactId } = action.payload; + + delete state?.[artifactType]?.[baseArtifactId]; + + return state; +}; diff --git a/app/client/packages/git/src/actions/pullActions.ts b/app/client/packages/git/src/actions/pullActions.ts new file mode 100644 index 0000000000..44311e3840 --- /dev/null +++ b/app/client/packages/git/src/actions/pullActions.ts @@ -0,0 +1,26 @@ +import { createSingleArtifactAction } from "./helpers/createSingleArtifactAction"; +import type { GitArtifactPayloadAction } from "../types"; + +export const pullInitAction = createSingleArtifactAction((state) => { + state.pull.loading = true; + state.pull.error = null; + + return state; +}); + +export const pullSuccessAction = createSingleArtifactAction((state) => { + state.pull.loading = false; + + return state; +}); + +export const pullErrorAction = createSingleArtifactAction( + (state, action: GitArtifactPayloadAction<{ error: string }>) => { + const { error } = action.payload; + + state.pull.loading = false; + state.pull.error = error; + + return state; + }, +); diff --git a/app/client/packages/git/src/components/connect/GitTest.tsx b/app/client/packages/git/src/components/connect/GitTest.tsx new file mode 100644 index 0000000000..88e24b56e3 --- /dev/null +++ b/app/client/packages/git/src/components/connect/GitTest.tsx @@ -0,0 +1,7 @@ +import React from "react"; + +function GitTest() { + return
GitTest
; +} + +export default GitTest; diff --git a/app/client/packages/git/src/store/gitArtifactSlice.ts b/app/client/packages/git/src/store/gitArtifactSlice.ts new file mode 100644 index 0000000000..73b50f2c19 --- /dev/null +++ b/app/client/packages/git/src/store/gitArtifactSlice.ts @@ -0,0 +1,67 @@ +/* eslint-disable padding-line-between-statements */ +import { createSlice } from "@reduxjs/toolkit"; +import type { GitArtifactReduxState } from "../types"; +import { mountAction, unmountAction } from "../actions/mountActions"; +import { + connectErrorAction, + connectInitAction, + connectSuccessAction, +} from "../actions/connectActions"; +import { + fetchMetadataErrorAction, + fetchMetadataInitAction, + fetchMetadataSuccessAction, +} from "../actions/fetchMetadataActions"; +import { + fetchBranchesErrorAction, + fetchBranchesInitAction, + fetchBranchesSuccessAction, +} from "../actions/fetchBranchesActions"; +import { + fetchStatusErrorAction, + fetchStatusInitAction, + fetchStatusSuccessAction, +} from "../actions/fetchStatusActions"; +import { + commitErrorAction, + commitInitAction, + commitSuccessAction, +} from "../actions/commitActions"; +import { + pullErrorAction, + pullInitAction, + pullSuccessAction, +} from "../actions/pullActions"; + +const initialState: GitArtifactReduxState = {}; + +export const gitArtifactSlice = createSlice({ + name: "gitArtifact", + initialState, + reducers: { + mount: mountAction, + unmount: unmountAction, + connectInit: connectInitAction, + connectSuccess: connectSuccessAction, + connectError: connectErrorAction, + fetchMetadataInit: fetchMetadataInitAction, + fetchMetadataSuccess: fetchMetadataSuccessAction, + fetchMetadataError: fetchMetadataErrorAction, + fetchBranchesInit: fetchBranchesInitAction, + fetchBranchesSuccess: fetchBranchesSuccessAction, + fetchBranchesError: fetchBranchesErrorAction, + fetchStatusInit: fetchStatusInitAction, + fetchStatusSuccess: fetchStatusSuccessAction, + fetchStatusError: fetchStatusErrorAction, + commitInit: commitInitAction, + commitSuccess: commitSuccessAction, + commitError: commitErrorAction, + pullInit: pullInitAction, + pullSuccess: pullSuccessAction, + pullError: pullErrorAction, + }, +}); + +export const gitArtifactActions = gitArtifactSlice.actions; + +export default gitArtifactSlice.reducer; diff --git a/app/client/packages/git/src/store/index.ts b/app/client/packages/git/src/store/index.ts new file mode 100644 index 0000000000..e69de29bb2 diff --git a/app/client/packages/git/src/types.ts b/app/client/packages/git/src/types.ts new file mode 100644 index 0000000000..df64af3312 --- /dev/null +++ b/app/client/packages/git/src/types.ts @@ -0,0 +1,35 @@ +import type { PayloadAction } from "@reduxjs/toolkit"; + +// These will be updated when contracts are finalized +export type GitMetadata = Record; + +export type GitBranches = Record; + +export type GitStatus = Record; + +interface AsyncState { + value: T | null; + loading: boolean; + error: string | null; +} + +export interface GitSingleArtifactReduxState { + metadata: AsyncState; + connect: Omit; + branches: AsyncState; + status: AsyncState; + commit: Omit; + pull: Omit; +} + +export interface GitArtifactReduxState { + [key: string]: Record; +} + +export interface GitArtifactBasePayload { + artifactType: string; + baseArtifactId: string; +} + +export type GitArtifactPayloadAction> = + PayloadAction; diff --git a/app/client/packages/git/tsconfig.json b/app/client/packages/git/tsconfig.json new file mode 100644 index 0000000000..752e48c03e --- /dev/null +++ b/app/client/packages/git/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "../../tsconfig.json", + "include": ["./src/**/*"] +} diff --git a/app/client/yarn.lock b/app/client/yarn.lock index 88c6bbf5d0..5e70812a01 100644 --- a/app/client/yarn.lock +++ b/app/client/yarn.lock @@ -192,6 +192,14 @@ __metadata: languageName: unknown linkType: soft +"@appsmith/git@workspace:packages/git": + version: 0.0.0-use.local + resolution: "@appsmith/git@workspace:packages/git" + dependencies: + "@reduxjs/toolkit": ^2.3.0 + languageName: unknown + linkType: soft + "@appsmith/utils@workspace:^, @appsmith/utils@workspace:packages/utils": version: 0.0.0-use.local resolution: "@appsmith/utils@workspace:packages/utils" @@ -8011,6 +8019,26 @@ __metadata: languageName: node linkType: hard +"@reduxjs/toolkit@npm:^2.3.0": + version: 2.3.0 + resolution: "@reduxjs/toolkit@npm:2.3.0" + dependencies: + immer: ^10.0.3 + redux: ^5.0.1 + redux-thunk: ^3.1.0 + reselect: ^5.1.0 + peerDependencies: + react: ^16.9.0 || ^17.0.0 || ^18 + react-redux: ^7.2.1 || ^8.1.3 || ^9.0.0 + peerDependenciesMeta: + react: + optional: true + react-redux: + optional: true + checksum: 1a0d85978f99a44f7ceabec8623f46cdd2a2dc25d809dfb0d5c9cd13e2aa12cf116cffe34a4ed949169804dc6125ef9cf68143225e9527f861b597ea701e8bb5 + languageName: node + linkType: hard + "@rollup/plugin-babel@npm:^5.2.0": version: 5.3.1 resolution: "@rollup/plugin-babel@npm:5.3.1" @@ -20770,10 +20798,17 @@ __metadata: languageName: node linkType: hard +"immer@npm:^10.0.3": + version: 10.1.1 + resolution: "immer@npm:10.1.1" + checksum: 07c67970b7d22aded73607193d84861bf786f07d47f7d7c98bb10016c7a88f6654ad78ae1e220b3c623695b133aabbf24f5eb8d9e8060cff11e89ccd81c9c10b + languageName: node + linkType: hard + "immer@npm:^9.0.6, immer@npm:^9.0.7": - version: 9.0.14 - resolution: "immer@npm:9.0.14" - checksum: 17f1365c06d653e672a4f609f08e7203e9ab4b4284818332d6ca9b3f3577a0e3c0066ca7933b636fbae560df79a4b3fde70ed717ce3c6e95c39bf3d5861d5be9 + version: 9.0.21 + resolution: "immer@npm:9.0.21" + checksum: 70e3c274165995352f6936695f0ef4723c52c92c92dd0e9afdfe008175af39fa28e76aafb3a2ca9d57d1fb8f796efc4dd1e1cc36f18d33fa5b74f3dfb0375432 languageName: node linkType: hard @@ -29630,6 +29665,15 @@ __metadata: languageName: node linkType: hard +"redux-thunk@npm:^3.1.0": + version: 3.1.0 + resolution: "redux-thunk@npm:3.1.0" + peerDependencies: + redux: ^5.0.0 + checksum: bea96f8233975aad4c9f24ca1ffd08ac7ec91eaefc26e7ba9935544dc55d7f09ba2aa726676dab53dc79d0c91e8071f9729cddfea927f4c41839757d2ade0f50 + languageName: node + linkType: hard + "redux@npm:^3.6.0 || ^4.0.0, redux@npm:^4.0.0, redux@npm:^4.0.1, redux@npm:^4.0.4, redux@npm:^4.0.5": version: 4.0.5 resolution: "redux@npm:4.0.5" @@ -29640,6 +29684,13 @@ __metadata: languageName: node linkType: hard +"redux@npm:^5.0.1": + version: 5.0.1 + resolution: "redux@npm:5.0.1" + checksum: e74affa9009dd5d994878b9a1ce30d6569d986117175056edb003de2651c05b10fe7819d6fa94aea1a94de9a82f252f986547f007a2fbeb35c317a2e5f5ecf2c + languageName: node + linkType: hard + "reflect.getprototypeof@npm:^1.0.4": version: 1.0.4 resolution: "reflect.getprototypeof@npm:1.0.4" @@ -29931,6 +29982,13 @@ __metadata: languageName: node linkType: hard +"reselect@npm:^5.1.0": + version: 5.1.1 + resolution: "reselect@npm:5.1.1" + checksum: 5d32d48be29071ddda21a775945c2210cf4ca3fccde1c4a0e1582ac3bf99c431c6c2330ef7ca34eae4c06feea617e7cb2c275c4b33ccf9a930836dfc98b49b13 + languageName: node + linkType: hard + "resize-observer-polyfill@npm:^1.5.0, resize-observer-polyfill@npm:^1.5.1": version: 1.5.1 resolution: "resize-observer-polyfill@npm:1.5.1"