Menu item translations (#2181)

* [Feat] Added MenuItem translations

* [Feat] Added MenuItem translations

* Stories snaps

* max
This commit is contained in:
Carles López Magem 2022-07-26 11:12:02 +02:00 committed by GitHub
parent 9d99491623
commit 437a2130eb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 595 additions and 0 deletions

View file

@ -1483,6 +1483,9 @@
"context": "section header",
"string": "Eligible Categories"
},
"AcMzwj": {
"string": "Menu items"
},
"AdmPca": {
"context": "error message",
"string": "Max value cannot be less than min value"
@ -2556,6 +2559,10 @@
"context": "payment status",
"string": "Partially paid"
},
"IOshTA": {
"context": "header",
"string": "Translation MenuItem \"{menuItemName}\" - {languageCode}"
},
"IUeGzv": {
"context": "plugin name",
"string": "Plugin Name"

View file

@ -312,3 +312,19 @@ export const attributeValueTranslatableContentFragment = gql`
}
}
`;
export const menuItemTranslationFragment = gql`
fragment MenuItemTranslation on MenuItemTranslatableContent {
translation(languageCode: $language) {
id
language {
language
}
name
}
menuItem {
id
name
}
}
`;

View file

@ -2657,6 +2657,21 @@ export const AttributeValueTranslatableContentFragmentDoc = gql`
}
}
${AttributeChoicesTranslationFragmentDoc}`;
export const MenuItemTranslationFragmentDoc = gql`
fragment MenuItemTranslation on MenuItemTranslatableContent {
translation(languageCode: $language) {
id
language {
language
}
name
}
menuItem {
id
name
}
}
`;
export const WarehouseWithShippingFragmentDoc = gql`
fragment WarehouseWithShipping on Warehouse {
...Warehouse
@ -15239,6 +15254,55 @@ export function useUpdateShippingMethodTranslationsMutation(baseOptions?: Apollo
export type UpdateShippingMethodTranslationsMutationHookResult = ReturnType<typeof useUpdateShippingMethodTranslationsMutation>;
export type UpdateShippingMethodTranslationsMutationResult = Apollo.MutationResult<Types.UpdateShippingMethodTranslationsMutation>;
export type UpdateShippingMethodTranslationsMutationOptions = Apollo.BaseMutationOptions<Types.UpdateShippingMethodTranslationsMutation, Types.UpdateShippingMethodTranslationsMutationVariables>;
export const UpdateMenuItemTranslationsDocument = gql`
mutation UpdateMenuItemTranslations($id: ID!, $input: NameTranslationInput!, $language: LanguageCodeEnum!) {
menuItemTranslate(id: $id, input: $input, languageCode: $language) {
errors {
field
message
}
menuItem {
id
name
translation(languageCode: $language) {
id
language {
language
}
name
}
}
}
}
`;
export type UpdateMenuItemTranslationsMutationFn = Apollo.MutationFunction<Types.UpdateMenuItemTranslationsMutation, Types.UpdateMenuItemTranslationsMutationVariables>;
/**
* __useUpdateMenuItemTranslationsMutation__
*
* To run a mutation, you first call `useUpdateMenuItemTranslationsMutation` within a React component and pass it any options that fit your needs.
* When your component renders, `useUpdateMenuItemTranslationsMutation` returns a tuple that includes:
* - A mutate function that you can call at any time to execute the mutation
* - An object with fields that represent the current status of the mutation's execution
*
* @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;
*
* @example
* const [updateMenuItemTranslationsMutation, { data, loading, error }] = useUpdateMenuItemTranslationsMutation({
* variables: {
* id: // value for 'id'
* input: // value for 'input'
* language: // value for 'language'
* },
* });
*/
export function useUpdateMenuItemTranslationsMutation(baseOptions?: ApolloReactHooks.MutationHookOptions<Types.UpdateMenuItemTranslationsMutation, Types.UpdateMenuItemTranslationsMutationVariables>) {
const options = {...defaultOptions, ...baseOptions}
return ApolloReactHooks.useMutation<Types.UpdateMenuItemTranslationsMutation, Types.UpdateMenuItemTranslationsMutationVariables>(UpdateMenuItemTranslationsDocument, options);
}
export type UpdateMenuItemTranslationsMutationHookResult = ReturnType<typeof useUpdateMenuItemTranslationsMutation>;
export type UpdateMenuItemTranslationsMutationResult = Apollo.MutationResult<Types.UpdateMenuItemTranslationsMutation>;
export type UpdateMenuItemTranslationsMutationOptions = Apollo.BaseMutationOptions<Types.UpdateMenuItemTranslationsMutation, Types.UpdateMenuItemTranslationsMutationVariables>;
export const CategoryTranslationsDocument = gql`
query CategoryTranslations($language: LanguageCodeEnum!, $first: Int, $after: String, $last: Int, $before: String) {
translations(
@ -15663,6 +15727,59 @@ export function useShippingMethodTranslationsLazyQuery(baseOptions?: ApolloReact
export type ShippingMethodTranslationsQueryHookResult = ReturnType<typeof useShippingMethodTranslationsQuery>;
export type ShippingMethodTranslationsLazyQueryHookResult = ReturnType<typeof useShippingMethodTranslationsLazyQuery>;
export type ShippingMethodTranslationsQueryResult = Apollo.QueryResult<Types.ShippingMethodTranslationsQuery, Types.ShippingMethodTranslationsQueryVariables>;
export const MenuItemTranslationsDocument = gql`
query MenuItemTranslations($language: LanguageCodeEnum!, $first: Int, $after: String, $last: Int, $before: String) {
translations(
kind: MENU_ITEM
before: $before
after: $after
first: $first
last: $last
) {
edges {
node {
...MenuItemTranslation
}
}
pageInfo {
...PageInfo
}
}
}
${MenuItemTranslationFragmentDoc}
${PageInfoFragmentDoc}`;
/**
* __useMenuItemTranslationsQuery__
*
* To run a query within a React component, call `useMenuItemTranslationsQuery` and pass it any options that fit your needs.
* When your component renders, `useMenuItemTranslationsQuery` returns an object from Apollo Client that contains loading, error, and data properties
* you can use to render your UI.
*
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
*
* @example
* const { data, loading, error } = useMenuItemTranslationsQuery({
* variables: {
* language: // value for 'language'
* first: // value for 'first'
* after: // value for 'after'
* last: // value for 'last'
* before: // value for 'before'
* },
* });
*/
export function useMenuItemTranslationsQuery(baseOptions: ApolloReactHooks.QueryHookOptions<Types.MenuItemTranslationsQuery, Types.MenuItemTranslationsQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return ApolloReactHooks.useQuery<Types.MenuItemTranslationsQuery, Types.MenuItemTranslationsQueryVariables>(MenuItemTranslationsDocument, options);
}
export function useMenuItemTranslationsLazyQuery(baseOptions?: ApolloReactHooks.LazyQueryHookOptions<Types.MenuItemTranslationsQuery, Types.MenuItemTranslationsQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return ApolloReactHooks.useLazyQuery<Types.MenuItemTranslationsQuery, Types.MenuItemTranslationsQueryVariables>(MenuItemTranslationsDocument, options);
}
export type MenuItemTranslationsQueryHookResult = ReturnType<typeof useMenuItemTranslationsQuery>;
export type MenuItemTranslationsLazyQueryHookResult = ReturnType<typeof useMenuItemTranslationsLazyQuery>;
export type MenuItemTranslationsQueryResult = Apollo.QueryResult<Types.MenuItemTranslationsQuery, Types.MenuItemTranslationsQueryVariables>;
export const ProductTranslationDetailsDocument = gql`
query ProductTranslationDetails($id: ID!, $language: LanguageCodeEnum!) {
translation(kind: PRODUCT, id: $id) {
@ -16031,6 +16148,42 @@ export function useShippingMethodTranslationDetailsLazyQuery(baseOptions?: Apoll
export type ShippingMethodTranslationDetailsQueryHookResult = ReturnType<typeof useShippingMethodTranslationDetailsQuery>;
export type ShippingMethodTranslationDetailsLazyQueryHookResult = ReturnType<typeof useShippingMethodTranslationDetailsLazyQuery>;
export type ShippingMethodTranslationDetailsQueryResult = Apollo.QueryResult<Types.ShippingMethodTranslationDetailsQuery, Types.ShippingMethodTranslationDetailsQueryVariables>;
export const MenuItemTranslationDetailsDocument = gql`
query MenuItemTranslationDetails($id: ID!, $language: LanguageCodeEnum!) {
translation(kind: MENU_ITEM, id: $id) {
...MenuItemTranslation
}
}
${MenuItemTranslationFragmentDoc}`;
/**
* __useMenuItemTranslationDetailsQuery__
*
* To run a query within a React component, call `useMenuItemTranslationDetailsQuery` and pass it any options that fit your needs.
* When your component renders, `useMenuItemTranslationDetailsQuery` returns an object from Apollo Client that contains loading, error, and data properties
* you can use to render your UI.
*
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
*
* @example
* const { data, loading, error } = useMenuItemTranslationDetailsQuery({
* variables: {
* id: // value for 'id'
* language: // value for 'language'
* },
* });
*/
export function useMenuItemTranslationDetailsQuery(baseOptions: ApolloReactHooks.QueryHookOptions<Types.MenuItemTranslationDetailsQuery, Types.MenuItemTranslationDetailsQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return ApolloReactHooks.useQuery<Types.MenuItemTranslationDetailsQuery, Types.MenuItemTranslationDetailsQueryVariables>(MenuItemTranslationDetailsDocument, options);
}
export function useMenuItemTranslationDetailsLazyQuery(baseOptions?: ApolloReactHooks.LazyQueryHookOptions<Types.MenuItemTranslationDetailsQuery, Types.MenuItemTranslationDetailsQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return ApolloReactHooks.useLazyQuery<Types.MenuItemTranslationDetailsQuery, Types.MenuItemTranslationDetailsQueryVariables>(MenuItemTranslationDetailsDocument, options);
}
export type MenuItemTranslationDetailsQueryHookResult = ReturnType<typeof useMenuItemTranslationDetailsQuery>;
export type MenuItemTranslationDetailsLazyQueryHookResult = ReturnType<typeof useMenuItemTranslationDetailsLazyQuery>;
export type MenuItemTranslationDetailsQueryResult = Apollo.QueryResult<Types.MenuItemTranslationDetailsQuery, Types.MenuItemTranslationDetailsQueryVariables>;
export const UpdateMetadataDocument = gql`
mutation UpdateMetadata($id: ID!, $input: [MetadataInput!]!, $keysToDelete: [String!]!) {
updateMetadata(id: $id, input: $input) {

View file

@ -6568,6 +6568,8 @@ export type AttributeTranslationDetailsFragment = { __typename: 'AttributeTransl
export type AttributeValueTranslatableContentFragment = { __typename: 'AttributeTranslatableContent', translation: { __typename: 'AttributeTranslation', id: string, name: string } | null, attribute: { __typename: 'Attribute', id: string, name: string | null, inputType: AttributeInputTypeEnum | null, choices: { __typename: 'AttributeValueCountableConnection', pageInfo: { __typename: 'PageInfo', endCursor: string | null, hasNextPage: boolean, hasPreviousPage: boolean, startCursor: string | null }, edges: Array<{ __typename: 'AttributeValueCountableEdge', cursor: string, node: { __typename: 'AttributeValue', id: string, name: string | null, richText: any | null, inputType: AttributeInputTypeEnum | null, translation: { __typename: 'AttributeValueTranslation', id: string, name: string, richText: any | null } | null } }> } | null } | null };
export type MenuItemTranslationFragment = { __typename: 'MenuItemTranslatableContent', translation: { __typename: 'MenuItemTranslation', id: string, name: string, language: { __typename: 'LanguageDisplay', language: string } } | null, menuItem: { __typename: 'MenuItem', id: string, name: string } | null };
export type WarehouseFragment = { __typename: 'Warehouse', id: string, name: string };
export type WarehouseWithShippingFragment = { __typename: 'Warehouse', id: string, name: string, shippingZones: { __typename: 'ShippingZoneCountableConnection', edges: Array<{ __typename: 'ShippingZoneCountableEdge', node: { __typename: 'ShippingZone', id: string, name: string } }> } };
@ -8203,6 +8205,15 @@ export type UpdateShippingMethodTranslationsMutationVariables = Exact<{
export type UpdateShippingMethodTranslationsMutation = { __typename: 'Mutation', shippingPriceTranslate: { __typename: 'ShippingPriceTranslate', errors: Array<{ __typename: 'TranslationError', code: TranslationErrorCode, field: string | null, message: string | null }>, shippingMethod: { __typename: 'ShippingMethodType', id: string, name: string, description: any | null, translation: { __typename: 'ShippingMethodTranslation', id: string, name: string | null, description: any | null, language: { __typename: 'LanguageDisplay', language: string } } | null } | null } | null };
export type UpdateMenuItemTranslationsMutationVariables = Exact<{
id: Scalars['ID'];
input: NameTranslationInput;
language: LanguageCodeEnum;
}>;
export type UpdateMenuItemTranslationsMutation = { __typename: 'Mutation', menuItemTranslate: { __typename: 'MenuItemTranslate', errors: Array<{ __typename: 'TranslationError', field: string | null, message: string | null }>, menuItem: { __typename: 'MenuItem', id: string, name: string, translation: { __typename: 'MenuItemTranslation', id: string, name: string, language: { __typename: 'LanguageDisplay', language: string } } | null } | null } | null };
export type CategoryTranslationsQueryVariables = Exact<{
language: LanguageCodeEnum;
first?: InputMaybe<Scalars['Int']>;
@ -8291,6 +8302,17 @@ export type ShippingMethodTranslationsQueryVariables = Exact<{
export type ShippingMethodTranslationsQuery = { __typename: 'Query', translations: { __typename: 'TranslatableItemConnection', edges: Array<{ __typename: 'TranslatableItemEdge', node: { __typename: 'ProductTranslatableContent' } | { __typename: 'CollectionTranslatableContent' } | { __typename: 'CategoryTranslatableContent' } | { __typename: 'AttributeTranslatableContent' } | { __typename: 'AttributeValueTranslatableContent' } | { __typename: 'ProductVariantTranslatableContent' } | { __typename: 'PageTranslatableContent' } | { __typename: 'ShippingMethodTranslatableContent', id: string, name: string, description: any | null, shippingMethod: { __typename: 'ShippingMethodType', id: string } | null, translation: { __typename: 'ShippingMethodTranslation', id: string, name: string | null, description: any | null, language: { __typename: 'LanguageDisplay', code: LanguageCodeEnum, language: string } } | null } | { __typename: 'SaleTranslatableContent' } | { __typename: 'VoucherTranslatableContent' } | { __typename: 'MenuItemTranslatableContent' } }>, pageInfo: { __typename: 'PageInfo', endCursor: string | null, hasNextPage: boolean, hasPreviousPage: boolean, startCursor: string | null } } | null };
export type MenuItemTranslationsQueryVariables = Exact<{
language: LanguageCodeEnum;
first?: InputMaybe<Scalars['Int']>;
after?: InputMaybe<Scalars['String']>;
last?: InputMaybe<Scalars['Int']>;
before?: InputMaybe<Scalars['String']>;
}>;
export type MenuItemTranslationsQuery = { __typename: 'Query', translations: { __typename: 'TranslatableItemConnection', edges: Array<{ __typename: 'TranslatableItemEdge', node: { __typename: 'ProductTranslatableContent' } | { __typename: 'CollectionTranslatableContent' } | { __typename: 'CategoryTranslatableContent' } | { __typename: 'AttributeTranslatableContent' } | { __typename: 'AttributeValueTranslatableContent' } | { __typename: 'ProductVariantTranslatableContent' } | { __typename: 'PageTranslatableContent' } | { __typename: 'ShippingMethodTranslatableContent' } | { __typename: 'SaleTranslatableContent' } | { __typename: 'VoucherTranslatableContent' } | { __typename: 'MenuItemTranslatableContent', translation: { __typename: 'MenuItemTranslation', id: string, name: string, language: { __typename: 'LanguageDisplay', language: string } } | null, menuItem: { __typename: 'MenuItem', id: string, name: string } | null } }>, pageInfo: { __typename: 'PageInfo', endCursor: string | null, hasNextPage: boolean, hasPreviousPage: boolean, startCursor: string | null } } | null };
export type ProductTranslationDetailsQueryVariables = Exact<{
id: Scalars['ID'];
language: LanguageCodeEnum;
@ -8374,6 +8396,14 @@ export type ShippingMethodTranslationDetailsQueryVariables = Exact<{
export type ShippingMethodTranslationDetailsQuery = { __typename: 'Query', translation: { __typename: 'ProductTranslatableContent' } | { __typename: 'CollectionTranslatableContent' } | { __typename: 'CategoryTranslatableContent' } | { __typename: 'AttributeTranslatableContent' } | { __typename: 'AttributeValueTranslatableContent' } | { __typename: 'ProductVariantTranslatableContent' } | { __typename: 'PageTranslatableContent' } | { __typename: 'ShippingMethodTranslatableContent', id: string, name: string, description: any | null, shippingMethod: { __typename: 'ShippingMethodType', id: string } | null, translation: { __typename: 'ShippingMethodTranslation', id: string, name: string | null, description: any | null, language: { __typename: 'LanguageDisplay', code: LanguageCodeEnum, language: string } } | null } | { __typename: 'SaleTranslatableContent' } | { __typename: 'VoucherTranslatableContent' } | { __typename: 'MenuItemTranslatableContent' } | null };
export type MenuItemTranslationDetailsQueryVariables = Exact<{
id: Scalars['ID'];
language: LanguageCodeEnum;
}>;
export type MenuItemTranslationDetailsQuery = { __typename: 'Query', translation: { __typename: 'ProductTranslatableContent' } | { __typename: 'CollectionTranslatableContent' } | { __typename: 'CategoryTranslatableContent' } | { __typename: 'AttributeTranslatableContent' } | { __typename: 'AttributeValueTranslatableContent' } | { __typename: 'ProductVariantTranslatableContent' } | { __typename: 'PageTranslatableContent' } | { __typename: 'ShippingMethodTranslatableContent' } | { __typename: 'SaleTranslatableContent' } | { __typename: 'VoucherTranslatableContent' } | { __typename: 'MenuItemTranslatableContent', translation: { __typename: 'MenuItemTranslation', id: string, name: string, language: { __typename: 'LanguageDisplay', language: string } } | null, menuItem: { __typename: 'MenuItem', id: string, name: string } | null } | null };
export type UpdateMetadataMutationVariables = Exact<{
id: Scalars['ID'];
input: Array<MetadataInput> | MetadataInput;

View file

@ -253558,6 +253558,18 @@ exports[`Storyshots Views / Translations / Entity list default 1`] = `
Shipping methods
</span>
</button>
<button
class="MuiButtonBase-root-id MuiTab-root-id FilterTab-tabRoot-id MuiTab-textColorInherit-id"
role="tab"
tabindex="-1"
type="button"
>
<span
class="MuiTab-wrapper-id FilterTab-tabLabel-id"
>
Menu items
</span>
</button>
</div>
</div>
</div>

View file

@ -24,6 +24,7 @@ const props: TranslationsEntitiesListPageProps = {
onSalesTabClick: () => undefined,
onShippingMethodsTabClick: () => undefined,
onVouchersTabClick: () => undefined,
onMenuItemsTabClick: () => undefined,
},
language: {
__typename: "LanguageDisplay",

View file

@ -26,6 +26,7 @@ export interface TranslationsEntitiesFilters {
onPagesTabClick: () => void;
onAttributesTabClick: () => void;
onShippingMethodsTabClick: () => void;
onMenuItemsTabClick: () => void;
}
export type TranslationsEntitiesListFilterTab = keyof typeof TranslatableEntities;
@ -39,6 +40,7 @@ const tabs: TranslationsEntitiesListFilterTab[] = [
"pages",
"attributes",
"shippingMethods",
"menuItems",
];
const TranslationsEntitiesListPage: React.FC<TranslationsEntitiesListPageProps> = props => {
@ -126,6 +128,13 @@ const TranslationsEntitiesListPage: React.FC<TranslationsEntitiesListPageProps>
})}
onClick={filters.onShippingMethodsTabClick}
/>
<FilterTab
label={intl.formatMessage({
id: "AcMzwj",
defaultMessage: "Menu items",
})}
onClick={filters.onMenuItemsTabClick}
/>
</FilterTabs>
{children}
</Card>

View file

@ -0,0 +1,104 @@
import { Backlink } from "@saleor/components/Backlink";
import Container from "@saleor/components/Container";
import LanguageSwitch from "@saleor/components/LanguageSwitch";
import PageHeader from "@saleor/components/PageHeader";
import { LanguageCodeEnum, MenuItemTranslationFragment } from "@saleor/graphql";
import { commonMessages, sectionNames } from "@saleor/intl";
import { getStringOrPlaceholder } from "@saleor/misc";
import {
TranslationInputFieldName,
TranslationsEntitiesPageProps,
} from "@saleor/translations/types";
import {
languageEntitiesUrl,
languageEntityUrl,
TranslatableEntities,
} from "@saleor/translations/urls";
import React from "react";
import { useIntl } from "react-intl";
import TranslationFields from "../TranslationFields";
export interface TranslationsMenuItemPageProps
extends TranslationsEntitiesPageProps {
data: MenuItemTranslationFragment;
}
const TranslationsMenuItemPage: React.FC<TranslationsMenuItemPageProps> = ({
translationId,
activeField,
disabled,
languageCode,
languages,
data,
saveButtonState,
onDiscard,
onEdit,
onSubmit,
}) => {
const intl = useIntl();
return (
<Container>
<Backlink
href={languageEntitiesUrl(languageCode, {
tab: TranslatableEntities.menuItems,
})}
>
{intl.formatMessage(sectionNames.translations)}
</Backlink>
<PageHeader
title={intl.formatMessage(
{
id: "IOshTA",
defaultMessage:
'Translation MenuItem "{menuItemName}" - {languageCode}',
description: "header",
},
{
languageCode,
menuItemName: getStringOrPlaceholder(data?.menuItem.name),
},
)}
>
<LanguageSwitch
currentLanguage={LanguageCodeEnum[languageCode]}
languages={languages}
getLanguageUrl={lang =>
languageEntityUrl(
lang,
TranslatableEntities.menuItems,
translationId,
)
}
/>
</PageHeader>
<TranslationFields
activeField={activeField}
disabled={disabled}
initialState={true}
title={intl.formatMessage(commonMessages.generalInformations)}
fields={[
{
displayName: intl.formatMessage({
id: "0Vyr8h",
defaultMessage: "Name",
description: "menu item name",
}),
name: TranslationInputFieldName.name,
translation: data?.translation?.name || null,
type: "short" as "short",
value: data?.menuItem.name,
},
]}
saveButtonState={saveButtonState}
richTextResetKey={languageCode}
onEdit={onEdit}
onDiscard={onDiscard}
onSubmit={onSubmit}
/>
</Container>
);
};
TranslationsMenuItemPage.displayName = "TranslationsMenuItemPage";
export default TranslationsMenuItemPage;

View file

@ -0,0 +1,2 @@
export { default } from "./TranslationsMenuItemPage";
export * from "./TranslationsMenuItemPage";

View file

@ -23,6 +23,7 @@ import TranslationsCollectionsComponent, {
} from "./views/TranslationsCollections";
import TranslationsEntitiesComponent from "./views/TranslationsEntities";
import TranslationsLanguageList from "./views/TranslationsLanguageList";
import TranslationsMenuItemComponent from "./views/TranslationsMenuItem";
import TranslationsPagesComponent, {
TranslationsPagesQueryParams,
} from "./views/TranslationsPages";
@ -212,6 +213,22 @@ const TranslationsShippingMethod: React.FC<TranslationsEntityRouteProps> = ({
/>
);
};
const TranslationsMenuItem: React.FC<TranslationsEntityRouteProps> = ({
location,
match,
}) => {
const qs = parseQs(location.search.substr(1));
const params: TranslationsShippingMethodQueryParams = {
activeField: qs.activeField,
};
return (
<TranslationsMenuItemComponent
id={decodeURIComponent(match.params.id)}
languageCode={LanguageCodeEnum[match.params.languageCode]}
params={params}
/>
);
};
const TranslationsRouter: React.FC = () => {
const intl = useIntl();
@ -313,6 +330,15 @@ const TranslationsRouter: React.FC = () => {
)}
component={TranslationsShippingMethod}
/>
<Route
exact
path={languageEntityPath(
":languageCode",
TranslatableEntities.menuItems,
":id",
)}
component={TranslationsMenuItem}
/>
</Switch>
</>
);

View file

@ -261,3 +261,29 @@ export const updateShippingMethodTranslations = gql`
}
}
`;
export const updateMethodItemTranslations = gql`
mutation UpdateMenuItemTranslations(
$id: ID!
$input: NameTranslationInput!
$language: LanguageCodeEnum!
) {
menuItemTranslate(id: $id, input: $input, languageCode: $language) {
errors {
field
message
}
menuItem {
id
name
translation(languageCode: $language) {
id
language {
language
}
name
}
}
}
}
`;

View file

@ -216,6 +216,33 @@ export const shippingMethodTranslations = gql`
}
`;
export const menuItemTranslations = gql`
query MenuItemTranslations(
$language: LanguageCodeEnum!
$first: Int
$after: String
$last: Int
$before: String
) {
translations(
kind: MENU_ITEM
before: $before
after: $after
first: $first
last: $last
) {
edges {
node {
...MenuItemTranslation
}
}
pageInfo {
...PageInfo
}
}
}
`;
export const productTranslationDetails = gql`
query ProductTranslationDetails($id: ID!, $language: LanguageCodeEnum!) {
translation(kind: PRODUCT, id: $id) {
@ -313,3 +340,11 @@ export const shippingMethodTranslationDetails = gql`
}
}
`;
export const menuItemTranslationDetails = gql`
query MenuItemTranslationDetails($id: ID!, $language: LanguageCodeEnum!) {
translation(kind: MENU_ITEM, id: $id) {
...MenuItemTranslation
}
}
`;

View file

@ -14,6 +14,7 @@ export enum TranslatableEntities {
pages = "pages",
attributes = "attributes",
shippingMethods = "shippingMethods",
menuItems = "menuItems",
}
const translationsSection = "/translations/";

View file

@ -0,0 +1,56 @@
import { useMenuItemTranslationsQuery } from "@saleor/graphql";
import usePaginator, { PaginatorContext } from "@saleor/hooks/usePaginator";
import TranslationsEntitiesList from "@saleor/translations/components/TranslationsEntitiesList";
import {
languageEntityUrl,
TranslatableEntities,
} from "@saleor/translations/urls";
import { mapEdgesToItems } from "@saleor/utils/maps";
import React from "react";
import { TranslationsEntityListProps } from "./types";
import { sumCompleted } from "./utils";
const TranslationsMenuItemList: React.FC<TranslationsEntityListProps> = ({
params,
variables,
}) => {
const { data, loading } = useMenuItemTranslationsQuery({
displayLoader: true,
variables,
});
const paginationValues = usePaginator({
pageInfo: data?.translations?.pageInfo,
paginationState: variables,
queryString: params,
});
return (
<PaginatorContext.Provider value={paginationValues}>
<TranslationsEntitiesList
disabled={loading}
entities={mapEdgesToItems(data?.translations)?.map(
node =>
node.__typename === "MenuItemTranslatableContent" && {
completion: {
current: sumCompleted([node.translation?.name]),
max: 1,
},
id: node?.menuItem.id,
name: node?.menuItem.name,
},
)}
getRowHref={id =>
languageEntityUrl(
variables.language,
TranslatableEntities.menuItems,
id,
)
}
/>
</PaginatorContext.Provider>
);
};
export default TranslationsMenuItemList;

View file

@ -11,6 +11,7 @@ import { LanguageEntitiesUrlQueryParams, TranslatableEntities } from "../urls";
import TranslationsAttributeList from "./EntityLists/TranslationsAttributeList";
import TranslationsCategoryList from "./EntityLists/TranslationsCategoryList";
import TranslationsCollectionList from "./EntityLists/TranslationsCollectionList";
import TranslationsMenuItemList from "./EntityLists/TranslationsMenuItemList";
import TranslationsPageList from "./EntityLists/TranslationsPageList";
import TranslationsProductList from "./EntityLists/TranslationsProductList";
import TranslationsSaleList from "./EntityLists/TranslationsSaleList";
@ -96,6 +97,13 @@ const TranslationsEntities: React.FC<TranslationsEntitiesProps> = ({
tab: TranslatableEntities.vouchers,
}),
),
onMenuItemsTabClick: () =>
navigate(
"?" +
stringifyQs({
tab: TranslatableEntities.menuItems,
}),
),
};
const lang = maybe(() =>
shop.languages.find(languageFromList => languageFromList.code === language),
@ -138,6 +146,8 @@ const TranslationsEntities: React.FC<TranslationsEntitiesProps> = ({
params={params}
variables={queryVariables}
/>
) : params.tab === "menuItems" ? (
<TranslationsMenuItemList params={params} variables={queryVariables} />
) : null}
</TranslationsEntitiesListPage>
);

View file

@ -0,0 +1,107 @@
import {
LanguageCodeEnum,
useMenuItemTranslationDetailsQuery,
useUpdateMenuItemTranslationsMutation,
} from "@saleor/graphql";
import useNavigator from "@saleor/hooks/useNavigator";
import useNotifier from "@saleor/hooks/useNotifier";
import useShop from "@saleor/hooks/useShop";
import { commonMessages } from "@saleor/intl";
import { extractMutationErrors } from "@saleor/misc";
import { stringifyQs } from "@saleor/utils/urls";
import React from "react";
import { useIntl } from "react-intl";
import TranslationsMenuItemPage from "../components/TranslationsMenuItemPage";
import { TranslationField, TranslationInputFieldName } from "../types";
import { getParsedTranslationInputData } from "../utils";
export interface TranslationsMenuItemQueryParams {
activeField: string;
}
export interface TranslationsMenuItemProps {
id: string;
languageCode: LanguageCodeEnum;
params: TranslationsMenuItemQueryParams;
}
const TranslationsMenuItem: React.FC<TranslationsMenuItemProps> = ({
id,
languageCode,
params,
}) => {
const navigate = useNavigator();
const notify = useNotifier();
const shop = useShop();
const intl = useIntl();
const menuItemTranslations = useMenuItemTranslationDetailsQuery({
variables: { id, language: languageCode },
});
const [
updateTranslations,
updateTranslationsOpts,
] = useUpdateMenuItemTranslationsMutation({
onCompleted: data => {
if (data.menuItemTranslate.errors.length === 0) {
menuItemTranslations.refetch();
notify({
status: "success",
text: intl.formatMessage(commonMessages.savedChanges),
});
navigate("?", { replace: true });
}
},
});
const onEdit = (field: string) =>
navigate(
"?" +
stringifyQs({
activeField: field,
}),
{ replace: true },
);
const onDiscard = () => {
navigate("?", { replace: true });
};
const handleSubmit = (
{ name: fieldName }: TranslationField<TranslationInputFieldName>,
data: string,
) =>
extractMutationErrors(
updateTranslations({
variables: {
id,
input: getParsedTranslationInputData({ fieldName, data }),
language: languageCode,
},
}),
);
const translation = menuItemTranslations?.data?.translation;
return (
<TranslationsMenuItemPage
translationId={id}
activeField={params.activeField}
disabled={menuItemTranslations.loading || updateTranslationsOpts.loading}
languages={shop?.languages || []}
languageCode={languageCode}
saveButtonState={updateTranslationsOpts.status}
onEdit={onEdit}
onDiscard={onDiscard}
onSubmit={handleSubmit}
data={
translation?.__typename === "MenuItemTranslatableContent"
? translation
: null
}
/>
);
};
TranslationsMenuItem.displayName = "TranslationsMenuItem";
export default TranslationsMenuItem;