diff --git a/app/client/src/pages/AppViewer/viewer/AppViewerHeader.tsx b/app/client/src/pages/AppViewer/viewer/AppViewerHeader.tsx index 39e5752173..5dc886f5d4 100644 --- a/app/client/src/pages/AppViewer/viewer/AppViewerHeader.tsx +++ b/app/client/src/pages/AppViewer/viewer/AppViewerHeader.tsx @@ -4,7 +4,6 @@ import { Helmet } from "react-helmet"; import styled, { ThemeProvider } from "styled-components"; import StyledHeader from "components/designSystems/appsmith/StyledHeader"; import AppsmithLogo from "assets/images/appsmith_logo.png"; -import { createMessage, EDIT_APP, FORK_APP, SIGN_IN } from "constants/messages"; import { isPermitted, PERMISSION_TYPE, @@ -33,7 +32,7 @@ import ProfileDropdown from "pages/common/ProfileDropdown"; import { Profile } from "pages/common/ProfileImage"; import PageTabsContainer from "./PageTabsContainer"; import { getThemeDetails, ThemeMode } from "selectors/themeSelectors"; -import ForkApplicationModal from "pages/Applications/ForkApplicationModal"; +import getAppViewerHeaderCTA from "./getAppViewerHeaderCTA"; const HeaderWrapper = styled(StyledHeader)<{ hasPages: boolean }>` box-shadow: unset; @@ -107,17 +106,6 @@ const AppsmithLogoImg = styled.img` max-width: 110px; `; -const Cta = styled(Button)` - ${(props) => getTypographyByKey(props, "btnLarge")} - height: 100%; -`; - -const ForkButton = styled(Cta)` - svg { - transform: rotate(-90deg); - } - height: ${(props) => `calc(${props.theme.smallHeaderHeight})`}; -`; const HeaderRightItemContainer = styled.div` display: flex; align-items: center; @@ -162,42 +150,14 @@ export const AppViewerHeader = (props: AppViewerHeaderProps) => { const forkUrl = `${AUTH_LOGIN_URL}?redirectUrl=${window.location.href}/fork`; const loginUrl = `${AUTH_LOGIN_URL}?redirectUrl=${window.location.href}`; - let CTA = null; - - if (props.url && canEdit) { - CTA = ( - - ); - } else if ( - currentApplicationDetails?.forkingEnabled && - currentApplicationDetails?.isPublic && - currentUser?.username === ANONYMOUS_USERNAME - ) { - CTA = ( - - ); - } else if ( - currentApplicationDetails?.isPublic && - currentUser?.username === ANONYMOUS_USERNAME - ) { - CTA = ( - - ); - } + const CTA = getAppViewerHeaderCTA({ + url: props.url, + canEdit, + currentApplicationDetails, + currentUser, + forkUrl, + loginUrl, + }); return ( @@ -232,15 +192,6 @@ export const AppViewerHeader = (props: AppViewerHeaderProps) => { title={currentApplicationDetails.name} canOutsideClickClose={true} /> - {currentUser && - currentUser.username !== ANONYMOUS_USERNAME && - currentApplicationDetails?.forkingEnabled && ( -
- -
- )} {CTA && ( {CTA} )} diff --git a/app/client/src/pages/AppViewer/viewer/getAppViewerHeaderCTA.test.tsx b/app/client/src/pages/AppViewer/viewer/getAppViewerHeaderCTA.test.tsx new file mode 100644 index 0000000000..ca2a5c646f --- /dev/null +++ b/app/client/src/pages/AppViewer/viewer/getAppViewerHeaderCTA.test.tsx @@ -0,0 +1,143 @@ +import { unmountComponentAtNode } from "react-dom"; +import { render } from "test/testUtils"; +import getAppViewerHeaderCTA from "./getAppViewerHeaderCTA"; +import { waitFor } from "@testing-library/dom"; +import { ANONYMOUS_USERNAME } from "constants/userConstants"; + +const sampleProps = { + url: + "/applications/606ad816c7a35467ac887f87/pages/606ad816c7a35467ac887f89/edit", + canEdit: true, + currentApplicationDetails: { + id: "606ad816c7a35467ac887f87", + userPermissions: [ + "manage:applications", + "canComment:applications", + "read:applications", + "publish:applications", + "makePublic:applications", + ], + name: "Untitled application 1", + organizationId: "606ad7eec7a35467ac887f84", + isPublic: false, + pages: [ + { + id: "606ad816c7a35467ac887f89", + isDefault: true, + default: true, + }, + ], + appIsExample: false, + color: "#C03C3C", + icon: "flag", + new: false, + }, + currentUser: { + userPermissions: [], + email: "b1@appsmith.com", + source: "FORM", + isEnabled: true, + currentOrganizationId: "606ad7eec7a35467ac887f84", + organizationIds: ["606ad7eec7a35467ac887f84"], + groupIds: [], + permissions: [], + isAnonymous: false, + username: "b1@appsmith.com", + accountNonExpired: true, + accountNonLocked: true, + credentialsNonExpired: true, + claims: {}, + enabled: true, + address: {}, + new: true, + }, + forkUrl: + "/user/login?redirectUrl=https://dev.appsmith.com/applications/606ad816c7a35467ac887f87/pages/606ad816c7a35467ac887f89/fork", + loginUrl: + "/user/login?redirectUrl=https://dev.appsmith.com/applications/606ad816c7a35467ac887f87/pages/606ad816c7a35467ac887f89", +}; + +let container: any = null; +describe("get app viewer header CTA", () => { + beforeEach(async () => { + // setup a DOM element as a render target + container = document.createElement("div"); + document.body.appendChild(container); + }); + it("renders the edit app button and does not render the fork app button", async () => { + const CTA = getAppViewerHeaderCTA(sampleProps); + if (CTA) { + render(CTA); + const result = await waitFor(() => + document.querySelector(".t--back-to-editor"), + ); + expect(!!result).toBeTruthy(); + + const forkButton = await waitFor(() => + document.querySelector(".t--fork-app"), + ); + expect(!!forkButton).toBeFalsy(); + } + }); + it("renders the fork app button", async () => { + const CTA = getAppViewerHeaderCTA({ + ...sampleProps, + canEdit: false, + currentApplicationDetails: { + ...sampleProps.currentApplicationDetails, + forkingEnabled: true, + isPublic: true, + }, + currentUser: { + ...sampleProps.currentUser, + username: ANONYMOUS_USERNAME, + }, + }); + if (CTA) { + render(CTA); + const result = await waitFor(() => + document.querySelector(".t--fork-app"), + ); + expect(!!result).toBeTruthy(); + } + }); + it("renders the fork app link", async () => { + const CTA = getAppViewerHeaderCTA({ + ...sampleProps, + canEdit: false, + currentApplicationDetails: { + ...sampleProps.currentApplicationDetails, + forkingEnabled: true, + isPublic: true, + }, + }); + if (CTA) { + render(CTA); + const result = await waitFor(() => + document.querySelector(".t--fork-btn-wrapper"), + ); + expect(!!result).toBeTruthy(); + } + }); + it("renders the sign in link", async () => { + const CTA = getAppViewerHeaderCTA({ + ...sampleProps, + canEdit: false, + currentApplicationDetails: { + ...sampleProps.currentApplicationDetails, + isPublic: true, + }, + }); + if (CTA) { + render(CTA); + const result = await waitFor(() => document.querySelector(".t--sign-in")); + expect(!!result).toBeTruthy(); + } + }); + afterEach(() => { + // cleanup on exiting + unmountComponentAtNode(container); + container.remove(); + container = null; + }); +}); diff --git a/app/client/src/pages/AppViewer/viewer/getAppViewerHeaderCTA.tsx b/app/client/src/pages/AppViewer/viewer/getAppViewerHeaderCTA.tsx new file mode 100644 index 0000000000..4ff0adbf71 --- /dev/null +++ b/app/client/src/pages/AppViewer/viewer/getAppViewerHeaderCTA.tsx @@ -0,0 +1,76 @@ +import React from "react"; +import styled from "styled-components"; +import { createMessage, EDIT_APP, FORK_APP, SIGN_IN } from "constants/messages"; +import { ANONYMOUS_USERNAME } from "constants/userConstants"; +import { getTypographyByKey } from "constants/DefaultTheme"; +import Button from "components/ads/Button"; +import ForkApplicationModal from "pages/Applications/ForkApplicationModal"; + +const Cta = styled(Button)` + ${(props) => getTypographyByKey(props, "btnLarge")} + height: 100%; +`; + +const ForkButton = styled(Cta)` + svg { + transform: rotate(-90deg); + } + height: ${(props) => `calc(${props.theme.smallHeaderHeight})`}; +`; + +const getAppViewerHeaderCTA = ({ + url, + canEdit, + currentApplicationDetails, + currentUser, + forkUrl, + loginUrl, +}: any) => { + let CTA = null; + + if (url && canEdit) { + CTA = ( + + ); + } else if ( + currentApplicationDetails?.forkingEnabled && + currentApplicationDetails?.isPublic + ) { + if (currentUser?.username === ANONYMOUS_USERNAME) { + CTA = ( + + ); + } else { + CTA = ( +
+ +
+ ); + } + } else if ( + currentApplicationDetails?.isPublic && + currentUser?.username === ANONYMOUS_USERNAME + ) { + CTA = ( + + ); + } + + return CTA; +}; + +export default getAppViewerHeaderCTA; diff --git a/app/client/src/pages/Applications/ForkApplicationModal.tsx b/app/client/src/pages/Applications/ForkApplicationModal.tsx index 38f22dd61e..cebc666c67 100644 --- a/app/client/src/pages/Applications/ForkApplicationModal.tsx +++ b/app/client/src/pages/Applications/ForkApplicationModal.tsx @@ -29,7 +29,6 @@ const TriggerButton = styled(Button)` svg { transform: rotate(-90deg); } - margin-right: ${(props) => props.theme.spaces[7]}px; `; const StyledDialog = styled(Dialog)`