Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,12 @@ describe(
});

it("1.Bug #17002 Forking a template into an existing app which is connected to git makes the application go into a bad state ", function () {
PageList.AddNewPage("Add page from template");
_.agHelper.AssertElementExist(template.templateDialogBox);
_.agHelper.GetNClick(template.templateCard);
_.agHelper.GetNClick(template.templateViewForkButton);
cy.get(template.startFromTemplateCard).click();
_.assertHelper.AssertNetworkStatus("fetchTemplate");

cy.get(template.templateDialogBox).should("be.visible");
cy.get(template.templateCard).first().click();
cy.get(template.templateViewForkButton).first().click();
cy.waitUntil(() => cy.xpath("//span[text()='Setting up the template']"), {
errorMsg: "Setting Templates did not finish even after 75 seconds",
timeout: 75000,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ describe(

it("2. Add selected pages from template to an app", () => {
homePage.CreateNewApplication();
PageList.AddNewPage("Add page from template");
agHelper.GetNClick(template.startFromTemplateCard);
agHelper.AssertElementVisibility(template.templateDialogBox);
agHelper.GetNClick("//h1[text()='Applicant Tracker-test']");
agHelper.FailIfErrorToast(
Expand Down
6 changes: 6 additions & 0 deletions app/client/src/ce/constants/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1771,6 +1771,9 @@ export const WIDGET_USED = () => "Widgets";
export const SIMILAR_TEMPLATES = () => "Similar templates";
export const VIEW_ALL_TEMPLATES = () => "View all templates";
export const FILTERS = () => "Filters";
export const TEMPLATE_CARD_TITLE = () => "Start from a template";
export const TEMPLATE_CARD_DESCRIPTION = () =>
"Create app from template by selecting pages";
Comment on lines +1774 to +1776
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider using consistent naming for constants related to similar functionalities.

- export const TEMPLATE_CARD_TITLE = () => "Start from a template";
- export const TEMPLATE_CARD_DESCRIPTION = () =>
-   "Create app from template by selecting pages";
- export const GENERATE_PAGE = () => "Generate page from data table";
- export const GENERATE_PAGE_DESCRIPTION = () =>
-   "Start app with a simple CRUD UI and customize it";
+ export const TEMPLATE_CARD_TITLE = () => "Start From a Template";
+ export const TEMPLATE_CARD_DESCRIPTION = () => "Create App From Template by Selecting Pages";
+ export const GENERATE_PAGE = () => "Generate Page From Data Table";
+ export const GENERATE_PAGE_DESCRIPTION = () => "Start App With a Simple CRUD UI and Customize It";

This change ensures that the function names and return strings are more readable and maintain a consistent format across similar functionalities.

Also applies to: 1829-1831

Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
export const TEMPLATE_CARD_TITLE = () => "Start from a template";
export const TEMPLATE_CARD_DESCRIPTION = () =>
"Create app from template by selecting pages";
export const TEMPLATE_CARD_TITLE = () => "Start From a Template";
export const TEMPLATE_CARD_DESCRIPTION = () => "Create App From Template by Selecting Pages";
export const GENERATE_PAGE = () => "Generate Page From Data Table";
export const GENERATE_PAGE_DESCRIPTION = () => "Start App With a Simple CRUD UI and Customize It";

export const FILTER_SELECTALL = () => "Select all";
export const FILTER_SELECT_PAGE = () => "Add selected page";
export const FILTER_SELECT_PAGES = () => "Add selected pages";
Expand Down Expand Up @@ -1823,6 +1826,9 @@ export const SEARCH_USERS = (

export const CREATE_PAGE = () => "New blank page";
export const CANVAS_NEW_PAGE_CARD = () => "Create new page";
export const GENERATE_PAGE = () => "Generate page from data table";
export const GENERATE_PAGE_DESCRIPTION = () =>
"Start app with a simple CRUD UI and customize it";
export const ADD_PAGE_FROM_TEMPLATE = () => "Add page from template";
export const INVALID_URL = () =>
"Please enter a valid URL, for example, https://example.com";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
import useMissingModuleNotification from "@appsmith/pages/Editor/IDE/MainPane/useMissingModuleNotification";
import AnonymousDataPopup from "pages/Editor/FirstTimeUserOnboarding/AnonymousDataPopup";
import React from "react";
import AnonymousDataPopup from "pages/Editor/FirstTimeUserOnboarding/AnonymousDataPopup";
import EmptyCanvasPrompts from "./components/EmptyCanvasPrompts";
import { useSelector } from "react-redux";
import { combinedPreviewModeSelector } from "selectors/editorSelectors";
import { getIsAppSettingsPaneWithNavigationTabOpen } from "selectors/appSettingsPaneSelectors";
import { useCurrentAppState } from "pages/Editor/IDE/hooks";
import { EditorState } from "@appsmith/entities/IDE/constants";
import useMissingModuleNotification from "@appsmith/pages/Editor/IDE/MainPane/useMissingModuleNotification";

/**
* WidgetEditorHeader
Expand All @@ -11,9 +17,19 @@ import React from "react";
* - missing module notification
*/
export const WidgetEditorHeader = () => {
const isNavigationSelectedInSettings = useSelector(
getIsAppSettingsPaneWithNavigationTabOpen,
);
const appState = useCurrentAppState();
const isAppSettingsPaneWithNavigationTabOpen =
appState === EditorState.SETTINGS && isNavigationSelectedInSettings;
const isPreviewMode = useSelector(combinedPreviewModeSelector);
const missingModuleNotification = useMissingModuleNotification();
return (
<>
{!isAppSettingsPaneWithNavigationTabOpen && (
<EmptyCanvasPrompts isPreview={isPreviewMode} />
)}
{missingModuleNotification}
<AnonymousDataPopup />
</>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
import React, { useEffect } from "react";
import styled from "styled-components";
import { Text, TextType } from "design-system-old";
import { useDispatch, useSelector } from "react-redux";
import {
selectURLSlugs,
showCanvasTopSectionSelector,
} from "selectors/editorSelectors";
import AnalyticsUtil from "@appsmith/utils/AnalyticsUtil";
import history from "utils/history";
import { generateTemplateFormURL } from "@appsmith/RouteBuilder";
import { useParams } from "react-router";
import type { ExplorerURLParams } from "@appsmith/pages/Editor/Explorer/helpers";
import { showTemplatesModal as showTemplatesModalAction } from "actions/templateActions";
import {
createMessage,
GENERATE_PAGE,
GENERATE_PAGE_DESCRIPTION,
TEMPLATE_CARD_DESCRIPTION,
TEMPLATE_CARD_TITLE,
} from "@appsmith/constants/messages";
import { deleteCanvasCardsState } from "actions/editorActions";
import { isAirgapped } from "@appsmith/utils/airgapHelpers";
import { Icon } from "design-system";
import {
LayoutSystemFeatures,
useLayoutSystemFeatures,
} from "layoutSystems/common/useLayoutSystemFeatures";

const Wrapper = styled.div`
margin: ${(props) =>
`${props.theme.spaces[7]}px ${props.theme.spaces[16]}px 0px ${props.theme.spaces[13]}px`};
display: flex;
flex-direction: row;
gap: ${(props) => props.theme.spaces[7]}px;
`;

const Card = styled.div<{ centerAlign?: boolean }>`
padding: ${(props) =>
`${props.theme.spaces[5]}px ${props.theme.spaces[9]}px`};
border: solid 1px var(--ads-v2-color-border);
background: var(--ads-v2-color-bg);
flex: 1;
display: flex;
flex-direction: row;
align-items: center;
border-radius: var(--ads-v2-border-radius);
${(props) =>
props.centerAlign &&
`
justify-content: center;
`}
cursor: pointer;

svg {
height: 24px;
width: 24px;
}
&:hover {
background-color: var(--ads-v2-color-bg-subtle);
}
`;

const Content = styled.div`
display: flex;
flex-direction: column;
padding-left: ${(props) => props.theme.spaces[7]}px;
`;

interface routeId {
applicationSlug: string;
pageId: string;
pageSlug: string;
}

const goToGenPageForm = ({ pageId }: routeId): void => {
AnalyticsUtil.logEvent("GEN_CRUD_PAGE_ACTION_CARD_CLICK");
history.push(generateTemplateFormURL({ pageId }));
};

interface EmptyCanvasPromptsProps {
isPreview: boolean;
}

/**
* OldName: CanvasTopSection
*/
/**
* This Component encompasses the prompts for empty canvas
* prompts like generate crud app or import from template
* @param props Object that contains
* @prop isPreview, boolean to indicate preview mode
* @returns
*/
function EmptyCanvasPrompts(props: EmptyCanvasPromptsProps) {
const dispatch = useDispatch();
const showCanvasTopSection = useSelector(showCanvasTopSectionSelector);
const { isPreview } = props;
const { pageId } = useParams<ExplorerURLParams>();
const { applicationSlug, pageSlug } = useSelector(selectURLSlugs);

const checkLayoutSystemFeatures = useLayoutSystemFeatures();
const [enableForkingFromTemplates, enableGenerateCrud] =
checkLayoutSystemFeatures([
LayoutSystemFeatures.ENABLE_FORKING_FROM_TEMPLATES,
LayoutSystemFeatures.ENABLE_GENERATE_CRUD_APP,
]);

useEffect(() => {
if (!showCanvasTopSection && !isPreview) {
dispatch(deleteCanvasCardsState());
}
}, [showCanvasTopSection, isPreview]);

if (!showCanvasTopSection || isPreview) return null;

const showTemplatesModal = () => {
dispatch(showTemplatesModalAction({ isOpenFromCanvas: false }));
AnalyticsUtil.logEvent("CANVAS_BLANK_PAGE_CTA_CLICK", {
item: "ADD_PAGE_FROM_TEMPLATE",
});
};

const onGeneratePageClick = () => {
goToGenPageForm({ applicationSlug, pageSlug, pageId });
AnalyticsUtil.logEvent("CANVAS_BLANK_PAGE_CTA_CLICK", {
item: "GENERATE_PAGE",
});
};

const isAirgappedInstance = isAirgapped();
const showCanvasPrompts =
(enableForkingFromTemplates && !isAirgappedInstance) || enableGenerateCrud;
return showCanvasPrompts ? (
<Wrapper data-testid="canvas-ctas">
{enableForkingFromTemplates && !isAirgappedInstance && (
<Card data-testid="start-from-template" onClick={showTemplatesModal}>
<Icon name="layout-2-line" size="lg" />
<Content>
<Text color={"var(--ads-v2-color-fg-emphasis)"} type={TextType.H5}>
{createMessage(TEMPLATE_CARD_TITLE)}
</Text>
<Text type={TextType.P3}>
{createMessage(TEMPLATE_CARD_DESCRIPTION)}
</Text>
</Content>
</Card>
)}
{enableGenerateCrud && (
<Card
centerAlign={false}
data-testid="generate-app"
onClick={onGeneratePageClick}
>
<Icon name="database-2-line" size="lg" />
<Content>
<Text color={"var(--ads-v2-color-fg-emphasis)"} type={TextType.H5}>
{createMessage(GENERATE_PAGE)}
</Text>
<Text type={TextType.P3}>
{createMessage(GENERATE_PAGE_DESCRIPTION)}
</Text>
</Content>
</Card>
)}
</Wrapper>
) : null;
}

export default EmptyCanvasPrompts;