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)`