Add search to translations

This commit is contained in:
dominik-zeglen 2019-09-12 14:43:37 +02:00
parent 3974b23b15
commit f9285cec60
23 changed files with 333 additions and 171 deletions

View file

@ -0,0 +1,98 @@
import { Theme } from "@material-ui/core/styles";
import { makeStyles } from "@material-ui/styles";
import React from "react";
import { FormattedMessage } from "react-intl";
import { SearchPageProps } from "../../types";
import Debounce from "../Debounce";
import { FilterActionsOnlySearch } from "../Filter/FilterActions";
import Hr from "../Hr";
import Link from "../Link";
export interface FilterSearchProps extends SearchPageProps {
displaySearchAction: "save" | "delete" | null;
searchPlaceholder: string;
onSearchDelete?: () => void;
onSearchSave?: () => void;
}
const useStyles = makeStyles(
(theme: Theme) => ({
tabAction: {
display: "inline-block"
},
tabActionContainer: {
borderBottom: "1px solid #e8e8e8",
display: "flex",
justifyContent: "flex-end",
marginTop: theme.spacing.unit,
padding: `0 ${theme.spacing.unit * 3}px ${theme.spacing.unit}px`
}
}),
{
name: "FilterSearch"
}
);
const FilterSearch: React.FC<FilterSearchProps> = props => {
const {
displaySearchAction,
initialSearch,
onSearchChange,
onSearchDelete,
onSearchSave,
searchPlaceholder
} = props;
const classes = useStyles(props);
const [search, setSearch] = React.useState(initialSearch);
React.useEffect(() => setSearch(initialSearch), [initialSearch]);
return (
<Debounce debounceFn={onSearchChange}>
{debounceSearchChange => {
const handleSearchChange = (event: React.ChangeEvent<any>) => {
const value = event.target.value;
setSearch(value);
debounceSearchChange(value);
};
return (
<>
<FilterActionsOnlySearch
{...props}
placeholder={searchPlaceholder}
search={search}
onSearchChange={handleSearchChange}
/>
{!!displaySearchAction ? (
<div className={classes.tabActionContainer}>
<div className={classes.tabAction}>
{displaySearchAction === "save" ? (
<Link onClick={onSearchSave}>
<FormattedMessage
defaultMessage="Save Custom Search"
description="button"
/>
</Link>
) : (
<Link onClick={onSearchDelete}>
<FormattedMessage
defaultMessage="Delete Search"
description="button"
/>
</Link>
)}
</div>
</div>
) : (
<Hr />
)}
</>
);
}}
</Debounce>
);
};
FilterSearch.displayName = "FilterSearch";
export default FilterSearch;

View file

