Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add "Start with template" option and refactor template components #30946

Merged
merged 43 commits into from
Feb 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
4266aa3
Add "Start with template" option in workspace action menu
rahulbarwal Feb 4, 2024
260c5dc
Add onForkTemplateClick function to StartWithTemplatesWrapper
rahulbarwal Feb 7, 2024
dfaebd4
Update template import functionality
rahulbarwal Feb 7, 2024
4e933fc
Add forking functionality to TemplatesListLayoutSwitcher component
rahulbarwal Feb 7, 2024
4b94fcb
Add CreateNewAppFromTemplatesModal component
rahulbarwal Feb 7, 2024
dbb1655
Add TemplateDetailedViewHeader component
rahulbarwal Feb 7, 2024
2179e29
Refactor template modal header component
rahulbarwal Feb 7, 2024
95acaa4
Add handleBackPress prop to TemplateView and TemplateViewHeader compo…
rahulbarwal Feb 7, 2024
bc069f1
Refactor CreateNewAppFromTemplateModal component
rahulbarwal Feb 7, 2024
baed68e
Refactor CreateNewAppFromTemplatesModal component
rahulbarwal Feb 7, 2024
d1fb6c2
Merge branch 'release' of https://github.com/appsmithorg/appsmith int…
rahulbarwal Feb 7, 2024
1e80b81
Add componentDidUpdate method to handle isReconnectModalOpen prop change
rahulbarwal Feb 7, 2024
f0239d6
Fix disabled state of fork button
rahulbarwal Feb 7, 2024
096a70a
Commented out code for onForkTemplateClick and added check for presen…
rahulbarwal Feb 7, 2024
8686db1
Add isInsideModal prop to StartWithTemplatesWrapper
rahulbarwal Feb 7, 2024
4629e99
Refactor TemplatesListLayoutSwitcher component
rahulbarwal Feb 7, 2024
fa49391
Refactor StartWithTemplatesWrapper component and add TemplatesListLay…
rahulbarwal Feb 7, 2024
c4a5738
Update start icons in WorkspaceAction component
rahulbarwal Feb 7, 2024
c3dd100
Update app constants
rahulbarwal Feb 7, 2024
2af0e11
Update app constants
rahulbarwal Feb 7, 2024
a33a93d
Add forking feature to TemplatesListLayoutSwitcher
rahulbarwal Feb 7, 2024
25d3d68
Add isModalLayout prop to TemplateView component
rahulbarwal Feb 7, 2024
fc2f6c6
Update NEW_APP constant
rahulbarwal Feb 7, 2024
ced6a0d
Add feature flag for creating app from templates
rahulbarwal Feb 8, 2024
0b1d6d3
Add CreateNewAppFromTemplatesWrapper component
rahulbarwal Feb 8, 2024
02ffd2e
Add handleSimilarTemplateClick functionality to TemplateView component
rahulbarwal Feb 8, 2024
d9c7697
Add useRef hook to reset scroll position in CreateNewAppFromTemplates…
rahulbarwal Feb 8, 2024
019a716
Update LoadingWrapper styles in TemplateView.tsx
rahulbarwal Feb 8, 2024
9a62759
Merge branch 'release' of https://github.com/appsmithorg/appsmith int…
rahulbarwal Feb 8, 2024
4f1dc70
Fix casing of "Create New" button label
rahulbarwal Feb 11, 2024
50f28cc
Add ModalHeader component to CreateNewAppFromTemplateModal
rahulbarwal Feb 11, 2024
365ded6
Add divider in WorkspaceAction menu
rahulbarwal Feb 11, 2024
c7331f8
Refactor CreateNewAppFromTemplatesModal component
rahulbarwal Feb 11, 2024
656cb09
Add isImportingTemplateSelector to TemplateViewHeader
rahulbarwal Feb 11, 2024
387df47
Add AnalyticsUtil for template dropdown click event
rahulbarwal Feb 11, 2024
a9aba27
Merge branch 'release' of https://github.com/appsmithorg/appsmith int…
rahulbarwal Feb 11, 2024
6672166
Add GO_BACK functionality to CreateNewAppFromTemplateModal
rahulbarwal Feb 12, 2024
ad98e18
Update margin-bottom in StartWithTemplatesWrapper component
rahulbarwal Feb 12, 2024
4186153
Merge branch 'release' of https://github.com/appsmithorg/appsmith int…
rahulbarwal Feb 12, 2024
618c09e
Add template analytics and logging
rahulbarwal Feb 12, 2024
492df06
Add new analytics event for template card click
rahulbarwal Feb 12, 2024
5cf4b9a
Fix workspace action menu layout
rahulbarwal Feb 12, 2024
9721d9d
Merge branches 'feat/30859/revert-templates-exp-in-homepage' and 'rel…
rahulbarwal Feb 13, 2024
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
5 changes: 3 additions & 2 deletions app/client/src/ce/constants/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -264,8 +264,9 @@ export const APPLICATION_CARD_LIST_ZERO_STATE = () =>
export const TRY_GUIDED_TOUR = () => `Try guided tour`;
export const JOIN_OUR_DISCORD = () => `Join our discord`;
export const WHATS_NEW = () => `What's new?`;
export const WORKSPACE_ACTION_BUTTON = () => "Create New";
export const NEW_APP = () => "New app";
export const WORKSPACE_ACTION_BUTTON = () => "Create new";
export const NEW_APP = () => "Application";
export const NEW_APP_FROM_TEMPLATE = () => "Templates";
export const NO_WORKSPACE_HEADING = () => "Oops! No workspace found";
export const NO_WORKSPACE_DESCRIPTION = () =>
"You can find workspace list on the left sidebar, try selecting one of them to access a workspace.";
Expand Down
3 changes: 3 additions & 0 deletions app/client/src/ce/entities/FeatureFlag.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ export const FEATURE_FLAG = {
ab_start_with_data_default_enabled: "ab_start_with_data_default_enabled",
release_actions_redesign_enabled: "release_actions_redesign_enabled",
rollout_editor_pane_segments_enabled: "rollout_editor_pane_segments_enabled",
release_show_create_app_from_templates_enabled:
"release_show_create_app_from_templates_enabled",
} as const;

