PromucFlow_constructor/app/client/src/pages/Templates/index.tsx
2022-03-31 10:46:04 +05:30

193 lines
5.8 KiB
TypeScript

import React, { useEffect } from "react";
import styled from "styled-components";
import * as Sentry from "@sentry/react";
import { Classes, ControlGroup } from "@blueprintjs/core";
import { debounce, noop } from "lodash";
import { Switch, Route, useRouteMatch } from "react-router-dom";
import SearchInput, { SearchVariant } from "components/ads/SearchInput";
import TemplateList from "./TemplateList";
import TemplateView from "./TemplateView";
import Filters from "pages/Templates/Filters";
import { useDispatch, useSelector } from "react-redux";
import { setHeaderMeta } from "actions/themeActions";
import {
getAllTemplates,
setTemplateSearchQuery,
} from "actions/templateActions";
import {
getSearchedTemplateList,
getTemplateFiltersLength,
getTemplateSearchQuery,
isFetchingTemplatesSelector,
} from "selectors/templatesSelectors";
import { fetchDefaultPlugins } from "actions/pluginActions";
import { editorInitializer } from "utils/EditorUtils";
import { AppState } from "reducers";
import {
getIsFetchingApplications,
getUserApplicationsOrgsList,
} from "selectors/applicationSelectors";
import { getAllApplications } from "actions/applicationActions";
import { getTypographyByKey } from "constants/DefaultTheme";
import { Colors } from "constants/Colors";
import { createMessage, SEARCH_TEMPLATES } from "@appsmith/constants/messages";
const SentryRoute = Sentry.withSentryRouting(Route);
const PageWrapper = styled.div`
margin-top: ${(props) => props.theme.homePage.header}px;
display: flex;
height: calc(100vh - ${(props) => props.theme.homePage.header}px);
padding-left: 8vw;
`;
export const TemplateListWrapper = styled.div`
padding-top: ${(props) => props.theme.spaces[11]}px;
width: calc(100% - ${(props) => props.theme.homePage.sidebar}px);
height: calc(100vh - ${(props) => props.theme.headerHeight});
overflow: auto;
padding-right: 8vw;
`;
export const ResultsCount = styled.div`
${(props) => getTypographyByKey(props, "h1")}
color: ${Colors.CODE_GRAY};
margin-top: ${(props) => props.theme.spaces[5]}px;
margin-left: ${(props) => props.theme.spaces[12]}px;
padding-bottom: ${(props) => props.theme.spaces[11]}px;
`;
const Loader = styled(TemplateListWrapper)`
height: 100vh;
.results-count {
height: 20px;
width: 100px;
}
`;
const LoadingTemplateList = styled.div`
margin-top: ${(props) => props.theme.spaces[11]}px;
// 200 is to have some space at the bottom
height: calc(100% - 200px);
margin-right: ${(props) => props.theme.spaces[9]}px;
margin-left: ${(props) => props.theme.spaces[12] + 2}px;
`;
const SearchWrapper = styled.div`
margin-left: ${(props) => props.theme.spaces[11]}px;
`;
function TemplateRoutes() {
const { path } = useRouteMatch();
const dispatch = useDispatch();
const organizationListLength = useSelector(
(state: AppState) => getUserApplicationsOrgsList(state).length,
);
const pluginListLength = useSelector(
(state: AppState) => state.entities.plugins.defaultPluginList.length,
);
const templatesCount = useSelector(
(state: AppState) => state.ui.templates.templates.length,
);
useEffect(() => {
dispatch(setHeaderMeta(true, true));
// Generate the widget config list
editorInitializer();
}, []);
useEffect(() => {
if (!templatesCount) {
dispatch(getAllTemplates());
}
}, [templatesCount]);
useEffect(() => {
if (!organizationListLength) {
dispatch(getAllApplications());
}
}, [organizationListLength]);
useEffect(() => {
if (!pluginListLength) {
dispatch(fetchDefaultPlugins());
}
}, [pluginListLength]);
return (
<Switch>
<SentryRoute component={TemplateView} path={`${path}/:templateId`} />
<SentryRoute component={Templates} path={path} />
</Switch>
);
}
function TemplateListLoader() {
return (
<Loader>
<ResultsCount className={`results-count ${Classes.SKELETON}`} />
<LoadingTemplateList className={Classes.SKELETON} />
</Loader>
);
}
function Templates() {
const templates = useSelector(getSearchedTemplateList);
const templateSearchQuery = useSelector(getTemplateSearchQuery);
const isFetchingApplications = useSelector(getIsFetchingApplications);
const isFetchingTemplates = useSelector(isFetchingTemplatesSelector);
const filterCount = useSelector(getTemplateFiltersLength);
const dispatch = useDispatch();
let resultsText =
templates.length > 1
? `Showing all ${templates.length} templates`
: templates.length === 1
? "Showing 1 template"
: "No templates to show";
if (templates.length) {
resultsText +=
filterCount > 1
? ` matching ${filterCount} filters`
: filterCount === 1
? " matching 1 filter"
: "";
}
const isLoading = isFetchingApplications || isFetchingTemplates;
const onChange = (query: string) => {
dispatch(setTemplateSearchQuery(query));
};
const debouncedOnChange = debounce(onChange, 250, { maxWait: 1000 });
return (
<PageWrapper>
<Filters />
<TemplateListWrapper>
{isLoading ? (
<TemplateListLoader />
) : (
<>
<SearchWrapper>
<ControlGroup>
<SearchInput
cypressSelector={"t--application-search-input"}
defaultValue={templateSearchQuery}
disabled={isLoading}
onChange={debouncedOnChange || noop}
placeholder={createMessage(SEARCH_TEMPLATES)}
variant={SearchVariant.BACKGROUND}
/>
</ControlGroup>
</SearchWrapper>
<ResultsCount>{resultsText}</ResultsCount>
<TemplateList templates={templates} />
</>
)}
</TemplateListWrapper>
</PageWrapper>
);
}
export default TemplateRoutes;