@ -1,13 +1,8 @@
import { Theme } from "@material-ui/core/styles";
import { makeStyles } from "@material-ui/styles";
import React from "react"; import React from "react";
import { FormattedMessage, useIntl } from "react-intl"; import { useIntl } from "react-intl";
import { SearchPageProps, TabPageProps } from "@saleor/types"; import { SearchPageProps, TabPageProps } from "@saleor/types";
import Debounce from "../Debounce"; import FilterSearch from "../Filter/FilterSearch";
import { FilterActionsOnlySearch } from "../Filter/FilterActions";
import Hr from "../Hr";
import Link from "../Link";
import FilterTabs, { FilterTab } from "../TableFilter"; import FilterTabs, { FilterTab } from "../TableFilter";
export interface SearchBarProps extends SearchPageProps, TabPageProps { export interface SearchBarProps extends SearchPageProps, TabPageProps {
@ -15,24 +10,6 @@ export interface SearchBarProps extends SearchPageProps, TabPageProps {
searchPlaceholder: string; searchPlaceholder: string;
} }
const useStyles = makeStyles(
(theme: Theme) => ({
tabAction: {
display: "inline-block"
},
tabActionContainer: {
borderBottom: "1px solid #e8e8e8",
display: "flex",
justifyContent: "flex-end",
marginTop: theme.spacing.unit,
padding: `0 ${theme.spacing.unit * 3}px ${theme.spacing.unit}px`
}
}),
{
name: "SearchBar"
}
);
const SearchBar: React.FC<SearchBarProps> = props => { const SearchBar: React.FC<SearchBarProps> = props => {
const { const {
allTabLabel, allTabLabel,
@ -46,7 +23,6 @@ const SearchBar: React.FC<SearchBarProps> = props => {
onTabDelete, onTabDelete,
onTabSave onTabSave
} = props; } = props;
const classes = useStyles(props);
const [search, setSearch] = React.useState(initialSearch); const [search, setSearch] = React.useState(initialSearch);
const intl = useIntl(); const intl = useIntl();
React.useEffect(() => setSearch(initialSearch), [initialSearch]); React.useEffect(() => setSearch(initialSearch), [initialSearch]);
@ -73,49 +49,14 @@ const SearchBar: React.FC<SearchBarProps> = props => {
/> />
)} )}
</FilterTabs> </FilterTabs>
<Debounce debounceFn={onSearchChange}> <FilterSearch
{debounceSearchChange => { displaySearchAction={!!search ? (isCustom ? "save" : "delete") : null}
const handleSearchChange = (event: React.ChangeEvent<any>) => { initialSearch={initialSearch}
const value = event.target.value; searchPlaceholder={searchPlaceholder}
setSearch(value); onSearchChange={onSearchChange}
debounceSearchChange(value); onSearchDelete={onTabDelete}
}; onSearchSave={onTabSave}
/>
return (
<>
<FilterActionsOnlySearch
{...props}
placeholder={searchPlaceholder}
search={search}
onSearchChange={handleSearchChange}
/>
{!!search || (tabs && tabs.length > 0 && currentTab !== 0) ? (
<div className={classes.tabActionContainer}>
<div className={classes.tabAction}>
{isCustom ? (
<Link onClick={onTabSave}>
<FormattedMessage
defaultMessage="Save Custom Search"
description="button"
/>
</Link>
) : (
<Link onClick={onTabDelete}>
<FormattedMessage
defaultMessage="Delete Search"
description="button"
/>
</Link>
)}
</div>
</div>
) : (
<Hr />
)}
</>
);
}}
</Debounce>
</> </>
); );
}; };

View file

