diff --git a/app/client/src/actions/templateActions.ts b/app/client/src/actions/templateActions.ts index 315a3ef6b2..6f7161044d 100644 --- a/app/client/src/actions/templateActions.ts +++ b/app/client/src/actions/templateActions.ts @@ -41,3 +41,8 @@ export const setTemplateNotificationSeenAction = (payload: boolean) => ({ export const getTemplateNotificationSeenAction = () => ({ type: ReduxActionTypes.GET_TEMPLATE_NOTIFICATION_SEEN, }); + +export const getTemplateInformation = (payload: string) => ({ + type: ReduxActionTypes.GET_TEMPLATE_INIT, + payload, +}); diff --git a/app/client/src/api/TemplatesApi.ts b/app/client/src/api/TemplatesApi.ts index 4736821bd1..683350b593 100644 --- a/app/client/src/api/TemplatesApi.ts +++ b/app/client/src/api/TemplatesApi.ts @@ -18,6 +18,8 @@ export interface Template { datasources: string[]; } +export type FilterKeys = "widgets" | "datasources"; + export interface FetchTemplatesResponse extends ApiResponse { data: Template[]; } diff --git a/app/client/src/assets/icons/ads/fork-2.svg b/app/client/src/assets/icons/ads/fork-2.svg index 514e827bd9..54c7d36432 100644 --- a/app/client/src/assets/icons/ads/fork-2.svg +++ b/app/client/src/assets/icons/ads/fork-2.svg @@ -1,7 +1,7 @@ - - - - - - + + + + + + diff --git a/app/client/src/assets/images/request-template.svg b/app/client/src/assets/images/request-template.svg index f7b5303bbf..ebcb5a549d 100644 --- a/app/client/src/assets/images/request-template.svg +++ b/app/client/src/assets/images/request-template.svg @@ -1,67 +1,11 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + - - - - - - - - - - + - - - - - - - - - - - - - - - - + diff --git a/app/client/src/ce/constants/messages.ts b/app/client/src/ce/constants/messages.ts index 5183bfd986..83e6e0a5d1 100644 --- a/app/client/src/ce/constants/messages.ts +++ b/app/client/src/ce/constants/messages.ts @@ -1113,7 +1113,7 @@ export const REQUEST_TEMPLATE = () => "Request for a template"; export const SEARCH_TEMPLATES = () => "Search templates"; export const INTRODUCING_TEMPLATES = () => "Introducing Templates"; export const TEMPLATE_NOTIFICATION_DESCRIPTION = () => - "You can browse, fork, and make them your own here"; + "Use these templates to learn, create, and build apps even faster"; export const GO_BACK = () => "GO BACK"; export const OVERVIEW = () => "Overview"; export const FUNCTION = () => "Function"; @@ -1123,6 +1123,8 @@ export const NOTE = () => "Note:"; export const NOTE_MESSAGE = () => "You can add your datasources as well"; export const WIDGET_USED = () => "Widgets Used"; export const SIMILAR_TEMPLATES = () => "Similar Templates"; +export const VIEW_ALL_TEMPLATES = () => "VIEW ALL TEMPLATES"; +export const FILTERS = () => "FILTERS"; export const IMAGE_LOAD_ERROR = () => "Unable to display the image"; diff --git a/app/client/src/constants/ReduxActionConstants.tsx b/app/client/src/constants/ReduxActionConstants.tsx index 6248a7a1af..d99c022acb 100644 --- a/app/client/src/constants/ReduxActionConstants.tsx +++ b/app/client/src/constants/ReduxActionConstants.tsx @@ -690,6 +690,8 @@ export const ReduxActionTypes = { FETCH_PLUGIN_AND_JS_ACTIONS_SUCCESS: "FETCH_PLUGIN_AND_JS_ACTIONS_SUCCESS", GET_DEFAULT_PLUGINS_REQUEST: "GET_DEFAULT_PLUGINS_REQUEST", GET_DEFAULT_PLUGINS_SUCCESS: "GET_DEFAULT_PLUGINS_SUCCESS", + GET_TEMPLATE_INIT: "GET_TEMPLATES_INIT", + GET_TEMPLATE_SUCCESS: "GET_TEMPLATES_SUCCESS", }; export type ReduxActionType = typeof ReduxActionTypes[keyof typeof ReduxActionTypes]; @@ -857,6 +859,7 @@ export const ReduxActionErrorTypes = { IMPORT_TEMPLATE_TO_ORGANISATION_ERROR: "IMPORT_TEMPLATE_TO_ORGANISATION_ERROR", GET_DEFAULT_PLUGINS_ERROR: "GET_DEFAULT_PLUGINS_ERROR", + GET_TEMPLATE_ERROR: "GET_TEMPLATE_ERROR", }; export const ReduxFormActionTypes = { diff --git a/app/client/src/globalStyles/popover.ts b/app/client/src/globalStyles/popover.ts index 33629c19ac..ac4b525027 100644 --- a/app/client/src/globalStyles/popover.ts +++ b/app/client/src/globalStyles/popover.ts @@ -23,6 +23,10 @@ export const PopoverStyles = createGlobalStyle` .onboarding-carousel .${Classes.OVERLAY_CONTENT} { filter: drop-shadow(0px 6px 20px rgba(0, 0, 0, 0.15)); } + .templates-notification .bp3-popover2-arrow { + // !important because top is specified as an inline style in the lib + top: -8px !important; + } .templates-notification .bp3-popover2-arrow-fill { fill: ${Colors.SEA_SHELL}; } diff --git a/app/client/src/pages/AppViewer/viewer/GetAppViewerHeaderCTA.tsx b/app/client/src/pages/AppViewer/viewer/GetAppViewerHeaderCTA.tsx index 1520420eae..77ab6f2060 100644 --- a/app/client/src/pages/AppViewer/viewer/GetAppViewerHeaderCTA.tsx +++ b/app/client/src/pages/AppViewer/viewer/GetAppViewerHeaderCTA.tsx @@ -19,12 +19,6 @@ import history from "utils/history"; const Cta = styled(Button)` ${(props) => getTypographyByKey(props, "btnLarge")} height: 21px; - span > svg { - height: 10px; - path { - stroke: white; - } - } `; const ForkButton = styled(Cta)` @@ -67,7 +61,7 @@ function GetAppViewerHeaderCTA(props: any) { ); @@ -79,7 +73,7 @@ function GetAppViewerHeaderCTA(props: any) { trigger={ dispatch(getAllApplications())} size={Size.small} text={createMessage(FORK_APP)} diff --git a/app/client/src/pages/Applications/ApplicationCard.tsx b/app/client/src/pages/Applications/ApplicationCard.tsx index b9a33ce483..5c31f10270 100644 --- a/app/client/src/pages/Applications/ApplicationCard.tsx +++ b/app/client/src/pages/Applications/ApplicationCard.tsx @@ -477,7 +477,7 @@ export function ApplicationCard(props: ApplicationCardProps) { moreActionItems.push({ onSelect: forkApplicationInitiate, text: "Fork", - icon: "compasses-line", + icon: "fork-2", cypressSelector: "t--fork-app", }); } diff --git a/app/client/src/pages/Applications/ForkApplicationModal.tsx b/app/client/src/pages/Applications/ForkApplicationModal.tsx index 90226e61de..a3caa18f24 100644 --- a/app/client/src/pages/Applications/ForkApplicationModal.tsx +++ b/app/client/src/pages/Applications/ForkApplicationModal.tsx @@ -93,7 +93,7 @@ function ForkApplicationModal(props: ForkApplicationModalProps) { diff --git a/app/client/src/pages/Templates/Filters.tsx b/app/client/src/pages/Templates/Filters.tsx index 3eab128069..8cf899b326 100644 --- a/app/client/src/pages/Templates/Filters.tsx +++ b/app/client/src/pages/Templates/Filters.tsx @@ -1,4 +1,4 @@ -import React, { useState } from "react"; +import React from "react"; import styled from "styled-components"; import { useDispatch, useSelector } from "react-redux"; import { Collapse } from "@blueprintjs/core"; @@ -6,7 +6,7 @@ import { Classes } from "components/ads/common"; import Text, { TextType } from "components/ads/Text"; import Icon, { IconSize } from "components/ads/Icon"; import { filterTemplates } from "actions/templateActions"; -import { createMessage, MORE, SHOW_LESS } from "@appsmith/constants/messages"; +import { createMessage, FILTERS } from "@appsmith/constants/messages"; import { getFilterListSelector, getTemplateFilterSelector, @@ -14,6 +14,7 @@ import { import LeftPaneBottomSection from "pages/Home/LeftPaneBottomSection"; import { thinScrollbar } from "constants/DefaultTheme"; import { Colors } from "constants/Colors"; +import AnalyticsUtil from "utils/AnalyticsUtil"; const FilterWrapper = styled.div` overflow: auto; @@ -38,7 +39,6 @@ const Wrapper = styled.div` padding-left: ${(props) => props.theme.spaces[7]}px; padding-top: ${(props) => props.theme.spaces[11]}px; flex-direction: column; - box-shadow: 1px 0px 0px ${Colors.GALLERY_2}; `; const SecondWrapper = styled.div` @@ -80,6 +80,12 @@ const StyledFilterItem = styled.div<{ selected: boolean }>` const StyledFilterCategory = styled(Text)` margin-bottom: ${(props) => props.theme.spaces[4]}px; padding-left: ${(props) => props.theme.spaces[6]}px; + font-weight: bold; + + &.title { + margin-bottom: ${(props) => props.theme.spaces[12] - 2}px; + display: inline-block; + } `; const ListWrapper = styled.div` @@ -110,7 +116,13 @@ interface FilterCategoryProps { function FilterItem({ item, onSelect, selected }: FilterItemProps) { const onClick = () => { const action = selected ? "remove" : "add"; - onSelect(item?.value ?? item.label, action); + const filterValue = item?.value ?? item.label; + onSelect(filterValue, action); + if (action === "add") { + AnalyticsUtil.logEvent("TEMPLATE_FILTER_SELECTED", { + filter: filterValue, + }); + } }; return ( @@ -128,11 +140,11 @@ function FilterCategory({ label, selectedFilters, }: FilterCategoryProps) { - const [expand, setExpand] = useState(false); + // const [expand, setExpand] = useState(!!selectedFilters.length); const dispatch = useDispatch(); // This indicates how many filter items do we want to show, the rest are hidden // behind show more. - const FILTERS_TO_SHOW = 3; + const FILTERS_TO_SHOW = 4; const onSelect = (item: string, type: string) => { if (type === "add") { dispatch(filterTemplates(label, [...selectedFilters, item])); @@ -146,9 +158,9 @@ function FilterCategory({ } }; - const toggleExpand = () => { - setExpand((expand) => !expand); - }; + // const toggleExpand = () => { + // setExpand((expand) => !expand); + // }; const isSelected = (filter: Filter) => { return selectedFilters.includes(filter?.value ?? filter.label); @@ -156,7 +168,7 @@ function FilterCategory({ return ( - + {label.toLocaleUpperCase()}{" "} {!!selectedFilters.length && `(${selectedFilters.length})`} @@ -171,7 +183,7 @@ function FilterCategory({ /> ); })} - + {filterList.slice(FILTERS_TO_SHOW).map((filter) => { return ( - {!!filterList.slice(FILTERS_TO_SHOW).length && ( + {/* We will be adding this back later */} + {/* {!!filterList.slice(FILTERS_TO_SHOW).length && ( {expand ? `- ${createMessage(SHOW_LESS)}` - : `+ ${filterList.slice(3).length} ${createMessage(MORE)}`} + : `+ ${filterList.slice(FILTERS_TO_SHOW).length} ${createMessage( + MORE, + )}`} - )} + )} */} ); @@ -208,6 +223,9 @@ function Filters() { + + {createMessage(FILTERS)} + {Object.keys(filters).map((filter) => { return ( diff --git a/app/client/src/pages/Templates/Template/LargeTemplate.tsx b/app/client/src/pages/Templates/Template/LargeTemplate.tsx index 4123a6215d..6527c9335f 100644 --- a/app/client/src/pages/Templates/Template/LargeTemplate.tsx +++ b/app/client/src/pages/Templates/Template/LargeTemplate.tsx @@ -8,7 +8,6 @@ const LargeTemplate = styled(TemplateLayout)` display: flex; flex: 1; flex-direction: column; - max-width: 50%; cursor: pointer; &:hover { box-shadow: 0px 20px 24px -4px rgba(16, 24, 40, 0.1), @@ -30,22 +29,10 @@ const LargeTemplate = styled(TemplateLayout)` } .image-wrapper { - padding: ${(props) => - `${props.theme.spaces[9]}px ${props.theme.spaces[11]}px ${props.theme.spaces[0]}px`}; transition: all 1s ease-out; width: 100%; height: 270px; } - - .fork-button { - height: 38px; - width: 38px; - - svg { - height: 18px; - width: 18px; - } - } `; export default LargeTemplate; diff --git a/app/client/src/pages/Templates/Template/RequestTemplate.tsx b/app/client/src/pages/Templates/Template/RequestTemplate.tsx index fb8b8cacc9..8b7c4f7236 100644 --- a/app/client/src/pages/Templates/Template/RequestTemplate.tsx +++ b/app/client/src/pages/Templates/Template/RequestTemplate.tsx @@ -16,7 +16,7 @@ const Wrapper = styled.div` display: flex; flex-direction: column; padding: ${(props) => props.theme.spaces[11]}px; - background-color: rgba(248, 248, 248, 0.5); + background-color: ${Colors.SEA_SHELL}; transition: all 1s ease-out; margin-bottom: ${(props) => props.theme.spaces[12]}px; @@ -43,24 +43,25 @@ const Wrapper = styled.div` `; const StyledImage = styled.img` - height: 147px; + height: 168px; object-fit: cover; `; +const REQUEST_TEMPLATE_URL = + "https://app.appsmith.com/applications/6241b5a8c99df2369931a653/pages/6241b5a8c99df2369931a656"; + function RequestTemplate() { const onClick = () => { - window.open( - "https://github.com/appsmithorg/appsmith/issues/new?assignees=Kocharrahul8&labels=Example+Apps&template=Templates.yaml&title=%5BTemplate%5D%3A+", - ); + window.open(REQUEST_TEMPLATE_URL); }; return ( - + {createMessage(COULDNT_FIND_TEMPLATE)} - + {createMessage(COULDNT_FIND_TEMPLATE_DESCRIPTION)}
- + ); } function TemplateNotFound() { - return ( - - ; - - ); + return ; } function TemplateView() { @@ -216,9 +236,9 @@ function TemplateView() { const similarTemplates = useSelector( (state: AppState) => state.ui.templates.similarTemplates, ); - const isFetchingTemplates = useSelector(isFetchingTemplatesSelector); + const isFetchingTemplate = useSelector(isFetchingTemplateSelector); const params = useParams<{ templateId: string }>(); - const currentTemplate = useSelector(getTemplateById(params.templateId)); + const currentTemplate = useSelector(getActiveTemplateSelector); const [showForkModal, setShowForkModal] = useState(false); const containerRef = useRef(null); @@ -235,30 +255,38 @@ function TemplateView() { }; useEffect(() => { + dispatch(getTemplateInformation(params.templateId)); + dispatch(getSimilarTemplatesInit(params.templateId)); if (containerRef.current) { - containerRef.current.scrollTo({ top: 0, behavior: "smooth" }); - dispatch(getSimilarTemplatesInit(params.templateId)); + containerRef.current.scrollTo({ top: 0 }); } }, [params.templateId]); + const goBack = () => { + history.goBack(); + }; + return ( - - {isFetchingTemplates ? ( + {isFetchingTemplate ? ( ) : !currentTemplate ? ( ) : ( - - - {createMessage(GO_BACK)} - - - - {currentTemplate.title} - + +
+ + + {createMessage(GO_BACK)} + +
+ + {currentTemplate.title} + +
+
@@ -286,7 +314,7 @@ function TemplateView() { >