export type FeatureFlag = keyof typeof FEATURE_FLAG;
Expand Down Expand Up @@ -89,6 +91,7 @@ export const DEFAULT_FEATURE_FLAG_VALUE: FeatureFlags = {
ab_start_with_data_default_enabled: false,
release_actions_redesign_enabled: false,
rollout_editor_pane_segments_enabled: false,
release_show_create_app_from_templates_enabled: false,
};

export const AB_TESTING_EVENT_KEYS = {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import React from "react";
import CreateNewAppFromTemplatesModal from ".";
import { useFeatureFlag } from "utils/hooks/useFeatureFlag";

interface Props {
currentWorkspaceId: string;
handleClose: () => void;
isOpen: boolean;
}

const CreateNewAppFromTemplatesWrapper = ({
currentWorkspaceId,
handleClose,
isOpen,
}: Props) => {
const isCreateAppFromTemplatesEnabled = useFeatureFlag(
"release_show_create_app_from_templates_enabled",
);

if (!isCreateAppFromTemplatesEnabled) return null;

return (
<CreateNewAppFromTemplatesModal
currentWorkSpaceId={currentWorkspaceId}
handleClose={handleClose}
isOpen={isOpen}
/>
);
};

export default CreateNewAppFromTemplatesWrapper;
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
import { ReduxActionTypes } from "@appsmith/constants/ReduxActionConstants";
import {
GO_BACK,
START_WITH_TEMPLATE_CONNECT_HEADING,
START_WITH_TEMPLATE_CONNECT_SUBHEADING,
createMessage,
} from "@appsmith/constants/messages";
import type { AppState } from "@appsmith/reducers";
import { fetchDefaultPlugins } from "actions/pluginActions";
import {
getAllTemplates,
getTemplateFilters,
importTemplateToWorkspace,
setActiveLoadingTemplateId,
} from "actions/templateActions";
import type { Template as TemplateInterface } from "api/TemplatesApi";
import {
Link,
Modal,
ModalBody,
ModalContent,
ModalHeader,
} from "design-system";
import { isEmpty } from "lodash";
import { TemplateView } from "pages/Templates/TemplateView";
import TemplatesListLayoutSwitcher from "pages/Templates/TemplatesModal/TemplatesListLayoutSwitcher";
import React, { useEffect, useRef, useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import {
activeLoadingTemplateId,
allTemplatesFiltersSelector,
getTemplatesSelector,
templatesCountSelector,
} from "selectors/templatesSelectors";
import styled from "styled-components";
import AnalyticsUtil from "utils/AnalyticsUtil";
import { StartWithTemplatesHeader } from "../StartWithTemplatesWrapper";

interface CreateNewAppFromTemplatesModalProps {
currentWorkSpaceId: string;
isOpen: boolean;
handleClose: (open: boolean) => void;
}

function CreateNewAppFromTemplatesModal({
currentWorkSpaceId,
handleClose,
isOpen,
}: CreateNewAppFromTemplatesModalProps) {
const dispatch = useDispatch();
const templatesCount = useSelector(templatesCountSelector);
const pluginListLength = useSelector(
(state: AppState) => state.entities.plugins.defaultPluginList.length,
);
const filters = useSelector(allTemplatesFiltersSelector);
const [showTemplateDetails, setShowTemplateDetails] = useState("");
const allTemplates = useSelector(getTemplatesSelector);
const loadingTemplateId = useSelector(activeLoadingTemplateId);
const modadBodyRef = useRef<HTMLDivElement>(null);

useEffect(() => {
setShowTemplateDetails("");
dispatch(setActiveLoadingTemplateId(""));
dispatch({
type: ReduxActionTypes.RESET_TEMPLATE_FILTERS,
});
}, [isOpen]);

useEffect(() => {
if (!templatesCount) {
dispatch(getAllTemplates());
}
}, [templatesCount]);

useEffect(() => {
if (!pluginListLength) {
dispatch(fetchDefaultPlugins());
}
}, [pluginListLength]);

useEffect(() => {
if (isEmpty(filters.functions)) {
dispatch(getTemplateFilters());
}
}, [filters]);

useEffect(() => {
if (!showTemplateDetails && modadBodyRef.current) {
modadBodyRef.current.scrollTop = 0;
}
}, [showTemplateDetails]);

const onClose = (open: boolean) => {
if (open === false) {
handleClose(open);
setShowTemplateDetails("");
}
};

const getTemplateById = (id: string) => {
const template = allTemplates.find((template) => template.id === id);
return template;
};

const handleSimilarTemplateClick = (template: TemplateInterface) => {
if (typeof template === "string") {
template = getTemplateById(template) as TemplateInterface;
}
if (!template) return;

AnalyticsUtil.logEvent("TEMPLATE_SELECT_NEW_APP_FLOW", {
templateId: template.id,
templateName: template.title,
});
onTemplateClick(template);
};

const onTemplateClick = (template: TemplateInterface | string) => {
const templateId = typeof template === "string" ? template : template.id;
!loadingTemplateId && setShowTemplateDetails(templateId);
};

const onClickUseTemplate = (templateId: string) => {
const template = getTemplateById(templateId);
if (template) {
AnalyticsUtil.logEvent("FORK_TEMPLATE_NEW_APP_FLOW", {
templateId: template.id,
templateName: template.title,
});
dispatch(setActiveLoadingTemplateId(templateId));
dispatch(importTemplateToWorkspace(templateId, currentWorkSpaceId));
}
};

return (
<Modal onOpenChange={(open) => onClose(open)} open={isOpen}>
<ModalContentWrapper data-testid="t--create-app-from-templates-dialog-component">
<ModalHeader>
{!showTemplateDetails ? (
<StartWithTemplatesHeader
isModalLayout
subtitle={createMessage(START_WITH_TEMPLATE_CONNECT_SUBHEADING)}
title={createMessage(START_WITH_TEMPLATE_CONNECT_HEADING)}
/>
) : (
<Link
data-testid="t--template-view-goback"
onClick={() => setShowTemplateDetails("")}
startIcon="arrow-left-line"
>
{createMessage(GO_BACK)}
</Link>
)}
</ModalHeader>
<ModalBodyWrapper
isDetailedView={!!showTemplateDetails}
ref={modadBodyRef}
>
{!!showTemplateDetails ? (
<TemplateView
handleBackPress={() => setShowTemplateDetails("")}
handleSimilarTemplateClick={handleSimilarTemplateClick}
isModalLayout
onClickUseTemplate={onClickUseTemplate}
showBack={false}
showSimilarTemplate
similarTemplatesClassName="!p-0"
templateId={showTemplateDetails}
/>
) : (
<TemplatesListLayoutSwitcher
analyticsEventNameForTemplateCardClick="TEMPLATE_SELECT_NEW_APP_FLOW"
isForkingEnabled
onForkTemplateClick={onClickUseTemplate}
onTemplateClick={onTemplateClick}
/>
)}
</ModalBodyWrapper>
</ModalContentWrapper>
</Modal>
);
}

export default CreateNewAppFromTemplatesModal;

const ModalContentWrapper = styled(ModalContent)`
width: 100%;
overflow-y: hidden;
background-color: var(--ads-v2-color-gray-50);
`;
const ModalBodyWrapper = styled(ModalBody)<{ isDetailedView?: boolean }>`
width: 100%;
overflow-y: ${(props) => (props.isDetailedView ? "scroll" : "hidden")};
padding-top: 0;
`;
24 changes: 21 additions & 3 deletions app/client/src/ce/pages/Applications/CreateNewAppsOption.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import {
getAllTemplates,
getTemplateFilters,
importTemplateIntoApplicationViaOnboardingFlow,
setActiveLoadingTemplateId,
} from "actions/templateActions";
import { ASSETS_CDN_URL } from "constants/ThirdPartyConstants";
import { Flex, Link, Text } from "design-system";
Expand Down Expand Up @@ -57,6 +58,7 @@ import { fetchingEnvironmentConfigs } from "@appsmith/actions/environmentAction"
import StartWithTemplatesWrapper from "./StartWithTemplatesWrapper";
import { useFeatureFlag } from "utils/hooks/useFeatureFlag";
import { FEATURE_FLAG } from "@appsmith/entities/FeatureFlag";
import type { Template } from "api/TemplatesApi";

const SectionWrapper = styled.div`
display: flex;
Expand Down Expand Up @@ -475,6 +477,24 @@ const CreateNewAppsOption = ({
isEnabledForStartWithDataDefault &&
(!createNewAppPluginId || !selectedDatasource);

const onForkTemplateClick = (template: Template) => {
const title = template.title;
AnalyticsUtil.logEvent("FORK_TEMPLATE_WHEN_ONBOARDING", { title });
// When fork template is clicked to add a new app using the template
if (!isImportingTemplate && application) {
dispatch(setActiveLoadingTemplateId(template.id));
dispatch(
importTemplateIntoApplicationViaOnboardingFlow(
template.id,
template.title,
template.pages.map((p) => p.name),
application.id,
application.workspaceId,
),
);
}
};

return (
<SectionWrapper>
<BackWrapper hidden={!useType}>
Expand Down Expand Up @@ -509,9 +529,7 @@ const CreateNewAppsOption = ({
/>
) : (
<StartWithTemplatesWrapper
currentApplicationIdForCreateNewApp={
currentApplicationIdForCreateNewApp
}
onForkTemplateClick={onForkTemplateClick}
setSelectedTemplate={setSelectedTemplate}
/>
)
Expand Down
Loading
Loading