@ -1,17 +1,19 @@
import Card from "@material-ui/core/Card"; import Card from "@material-ui/core/Card";
import React from "react"; import React from "react";
import { useIntl } from "react-intl"; import { IntlShape, useIntl } from "react-intl";
import AppHeader from "@saleor/components/AppHeader"; import AppHeader from "@saleor/components/AppHeader";
import Container from "@saleor/components/Container"; import Container from "@saleor/components/Container";
import FilterSearch from "@saleor/components/Filter/FilterSearch";
import PageHeader from "@saleor/components/PageHeader"; import PageHeader from "@saleor/components/PageHeader";
// tslint:disable no-submodule-imports // tslint:disable no-submodule-imports
import { ShopInfo_shop_languages } from "@saleor/components/Shop/types/ShopInfo"; import { ShopInfo_shop_languages } from "@saleor/components/Shop/types/ShopInfo";
import FilterTabs, { FilterTab } from "@saleor/components/TableFilter"; import FilterTabs, { FilterTab } from "@saleor/components/TableFilter";
import { maybe } from "@saleor/misc"; import { maybe } from "@saleor/misc";
import { SearchPageProps } from "@saleor/types";
import { TranslatableEntities } from "../../urls"; import { TranslatableEntities } from "../../urls";
export interface TranslationsEntitiesListPageProps { export interface TranslationsEntitiesListPageProps extends SearchPageProps {
children: React.ReactNode; children: React.ReactNode;
filters: TranslationsEntitiesFilters; filters: TranslationsEntitiesFilters;
language: ShopInfo_shop_languages; language: ShopInfo_shop_languages;
@ -31,10 +33,66 @@ export interface TranslationsEntitiesFilters {
export type TranslationsEntitiesListFilterTab = keyof typeof TranslatableEntities; export type TranslationsEntitiesListFilterTab = keyof typeof TranslatableEntities;
function getSearchPlaceholder(
tab: TranslationsEntitiesListFilterTab,
intl: IntlShape
): string {
switch (tab) {
case "categories":
return intl.formatMessage({
defaultMessage: "Search Category"
});
case "collections":
return intl.formatMessage({
defaultMessage: "Search Collection"
});
case "products":
return intl.formatMessage({
defaultMessage: "Search Product"
});
case "sales":
return intl.formatMessage({
defaultMessage: "Search Sale"
});
case "vouchers":
return intl.formatMessage({
defaultMessage: "Search Voucher"
});
case "pages":
return intl.formatMessage({
defaultMessage: "Search Page"
});
case "productTypes":
return intl.formatMessage({
defaultMessage: "Search Product Type"
});
default:
return "...";
}
}
const tabs: TranslationsEntitiesListFilterTab[] = [
"categories",
"collections",
"products",
"sales",
"vouchers",
"pages",
"productTypes"
];
const TranslationsEntitiesListPage: React.StatelessComponent< const TranslationsEntitiesListPage: React.StatelessComponent<
TranslationsEntitiesListPageProps TranslationsEntitiesListPageProps
> = ({ filters, language, onBack, children }) => { > = ({ filters, language, onBack, children, ...searchProps }) => {
const intl = useIntl(); const intl = useIntl();
const currentTab = tabs.indexOf(filters.current);
return ( return (
<Container> <Container>
@ -55,17 +113,7 @@ const TranslationsEntitiesListPage: React.StatelessComponent<
)} )}
/> />
<Card> <Card>
<FilterTabs <FilterTabs currentTab={currentTab}>
currentTab={([
"categories",
"collections",
"products",
"sales",
"vouchers",
"pages",
"productTypes"
] as TranslationsEntitiesListFilterTab[]).indexOf(filters.current)}
>
<FilterTab <FilterTab
label={intl.formatMessage({ label={intl.formatMessage({
defaultMessage: "Categories" defaultMessage: "Categories"
@ -109,6 +157,11 @@ const TranslationsEntitiesListPage: React.StatelessComponent<
onClick={filters.onProductTypesTabClick} onClick={filters.onProductTypesTabClick}
/> />
</FilterTabs> </FilterTabs>
<FilterSearch
displaySearchAction={null}
searchPlaceholder={getSearchPlaceholder(filters.current, intl)}
{...searchProps}
/>
{children} {children}
</Card> </Card>
</Container> </Container>

View file

@ -18,9 +18,7 @@ import TranslationsCategoriesComponent, {
import TranslationsCollectionsComponent, { import TranslationsCollectionsComponent, {
TranslationsCollectionsQueryParams TranslationsCollectionsQueryParams
} from "./views/TranslationsCollections"; } from "./views/TranslationsCollections";
import TranslationsEntitiesComponent, { import TranslationsEntitiesComponent from "./views/TranslationsEntities";
TranslationsEntitiesListQueryParams
} from "./views/TranslationsEntities";
import TranslationsLanguageList from "./views/TranslationsLanguageList"; import TranslationsLanguageList from "./views/TranslationsLanguageList";
import TranslationsPagesComponent, { import TranslationsPagesComponent, {
TranslationsPagesQueryParams TranslationsPagesQueryParams
@ -46,15 +44,11 @@ const TranslationsEntities: React.FC<TranslationsEntitiesRouteProps> = ({
match match
}) => { }) => {
const qs = parseQs(location.search.substr(1)); const qs = parseQs(location.search.substr(1));
const params: TranslationsEntitiesListQueryParams = {
after: qs.after,
before: qs.before,
tab: qs.tab
};
return ( return (
<TranslationsEntitiesComponent <TranslationsEntitiesComponent
language={match.params.languageCode} language={match.params.languageCode}
params={params} params={qs}
/> />
); );
}; };

View file

@ -217,8 +217,15 @@ const categoryTranslations = gql`
$after: String $after: String
$last: Int $last: Int
$before: String $before: String
$filter: CategoryFilterInput
) { ) {
categories(before: $before, after: $after, first: $first, last: $last) { categories(
before: $before
after: $after
first: $first
last: $last
filter: $filter
) {
edges { edges {
node { node {
...CategoryTranslationFragment ...CategoryTranslationFragment
@ -244,8 +251,15 @@ const collectionTranslations = gql`
$after: String $after: String
$last: Int $last: Int
$before: String $before: String
$filter: CollectionFilterInput
) { ) {
collections(before: $before, after: $after, first: $first, last: $last) { collections(
before: $before
after: $after
first: $first
last: $last
filter: $filter
) {
edges { edges {
node { node {
...CollectionTranslationFragment ...CollectionTranslationFragment
@ -271,8 +285,15 @@ const productTranslations = gql`
$after: String $after: String
$last: Int $last: Int
$before: String $before: String
$filter: ProductFilterInput
) { ) {
products(before: $before, after: $after, first: $first, last: $last) { products(
before: $before
after: $after
first: $first
last: $last
filter: $filter
) {
edges { edges {
node { node {
...ProductTranslationFragment ...ProductTranslationFragment
@ -298,8 +319,15 @@ const pageTranslations = gql`
$after: String $after: String
$last: Int $last: Int
$before: String $before: String
$filter: PageFilterInput
) { ) {
pages(before: $before, after: $after, first: $first, last: $last) { pages(
before: $before
after: $after
first: $first
last: $last
filter: $filter
) {
edges { edges {
node { node {
...PageTranslationFragment ...PageTranslationFragment
@ -325,8 +353,15 @@ const voucherTranslations = gql`
$after: String $after: String
$last: Int $last: Int
$before: String $before: String
$filter: VoucherFilterInput
) { ) {
vouchers(before: $before, after: $after, first: $first, last: $last) { vouchers(
before: $before
after: $after
first: $first
last: $last
filter: $filter
) {
edges { edges {
node { node {
...VoucherTranslationFragment ...VoucherTranslationFragment
@ -352,8 +387,15 @@ const saleTranslations = gql`
$after: String $after: String
$last: Int $last: Int
$before: String $before: String
$filter: SaleFilterInput
) { ) {
sales(before: $before, after: $after, first: $first, last: $last) { sales(
before: $before
after: $after
first: $first
last: $last
filter: $filter
) {
edges { edges {
node { node {
...SaleTranslationFragment ...SaleTranslationFragment
@ -379,8 +421,15 @@ const productTypeTranslations = gql`
$after: String $after: String
$last: Int $last: Int
$before: String $before: String
$filter: ProductTypeFilterInput
) { ) {
productTypes(before: $before, after: $after, first: $first, last: $last) { productTypes(
before: $before
after: $after
first: $first
last: $last
filter: $filter
) {
edges { edges {
node { node {
...ProductTypeTranslationFragment ...ProductTypeTranslationFragment

View file

@ -2,7 +2,7 @@
/* eslint-disable */ /* eslint-disable */
// This file was automatically generated and should not be edited. // This file was automatically generated and should not be edited.
import { LanguageCodeEnum } from "./../../types/globalTypes"; import { LanguageCodeEnum, CategoryFilterInput } from "./../../types/globalTypes";
// ==================================================== // ====================================================
// GraphQL query operation: CategoryTranslations // GraphQL query operation: CategoryTranslations
@ -62,4 +62,5 @@ export interface CategoryTranslationsVariables {
after?: string | null; after?: string | null;
last?: number | null; last?: number | null;
before?: string | null; before?: string | null;
filter?: CategoryFilterInput | null;
} }

View file

@ -2,7 +2,7 @@
/* eslint-disable */ /* eslint-disable */
// This file was automatically generated and should not be edited. // This file was automatically generated and should not be edited.
import { LanguageCodeEnum } from "./../../types/globalTypes"; import { LanguageCodeEnum, CollectionFilterInput } from "./../../types/globalTypes";
// ==================================================== // ====================================================
// GraphQL query operation: CollectionTranslations // GraphQL query operation: CollectionTranslations
@ -62,4 +62,5 @@ export interface CollectionTranslationsVariables {
after?: string | null; after?: string | null;
last?: number | null; last?: number | null;
before?: string | null; before?: string | null;
filter?: CollectionFilterInput | null;
} }

View file

@ -2,7 +2,7 @@
/* eslint-disable */ /* eslint-disable */
// This file was automatically generated and should not be edited. // This file was automatically generated and should not be edited.
import { LanguageCodeEnum } from "./../../types/globalTypes"; import { LanguageCodeEnum, PageFilterInput } from "./../../types/globalTypes";
// ==================================================== // ====================================================
// GraphQL query operation: PageTranslations // GraphQL query operation: PageTranslations
@ -63,4 +63,5 @@ export interface PageTranslationsVariables {
after?: string | null; after?: string | null;
last?: number | null; last?: number | null;
before?: string | null; before?: string | null;
filter?: PageFilterInput | null;
} }

View file

@ -2,7 +2,7 @@
/* eslint-disable */ /* eslint-disable */
// This file was automatically generated and should not be edited. // This file was automatically generated and should not be edited.
import { LanguageCodeEnum } from "./../../types/globalTypes"; import { LanguageCodeEnum, ProductFilterInput } from "./../../types/globalTypes";
// ==================================================== // ====================================================
// GraphQL query operation: ProductTranslations // GraphQL query operation: ProductTranslations
@ -63,4 +63,5 @@ export interface ProductTranslationsVariables {
after?: string | null; after?: string | null;
last?: number | null; last?: number | null;
before?: string | null; before?: string | null;
filter?: ProductFilterInput | null;
} }

View file

@ -2,7 +2,7 @@
/* eslint-disable */ /* eslint-disable */
// This file was automatically generated and should not be edited. // This file was automatically generated and should not be edited.
import { LanguageCodeEnum } from "./../../types/globalTypes"; import { LanguageCodeEnum, ProductTypeFilterInput } from "./../../types/globalTypes";
// ==================================================== // ====================================================
// GraphQL query operation: ProductTypeTranslations // GraphQL query operation: ProductTypeTranslations
@ -99,4 +99,5 @@ export interface ProductTypeTranslationsVariables {
after?: string | null; after?: string | null;
last?: number | null; last?: number | null;
before?: string | null; before?: string | null;
filter?: ProductTypeFilterInput | null;
} }

View file

@ -2,7 +2,7 @@
/* eslint-disable */ /* eslint-disable */
// This file was automatically generated and should not be edited. // This file was automatically generated and should not be edited.
import { LanguageCodeEnum } from "./../../types/globalTypes"; import { LanguageCodeEnum, SaleFilterInput } from "./../../types/globalTypes";
// ==================================================== // ====================================================
// GraphQL query operation: SaleTranslations // GraphQL query operation: SaleTranslations
@ -57,4 +57,5 @@ export interface SaleTranslationsVariables {
after?: string | null; after?: string | null;
last?: number | null; last?: number | null;
before?: string | null; before?: string | null;
filter?: SaleFilterInput | null;
} }

View file

@ -2,7 +2,7 @@
/* eslint-disable */ /* eslint-disable */
// This file was automatically generated and should not be edited. // This file was automatically generated and should not be edited.
import { LanguageCodeEnum } from "./../../types/globalTypes"; import { LanguageCodeEnum, VoucherFilterInput } from "./../../types/globalTypes";
// ==================================================== // ====================================================
// GraphQL query operation: VoucherTranslations // GraphQL query operation: VoucherTranslations
@ -57,4 +57,5 @@ export interface VoucherTranslationsVariables {
after?: string | null; after?: string | null;
last?: number | null; last?: number | null;
before?: string | null; before?: string | null;
filter?: VoucherFilterInput | null;
} }

View file

@ -1,6 +1,9 @@
import { stringify as stringifyQs } from "qs"; import { stringify as stringifyQs } from "qs";
import urlJoin from "url-join"; import urlJoin from "url-join";
import { Pagination } from "@saleor/types";
import { TranslationsEntitiesListFilterTab } from "./components/TranslationsEntitiesListPage";
export enum TranslatableEntities { export enum TranslatableEntities {
categories = "categories", categories = "categories",
products = "products", products = "products",
@ -18,12 +21,15 @@ export const languageListUrl = translationsSection;
export const languageEntitiesPath = (code: string) => export const languageEntitiesPath = (code: string) =>
urlJoin(translationsSection, code); urlJoin(translationsSection, code);
export const languageEntitiesUrl = (code: string, tab?: TranslatableEntities) => export type LanguageEntitiesUrlQueryParams = Pagination &
languageEntitiesPath(code) + Partial<{
"?" + query: string;
stringifyQs({ tab: TranslationsEntitiesListFilterTab;
tab }>;
}); export const languageEntitiesUrl = (
code: string,
params: LanguageEntitiesUrlQueryParams
) => languageEntitiesPath(code) + "?" + stringifyQs(params);
export const languageEntityPath = ( export const languageEntityPath = (
code: string, code: string,

View file

@ -104,10 +104,9 @@ const TranslationsCategories: React.FC<TranslationsCategoriesProps> = ({
saveButtonState={saveButtonState} saveButtonState={saveButtonState}
onBack={() => onBack={() =>
navigate( navigate(
languageEntitiesUrl( languageEntitiesUrl(languageCode, {
languageCode, tab: TranslatableEntities.categories
TranslatableEntities.categories })
)
) )
} }
onEdit={onEdit} onEdit={onEdit}

View file

@ -109,10 +109,9 @@ const TranslationsCollections: React.FC<TranslationsCollectionsProps> = ({
onDiscard={onDiscard} onDiscard={onDiscard}
onBack={() => onBack={() =>
navigate( navigate(
languageEntitiesUrl( languageEntitiesUrl(languageCode, {
languageCode, tab: TranslatableEntities.collections
TranslatableEntities.collections })
)
) )
} }
onLanguageChange={lang => onLanguageChange={lang =>

View file

@ -8,11 +8,8 @@ import usePaginator, {
import useShop from "@saleor/hooks/useShop"; import useShop from "@saleor/hooks/useShop";
import { PAGINATE_BY } from "../../config"; import { PAGINATE_BY } from "../../config";
import { maybe } from "../../misc"; import { maybe } from "../../misc";
import { Pagination } from "../../types";
import TranslationsEntitiesList from "../components/TranslationsEntitiesList"; import TranslationsEntitiesList from "../components/TranslationsEntitiesList";
import TranslationsEntitiesListPage, { import TranslationsEntitiesListPage from "../components/TranslationsEntitiesListPage";
TranslationsEntitiesListFilterTab
} from "../components/TranslationsEntitiesListPage";
import { import {
TypedCategoryTranslations, TypedCategoryTranslations,
TypedCollectionTranslations, TypedCollectionTranslations,
@ -24,18 +21,16 @@ import {
} from "../queries"; } from "../queries";
import { AttributeTranslationFragment } from "../types/AttributeTranslationFragment"; import { AttributeTranslationFragment } from "../types/AttributeTranslationFragment";
import { import {
languageEntitiesUrl,
LanguageEntitiesUrlQueryParams,
languageEntityUrl, languageEntityUrl,
languageListUrl, languageListUrl,
TranslatableEntities TranslatableEntities
} from "../urls"; } from "../urls";
export type TranslationsEntitiesListQueryParams = Pagination & {
tab: TranslationsEntitiesListFilterTab;
};
interface TranslationsEntitiesProps { interface TranslationsEntitiesProps {
language: string; language: string;
params: TranslationsEntitiesListQueryParams; params: LanguageEntitiesUrlQueryParams;
} }
function sumTranslations( function sumTranslations(
@ -128,9 +123,29 @@ const TranslationsEntities: React.FC<TranslationsEntitiesProps> = ({
shop.languages.find(languageFromList => languageFromList.code === language) shop.languages.find(languageFromList => languageFromList.code === language)
); );
const paginationState = createPaginationState(PAGINATE_BY, params); const paginationState = createPaginationState(PAGINATE_BY, params);
const queryVariables = React.useMemo(
() => ({
...paginationState,
filter: {
search: params.query
},
language: language as any
}),
[params]
);
return ( return (
<TranslationsEntitiesListPage <TranslationsEntitiesListPage
initialSearch={params.query || ""}
onSearchChange={query =>
navigate(
languageEntitiesUrl(language, {
...params,
query
}),
true
)
}
filters={{ filters={{
current: params.tab, current: params.tab,
...filterCallbacks ...filterCallbacks
@ -139,9 +154,7 @@ const TranslationsEntities: React.FC<TranslationsEntitiesProps> = ({
onBack={() => navigate(languageListUrl)} onBack={() => navigate(languageListUrl)}
> >
{params.tab === "categories" ? ( {params.tab === "categories" ? (
<TypedCategoryTranslations <TypedCategoryTranslations variables={queryVariables}>
variables={{ language: language as any, ...paginationState }}
>
{({ data, loading }) => { {({ data, loading }) => {
const { loadNextPage, loadPreviousPage, pageInfo } = paginate( const { loadNextPage, loadPreviousPage, pageInfo } = paginate(
maybe(() => data.categories.pageInfo), maybe(() => data.categories.pageInfo),
@ -191,9 +204,7 @@ const TranslationsEntities: React.FC<TranslationsEntitiesProps> = ({
}} }}
</TypedCategoryTranslations> </TypedCategoryTranslations>
) : params.tab === "products" ? ( ) : params.tab === "products" ? (
<TypedProductTranslations <TypedProductTranslations variables={queryVariables}>
variables={{ language: language as any, ...paginationState }}
>
{({ data, loading }) => { {({ data, loading }) => {
const { loadNextPage, loadPreviousPage, pageInfo } = paginate( const { loadNextPage, loadPreviousPage, pageInfo } = paginate(
maybe(() => data.products.pageInfo), maybe(() => data.products.pageInfo),
@ -243,9 +254,7 @@ const TranslationsEntities: React.FC<TranslationsEntitiesProps> = ({
}} }}
</TypedProductTranslations> </TypedProductTranslations>
) : params.tab === "collections" ? ( ) : params.tab === "collections" ? (
<TypedCollectionTranslations <TypedCollectionTranslations variables={queryVariables}>
variables={{ language: language as any, ...paginationState }}
>
{({ data, loading }) => { {({ data, loading }) => {
const { loadNextPage, loadPreviousPage, pageInfo } = paginate( const { loadNextPage, loadPreviousPage, pageInfo } = paginate(
maybe(() => data.collections.pageInfo), maybe(() => data.collections.pageInfo),
@ -295,9 +304,7 @@ const TranslationsEntities: React.FC<TranslationsEntitiesProps> = ({
}} }}
</TypedCollectionTranslations> </TypedCollectionTranslations>
) : params.tab === "sales" ? ( ) : params.tab === "sales" ? (
<TypedSaleTranslations <TypedSaleTranslations variables={queryVariables}>
variables={{ language: language as any, ...paginationState }}
>
{({ data, loading }) => { {({ data, loading }) => {
const { loadNextPage, loadPreviousPage, pageInfo } = paginate( const { loadNextPage, loadPreviousPage, pageInfo } = paginate(
maybe(() => data.sales.pageInfo), maybe(() => data.sales.pageInfo),
@ -335,9 +342,7 @@ const TranslationsEntities: React.FC<TranslationsEntitiesProps> = ({
}} }}
</TypedSaleTranslations> </TypedSaleTranslations>
) : params.tab === "vouchers" ? ( ) : params.tab === "vouchers" ? (
<TypedVoucherTranslations <TypedVoucherTranslations variables={queryVariables}>
variables={{ language: language as any, ...paginationState }}
>
{({ data, loading }) => { {({ data, loading }) => {
const { loadNextPage, loadPreviousPage, pageInfo } = paginate( const { loadNextPage, loadPreviousPage, pageInfo } = paginate(
maybe(() => data.vouchers.pageInfo), maybe(() => data.vouchers.pageInfo),
@ -379,9 +384,7 @@ const TranslationsEntities: React.FC<TranslationsEntitiesProps> = ({
}} }}
</TypedVoucherTranslations> </TypedVoucherTranslations>
) : params.tab === "pages" ? ( ) : params.tab === "pages" ? (
<TypedPageTranslations <TypedPageTranslations variables={queryVariables}>
variables={{ language: language as any, ...paginationState }}
>
{({ data, loading }) => { {({ data, loading }) => {
const { loadNextPage, loadPreviousPage, pageInfo } = paginate( const { loadNextPage, loadPreviousPage, pageInfo } = paginate(
maybe(() => data.pages.pageInfo), maybe(() => data.pages.pageInfo),
@ -427,9 +430,7 @@ const TranslationsEntities: React.FC<TranslationsEntitiesProps> = ({
}} }}
</TypedPageTranslations> </TypedPageTranslations>
) : params.tab === "productTypes" ? ( ) : params.tab === "productTypes" ? (
<TypedProductTypeTranslations <TypedProductTypeTranslations variables={queryVariables}>
variables={{ language: language as any, ...paginationState }}
>
{({ data, loading }) => { {({ data, loading }) => {
const { loadNextPage, loadPreviousPage, pageInfo } = paginate( const { loadNextPage, loadPreviousPage, pageInfo } = paginate(
maybe(() => data.productTypes.pageInfo), maybe(() => data.productTypes.pageInfo),

View file

@ -14,7 +14,7 @@ const TranslationsLanguageList: React.FC = () => {
<TranslationsLanguageListPage <TranslationsLanguageListPage
languages={maybe(() => shop.languages)} languages={maybe(() => shop.languages)}
// onAdd={undefined} // onAdd={undefined}
onRowClick={code => navigate(languageEntitiesUrl(code))} onRowClick={code => navigate(languageEntitiesUrl(code, {}))}
/> />
); );
}; };

View file

@ -104,10 +104,9 @@ const TranslationsPages: React.FC<TranslationsPagesProps> = ({
saveButtonState={saveButtonState} saveButtonState={saveButtonState}
onBack={() => onBack={() =>
navigate( navigate(
languageEntitiesUrl( languageEntitiesUrl(languageCode, {
languageCode, tab: TranslatableEntities.pages
TranslatableEntities.pages })
)
) )
} }
onEdit={onEdit} onEdit={onEdit}

View file

@ -144,10 +144,9 @@ const TranslationsProductTypes: React.FC<TranslationsProductTypesProps> = ({
saveButtonState={saveButtonState} saveButtonState={saveButtonState}
onBack={() => onBack={() =>
navigate( navigate(
languageEntitiesUrl( languageEntitiesUrl(languageCode, {
languageCode, tab: TranslatableEntities.productTypes
TranslatableEntities.productTypes })
)
) )
} }
onEdit={onEdit} onEdit={onEdit}

View file

@ -104,10 +104,9 @@ const TranslationsProducts: React.FC<TranslationsProductsProps> = ({
saveButtonState={saveButtonState} saveButtonState={saveButtonState}
onBack={() => onBack={() =>
navigate( navigate(
languageEntitiesUrl( languageEntitiesUrl(languageCode, {
languageCode, tab: TranslatableEntities.products
TranslatableEntities.products })
)
) )
} }
onEdit={onEdit} onEdit={onEdit}

View file

@ -98,10 +98,9 @@ const TranslationsSales: React.FC<TranslationsSalesProps> = ({
saveButtonState={saveButtonState} saveButtonState={saveButtonState}
onBack={() => onBack={() =>
navigate( navigate(
languageEntitiesUrl( languageEntitiesUrl(languageCode, {
languageCode, tab: TranslatableEntities.sales
TranslatableEntities.sales })
)
) )
} }
onEdit={onEdit} onEdit={onEdit}

View file

@ -101,10 +101,9 @@ const TranslationsVouchers: React.FC<TranslationsVouchersProps> = ({
saveButtonState={saveButtonState} saveButtonState={saveButtonState}
onBack={() => onBack={() =>
navigate( navigate(
languageEntitiesUrl( languageEntitiesUrl(languageCode, {
languageCode, tab: TranslatableEntities.vouchers
TranslatableEntities.vouchers })
)
) )
} }
onEdit={onEdit} onEdit={onEdit}

View file

@ -187,6 +187,16 @@ export enum PermissionEnum {
MANAGE_USERS = "MANAGE_USERS", MANAGE_USERS = "MANAGE_USERS",
} }
export enum ProductTypeConfigurable {
CONFIGURABLE = "CONFIGURABLE",
SIMPLE = "SIMPLE",
}
export enum ProductTypeEnum {
DIGITAL = "DIGITAL",
SHIPPABLE = "SHIPPABLE",
}
export enum SaleType { export enum SaleType {
FIXED = "FIXED", FIXED = "FIXED",
PERCENTAGE = "PERCENTAGE", PERCENTAGE = "PERCENTAGE",
@ -520,6 +530,10 @@ export interface OrderUpdateShippingInput {
shippingMethod?: string | null; shippingMethod?: string | null;
} }
export interface PageFilterInput {
search?: string | null;
}
export interface PageInput { export interface PageInput {
slug?: string | null; slug?: string | null;
title?: string | null; title?: string | null;
@ -560,6 +574,12 @@ export interface ProductFilterInput {
minimalPrice?: PriceRangeInput | null; minimalPrice?: PriceRangeInput | null;
} }
export interface ProductTypeFilterInput {
search?: string | null;
configurable?: ProductTypeConfigurable | null;
productType?: ProductTypeEnum | null;
}
export interface ProductTypeInput { export interface ProductTypeInput {
name?: string | null; name?: string | null;
hasVariants?: boolean | null; hasVariants?: boolean | null;