fix: adding new settings modal (#30320)

## Description
Separates git sync modal from git settings modal

#### PR fixes following issue(s)
Fixes #30319 

#### Media
> A video or a GIF is preferred. when using Loom, don’t embed because it
looks like it’s a GIF. instead, just link to the video
>
>
#### Type of change
- New feature (non-breaking change which adds functionality)
>
>
>
## Testing
>
#### How Has This Been Tested?
> Please describe the tests that you ran to verify your changes. Also
list any relevant details for your test configuration.
> Delete anything that is not relevant
- [ ] Manual
- [ ] JUnit
- [ ] Jest
- [ ] Cypress
>
>
#### Test Plan
> Add Testsmith test cases links that relate to this PR
>
>
#### Issues raised during DP testing
> Link issues raised during DP testing for better visiblity and tracking
(copy link from comments dropped on this PR)
>
>
>
## Checklist:
#### Dev activity
- [ ] My code follows the style guidelines of this project
- [ ] I have performed a self-review of my own code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation
- [ ] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my
feature works
- [ ] New and existing unit tests pass locally with my changes
- [ ] PR is being merged under a feature flag


#### QA activity:
- [ ] [Speedbreak
features](https://github.com/appsmithorg/TestSmith/wiki/Guidelines-for-test-plans#speedbreakers-)
have been covered
- [ ] Test plan covers all impacted features and [areas of
interest](https://github.com/appsmithorg/TestSmith/wiki/Guidelines-for-test-plans#areas-of-interest-)
- [ ] Test plan has been peer reviewed by project stakeholders and other
QA members
- [ ] Manually tested functionality on DP
- [ ] We had an implementation alignment call with stakeholders post QA
Round 2
- [ ] Cypress test cases have been added and approved by SDET/manual QA
- [ ] Added `Test Plan Approved` label after Cypress tests were reviewed
- [ ] Added `Test Plan Approved` label after JUnit tests were reviewed


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **New Features**
	- Introduced the `GitSettingsModal` for enhanced Git configuration.
- Added the ability to switch between General and Branch settings tabs
within the Git settings modal.
- Implemented new user permission checks for displaying Git user
settings and danger zone sections.

- **Enhancements**
- Streamlined the Git settings experience by removing unnecessary modals
and components.

- **Refactor**
- Improved action and selector naming for better clarity and
maintainability.
- Adjusted UI components to utilize new Redux state management for Git
settings.

- **Style**
	- Updated padding for better visual spacing in Git user settings.

- **Tests**
- Modified and removed tests to align with the updated component
structure and functionality.

- **Bug Fixes**
- Fixed navigation issues within the Git settings modal by refining
action dispatches and state handling.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
Rudraprasad Das 2024-01-19 15:14:38 +05:30 committed by GitHub
parent 302ecb6a1c
commit 877aa1a2c9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
21 changed files with 220 additions and 57 deletions

View File

@ -9,9 +9,10 @@ import {
import type { ConnectToGitPayload } from "api/GitSyncAPI";
import type { GitConfig, GitSyncModalTab, MergeStatus } from "entities/GitSync";
import type { GitApplicationMetadata } from "@appsmith/api/ApplicationApi";
import type {
GitStatusData,
GitRemoteStatusData,
import {
type GitStatusData,
type GitRemoteStatusData,
GitSettingsTab,
} from "reducers/uiReducers/gitSyncReducer";
import type { ResponseMeta } from "api/ApiResponses";
import { noop } from "lodash";
@ -506,3 +507,11 @@ export const stopAutocommitProgressPolling = () => ({
export const getGitMetadataInitAction = () => ({
type: ReduxActionTypes.GIT_GET_METADATA_INIT,
});
export const setGitSettingsModalOpenAction = (payload: {
open: boolean;
tab?: GitSettingsTab;
}) => ({
type: ReduxActionTypes.GIT_SET_SETTINGS_MODAL_OPEN,
payload: { open: payload.open, tab: payload.tab || GitSettingsTab.GENERAL },
});

View File

@ -140,6 +140,8 @@ const ActionTypes = {
GIT_GET_METADATA_INIT: "GIT_GET_METADATA_INIT",
GIT_GET_METADATA_SUCCESS: "GIT_GET_METADATA_SUCCESS",
GIT_SET_SETTINGS_MODAL_OPEN: "GIT_SET_SETTINGS_MODAL_OPEN",
APP_COLLAB_LIST_EDITORS: "APP_COLLAB_LIST_EDITORS",
APP_COLLAB_RESET_EDITORS: "APP_COLLAB_RESET_EDITORS",
APP_COLLAB_SET_EDITORS_POINTER_DATA: "APP_COLLAB_SET_EDITORS_POINTER_DATA",

View File

@ -1110,6 +1110,9 @@ export const UPDATE_DEFAULT_BRANCH_SUCCESS = (branchName: string) =>
`Updated default branch ${!!branchName ? `to ${branchName}` : ""}`;
export const CONTACT_ADMIN_FOR_GIT = () =>
"Please contact your workspace admin to connect your app to a git repo";
export const GENERAL = () => "General";
export const BRANCH = () => "Branch";
// Git Branch Protection end
export const NAV_DESCRIPTION = () =>
@ -1798,7 +1801,6 @@ export const SAVE_OR_DISCARD_DATASOURCE_WARNING = () =>
export const APP_SETTINGS_PANE_HEADER = () => "Settings";
export const APP_SETTINGS_CLOSE_TOOLTIP = () => "Close settings panel";
export const GENERAL_SETTINGS_SECTION_HEADER = () => "General";
export const GENERAL_SETTINGS_SECTION_CONTENT_HEADER = () => "General settings";
export const GENERAL_SETTINGS_SECTION_HEADER_DESC = () =>
"App name, icon and share";

View File

@ -78,7 +78,6 @@ import SharedUserList from "pages/common/SharedUserList";
import { useIsMobileDevice } from "utils/hooks/useDeviceDetect";
import { Indices } from "constants/Layers";
import GitSyncModal from "pages/Editor/gitSync/GitSyncModal";
import DisconnectGitModal from "pages/Editor/gitSync/DisconnectGitModal";
import ReconnectDatasourceModal from "pages/Editor/gitSync/ReconnectDatasourceModal";
import LeftPaneBottomSection from "pages/Home/LeftPaneBottomSection";
import { MOBILE_MAX_WIDTH } from "constants/AppConstants";
@ -108,7 +107,6 @@ import WorkflowCardList from "@appsmith/pages/Applications/WorkflowCardList";
import { allowManageEnvironmentAccessForUser } from "@appsmith/selectors/environmentSelectors";
import CreateNewAppsOption from "@appsmith/pages/Applications/CreateNewAppsOption";
import { resetCurrentApplicationIdForCreateNewApp } from "actions/onboardingActions";
import DisableAutocommitModal from "pages/Editor/gitSync/DisableAutocommitModal";
import { getCurrentWorkspaceId } from "@appsmith/selectors/workspaceSelectors";
export const { cloudHosting } = getAppsmithConfigs();
@ -786,11 +784,7 @@ export function ApplicationsSection(props: any) {
isMobile={isMobile}
>
{workspacesListComponent}
<>
<GitSyncModal isImport />
<DisableAutocommitModal />
<DisconnectGitModal />
</>
<GitSyncModal isImport />
<ReconnectDatasourceModal />
</ApplicationContainer>
);

View File

@ -14,8 +14,8 @@ import { getAppSettingsPane } from "selectors/appSettingsPaneSelectors";
import {
APP_NAVIGATION_SETTING,
createMessage,
GENERAL,
GENERAL_SETTINGS_SECTION_CONTENT_HEADER,
GENERAL_SETTINGS_SECTION_HEADER,
GENERAL_SETTINGS_SECTION_HEADER_DESC,
IN_APP_EMBED_SETTING,
PAGE_SETTINGS_SECTION_CONTENT_HEADER,
@ -127,7 +127,7 @@ function AppSettings() {
id: "t--general-settings-header",
icon: "settings-2-line",
isSelected: selectedTab.type === AppSettingsTabs.General,
name: createMessage(GENERAL_SETTINGS_SECTION_HEADER),
name: createMessage(GENERAL),
onClick: () => {
setSelectedTab({ type: AppSettingsTabs.General });
AnalyticsUtil.logEvent("APP_SETTINGS_SECTION_CLICK", {

View File

@ -1,22 +1,19 @@
/* eslint-disable jest/no-focused-tests */
import React from "react";
import { render, screen } from "test/testUtils";
import GitSettings from ".";
import TabBranch from ".";
import type { AppState } from "@appsmith/reducers";
jest.mock("../../hooks/gitPermissionHooks", () => ({
useHasManageProtectedBranchesPermission: () => false,
useHasManageDefaultBranchPermission: () => false,
useHasConnectToGitPermission: () => false,
useHasManageAutoCommitPermission: () => false,
}));
describe("GitSettings test for git admin disabled", () => {
it("Branch protection, default branch and disconnect disabled when not ", () => {
describe("TabBranch test for git admin disabled", () => {
it("Branch protection and default branch disabled when no permission", () => {
const initialState: Partial<AppState> = {};
render(<GitSettings />, { initialState });
render(<TabBranch />, { initialState });
expect(screen.queryByTestId("t--git-protected-branches-select")).toBe(null);
expect(screen.queryByTestId("t--git-default-branch-select")).toBe(null);
expect(screen.queryByTestId("t--git-disconnect-btn")).toBe(null);
});
});

View File

@ -1,15 +1,11 @@
import React from "react";
import GitUserSettings from "./GitUserSettings";
import DangerZone from "./DangerZone";
import styled from "styled-components";
import { Divider, ModalBody } from "design-system";
import { ModalBody } from "design-system";
import GitDefaultBranch from "./GitDefaultBranch";
import GitProtectedBranches from "./GitProtectedBranches";
import {
useHasConnectToGitPermission,
useHasManageDefaultBranchPermission,
useHasManageProtectedBranchesPermission,
useHasManageAutoCommitPermission,
} from "../../hooks/gitPermissionHooks";
const Container = styled.div`
@ -17,36 +13,22 @@ const Container = styled.div`
min-height: calc(360px + 52px);
`;
const StyledDivider = styled(Divider)`
display: block;
margin-top: 8px;
margin-bottom: 8px;
`;
function GitSettings() {
function TabBranch() {
const isManageProtectedBranchesPermitted =
useHasManageProtectedBranchesPermission();
const isManageDefaultBranchPermitted = useHasManageDefaultBranchPermission();
const isConnectToGitPermitted = useHasConnectToGitPermission();
const isManageAutoCommitPermitted = useHasManageAutoCommitPermission();
const showDivider =
isManageDefaultBranchPermitted || isManageProtectedBranchesPermitted;
const showDangerZone = isConnectToGitPermitted || isManageAutoCommitPermitted;
const showDefaultBranch = isManageDefaultBranchPermitted;
const showProtectedBranches = isManageProtectedBranchesPermitted;
return (
<ModalBody>
<Container>
<GitUserSettings />
{showDivider && <StyledDivider />}
{showDefaultBranch && <GitDefaultBranch />}
{showProtectedBranches && <GitProtectedBranches />}
{showDangerZone && <DangerZone />}
</Container>
</ModalBody>
);
}
export default GitSettings;
export default TabBranch;

View File

@ -31,7 +31,7 @@ import {
const Container = styled.div`
padding-top: 8px;
padding-bottom: 16px;
padding-bottom: 8px;
`;
const HeadContainer = styled.div`

View File

@ -0,0 +1,18 @@
/* eslint-disable jest/no-focused-tests */
import React from "react";
import { render, screen } from "test/testUtils";
import TabGeneral from ".";
import type { AppState } from "@appsmith/reducers";
jest.mock("../../hooks/gitPermissionHooks", () => ({
useHasConnectToGitPermission: () => false,
useHasManageAutoCommitPermission: () => false,
}));
describe("GitSettings TabGeneral test for git admin disabled", () => {
it("disconnect disabled when no permission", () => {
const initialState: Partial<AppState> = {};
render(<TabGeneral />, { initialState });
expect(screen.queryByTestId("t--git-disconnect-btn")).toBe(null);
});
});

View File

@ -0,0 +1,32 @@
import React from "react";
import GitUserSettings from "./GitUserSettings";
import DangerZone from "./DangerZone";
import styled from "styled-components";
import { ModalBody } from "design-system";
import {
useHasConnectToGitPermission,
useHasManageAutoCommitPermission,
} from "../../hooks/gitPermissionHooks";
const Container = styled.div`
overflow: auto;
min-height: calc(360px + 52px);
`;
function TabGeneral() {
const isConnectToGitPermitted = useHasConnectToGitPermission();
const isManageAutoCommitPermitted = useHasManageAutoCommitPermission();
const showDangerZone = isConnectToGitPermitted || isManageAutoCommitPermitted;
return (
<ModalBody>
<Container>
<GitUserSettings />
{showDangerZone && <DangerZone />}
</Container>
</ModalBody>
);
}
export default TabGeneral;

View File

@ -0,0 +1,91 @@
import React from "react";
import {
activeGitSettingsModalTabSelector,
isGitSettingsModalOpenSelector,
} from "selectors/gitSyncSelectors";
import { useDispatch, useSelector } from "react-redux";
import { setGitSettingsModalOpenAction } from "actions/gitSyncActions";
import GitErrorPopup from "../components/GitErrorPopup";
import { Modal, ModalContent, ModalHeader } from "design-system";
import styled from "styled-components";
import Menu from "../Menu";
import { GitSettingsTab } from "reducers/uiReducers/gitSyncReducer";
import {
BRANCH,
GENERAL,
SETTINGS_GIT,
createMessage,
} from "@appsmith/constants/messages";
import TabGeneral from "./TabGeneral";
import TabBranch from "./TabBranch";
const menuOptions = [
{
key: GitSettingsTab.GENERAL,
title: createMessage(GENERAL),
},
{
key: GitSettingsTab.BRANCH,
title: createMessage(BRANCH),
},
];
const StyledModalContent = styled(ModalContent)`
&&& {
width: 640px;
transform: none !important;
top: 100px;
left: calc(50% - 320px);
max-height: calc(100vh - 200px);
}
`;
function GitSettingsModal() {
const isModalOpen = useSelector(isGitSettingsModalOpenSelector);
const activeTabKey = useSelector(activeGitSettingsModalTabSelector);
const dispatch = useDispatch();
const setActiveTabKey = (tabKey: GitSettingsTab) => {
dispatch(
setGitSettingsModalOpenAction({
open: true,
tab: tabKey,
}),
);
};
const handleClose = () => {
dispatch(setGitSettingsModalOpenAction({ open: false }));
};
return (
<>
<Modal
onOpenChange={(open) => {
if (!open) {
handleClose();
}
}}
open={isModalOpen}
>
<StyledModalContent data-testid="t--git-settings-modal">
<ModalHeader>{createMessage(SETTINGS_GIT)}</ModalHeader>
<Menu
activeTabKey={activeTabKey}
onSelect={(tabKey: string) =>
setActiveTabKey(tabKey as GitSettingsTab)
}
options={menuOptions}
/>
{activeTabKey === GitSettingsTab.GENERAL && <TabGeneral />}
{activeTabKey === GitSettingsTab.BRANCH && <TabBranch />}
</StyledModalContent>
</Modal>
<GitErrorPopup />
</>
);
}
export default GitSettingsModal;

View File

@ -26,7 +26,6 @@ import {
import AnalyticsUtil from "utils/AnalyticsUtil";
import { Modal, ModalContent, ModalHeader } from "design-system";
import GitConnectionV2 from "../Tabs/GitConnectionV2";
import GitSettings from "../Tabs/GitSettings";
import { GitSyncModalTab } from "entities/GitSync";
import ConnectionSuccess from "../Tabs/ConnectionSuccess";
import styled from "styled-components";
@ -152,7 +151,6 @@ function GitSyncModalV2({ isImport = false }: GitSyncModalV2Props) {
))}
{activeTabKey === GitSyncModalTab.DEPLOY && <Deploy />}
{activeTabKey === GitSyncModalTab.MERGE && <Merge />}
{activeTabKey === GitSyncModalTab.SETTINGS && <GitSettings />}
</StyledModalContent>
</Modal>
<GitErrorPopup />

View File

@ -27,6 +27,7 @@ import { useDispatch, useSelector } from "react-redux";
import {
discardChanges,
gitPullInit,
setGitSettingsModalOpenAction,
setIsGitSyncModalOpen,
} from "actions/gitSyncActions";
import { GitSyncModalTab } from "entities/GitSync";
@ -49,6 +50,7 @@ import { useFeatureFlag } from "utils/hooks/useFeatureFlag";
import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag";
import AutocommitStatusbar from "./AutocommitStatusbar";
import { useHasConnectToGitPermission } from "../hooks/gitPermissionHooks";
import { GitSettingsTab } from "reducers/uiReducers/gitSyncReducer";
interface QuickActionButtonProps {
className?: string;
@ -354,15 +356,22 @@ export default function QuickGitActions() {
});
},
settings: () => {
dispatch(
setIsGitSyncModalOpen({
isOpen: true,
tab: isGitConnectV2Enabled
? GitSyncModalTab.SETTINGS
: GitSyncModalTab.GIT_CONNECTION,
isDeploying: true,
}),
);
if (isGitConnectV2Enabled) {
dispatch(
setGitSettingsModalOpenAction({
open: true,
tab: GitSettingsTab.GENERAL,
}),
);
} else {
dispatch(
setIsGitSyncModalOpen({
isOpen: true,
tab: GitSyncModalTab.GIT_CONNECTION,
isDeploying: true,
}),
);
}
AnalyticsUtil.logEvent("GS_SETTING_CLICK", {
source: "BOTTOM_BAR_GIT_SETTING_BUTTON",
});

View File

@ -1,5 +1,6 @@
import {
fetchBranchesInit,
setGitSettingsModalOpenAction,
setIsGitSyncModalOpen,
} from "actions/gitSyncActions";
import {
@ -14,12 +15,12 @@ import {
createMessage,
} from "@appsmith/constants/messages";
import { Button, Icon, ModalBody, ModalFooter, Tag, Text } from "design-system";
import { GitSyncModalTab } from "entities/GitSync";
import React, { useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import styled from "styled-components";
import { getCurrentAppGitMetaData } from "@appsmith/selectors/applicationSelectors";
import AnalyticsUtil from "utils/AnalyticsUtil";
import { GitSettingsTab } from "reducers/uiReducers/gitSyncReducer";
const Container = styled.div``;
@ -91,9 +92,9 @@ function ConnectionSuccess() {
const handleOpenSettings = () => {
dispatch(
setIsGitSyncModalOpen({
isOpen: true,
tab: GitSyncModalTab.SETTINGS,
setGitSettingsModalOpenAction({
open: true,
tab: GitSettingsTab.GENERAL,
}),
);
AnalyticsUtil.logEvent("GS_OPEN_GIT_SETTINGS", {

View File

@ -44,6 +44,7 @@ import { editorInitializer } from "../../utils/editor/EditorUtils";
import { widgetInitialisationSuccess } from "../../actions/widgetActions";
import urlBuilder from "@appsmith/entities/URLRedirect/URLAssembly";
import DisableAutocommitModal from "./gitSync/DisableAutocommitModal";
import GitSettingsModal from "./gitSync/GitSettingsModal";
interface EditorProps {
currentApplicationId?: string;
@ -167,6 +168,7 @@ class Editor extends Component<Props> {
<GlobalHotKeys>
<IDE />
<GitSyncModal />
<GitSettingsModal />
<DisconnectGitModal />
<DisableAutocommitModal />
<GuidedTourModal />

View File

@ -9,6 +9,12 @@ import { GitSyncModalTab } from "entities/GitSync";
import type { GetSSHKeyResponseData, SSHKeyType } from "actions/gitSyncActions";
import type { PageDefaultMeta } from "@appsmith/api/ApplicationApi";
export enum GitSettingsTab {
GENERAL = "GENERAL",
BRANCH = "BRANCH",
CD = "CD",
}
const initialState: GitSyncReducerState = {
isGitSyncModalOpen: false,
isCommitting: false,
@ -51,6 +57,9 @@ const initialState: GitSyncReducerState = {
gitMetadata: null,
gitMetadataLoading: false,
isGitSettingsModalOpen: false,
activeGitSettingsModalTab: GitSettingsTab.GENERAL,
};
const gitSyncReducer = createReducer(initialState, {
@ -652,6 +661,14 @@ const gitSyncReducer = createReducer(initialState, {
...state,
gitMetadataLoading: false,
}),
[ReduxActionTypes.GIT_SET_SETTINGS_MODAL_OPEN]: (
state,
action: ReduxAction<{ open: boolean; tab?: GitSettingsTab }>,
) => ({
...state,
isGitSettingsModalOpen: action.payload.open,
activeGitSettingsModalTab: action.payload.tab || GitSettingsTab.GENERAL,
}),
});
export interface GitStatusData {
@ -813,6 +830,9 @@ export type GitSyncReducerState = GitBranchDeleteState & {
gitMetadata: GitMetadata | null;
gitMetadataLoading: boolean;
isGitSettingsModalOpen: boolean;
activeGitSettingsModalTab: GitSettingsTab;
};
export default gitSyncReducer;

View File

@ -261,3 +261,9 @@ export const getGitMetadataLoadingSelector = (state: AppState) =>
export const getAutocommitEnabledSelector = (state: AppState) =>
!!state.ui.gitSync.gitMetadata?.autoCommitConfig?.enabled;
export const isGitSettingsModalOpenSelector = (state: AppState) =>
state.ui.gitSync.isGitSettingsModalOpen;
export const activeGitSettingsModalTabSelector = (state: AppState) =>
state.ui.gitSync.activeGitSettingsModalTab;