Add text attribute for product and page translations (#1276)

* initial commit

* Refactor translation components

* Wire up products

* Update types

* add logic for withChoices flag

* refactoring

* fixing errors

* change in intl.ts

* amended Changelog

* fix formatting

* fixing stuff

* Update translations

* remove unused declaration

* add changes

* Fixes

* Add newline

* Update displayName

* Update snapshots

Co-authored-by: Jakub Majorek <majorek.jakub@gmail.com>
This commit is contained in:
Kamil Pastuszka 2021-08-09 16:59:12 +02:00 committed by GitHub
parent 8d2021675e
commit 034eea0dcd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
38 changed files with 781 additions and 298 deletions

View file

@ -73,6 +73,7 @@ All notable, unreleased changes to this project will be documented in this file.
- Add Metadata for Sale & Voucher - #7653 by @piotrgrundas
- Add variant create options dialog - #1238 by @orzechdev
- Fix for errors on changing channel availability - #1264 by @krzysztofwolski
- Add text attribute for product and page translations - #1276 by @kamilpastuszka
# 2.11.1

View file

@ -6668,6 +6668,9 @@
"context": "independent of any particular day, eg. 11:35",
"string": "Time"
},
"src_dot_translationAttributes": {
"string": "Attributes"
},
"src_dot_translations": {
"context": "translations section name",
"string": "Translations"
@ -6688,6 +6691,21 @@
"src_dot_translations_dot_components_dot_TranslationFields_dot_3793796047": {
"string": "No translation yet"
},
"src_dot_translations_dot_components_dot_TranslationsAttributesPage_dot_1567737068": {
"context": "attribute values",
"string": "Value {number}"
},
"src_dot_translations_dot_components_dot_TranslationsAttributesPage_dot_2642976392": {
"string": "Attribute Name"
},
"src_dot_translations_dot_components_dot_TranslationsAttributesPage_dot_884093025": {
"context": "header",
"string": "Translation Attribute \"{attribute}\" - {languageCode}"
},
"src_dot_translations_dot_components_dot_TranslationsAttributesPage_dot_values": {
"context": "section name",
"string": "Values"
},
"src_dot_translations_dot_components_dot_TranslationsCategoriesPage_dot_1214235329": {
"string": "Category Name"
},
@ -6790,28 +6808,13 @@
"src_dot_translations_dot_components_dot_TranslationsPagesPage_dot_3468022343": {
"string": "Search Engine Preview"
},
"src_dot_translations_dot_components_dot_TranslationsPagesPage_dot_4165966072": {
"context": "attribute list",
"string": "Attribute {number}"
},
"src_dot_translations_dot_components_dot_TranslationsPagesPage_dot_432157284": {
"string": "Page Title"
},
"src_dot_translations_dot_components_dot_TranslationsProductTypesPage_dot_1567737068": {
"context": "attribute values",
"string": "Value {number}"
},
"src_dot_translations_dot_components_dot_TranslationsProductTypesPage_dot_2642976392": {
"string": "Attribute Name"
},
"src_dot_translations_dot_components_dot_TranslationsProductTypesPage_dot_3495336243": {
"context": "attribute richtext value",
"string": "Text"
},
"src_dot_translations_dot_components_dot_TranslationsProductTypesPage_dot_884093025": {
"context": "header",
"string": "Translation Attribute \"{attribute}\" - {languageCode}"
},
"src_dot_translations_dot_components_dot_TranslationsProductTypesPage_dot_values": {
"context": "section name",
"string": "Values"
},
"src_dot_translations_dot_components_dot_TranslationsProductsPage_dot_1406947243": {
"string": "Search Engine Description"
},
@ -6831,6 +6834,10 @@
"src_dot_translations_dot_components_dot_TranslationsProductsPage_dot_3468022343": {
"string": "Search Engine Preview"
},
"src_dot_translations_dot_components_dot_TranslationsProductsPage_dot_4165966072": {
"context": "attribute list",
"string": "Attribute {number}"
},
"src_dot_translations_dot_components_dot_TranslationsSalesPage_dot_3731955064": {
"context": "header",
"string": "Translation Sale \"{saleName}\" - {languageCode}"

View file

@ -44,6 +44,7 @@ export const collectionTranslationFragment = gql`
}
}
`;
export const productTranslationFragment = gql`
fragment ProductTranslationFragment on ProductTranslatableContent {
product {
@ -55,14 +56,31 @@ export const productTranslationFragment = gql`
}
translation(languageCode: $language) {
id
seoTitle
seoDescription
name
description
language {
code
language
}
}
attributeValues {
id
name
seoDescription
seoTitle
richText
attributeValue {
id
}
translation(languageCode: $language) {
id
name
richText
language {
code
language
}
}
}
}
`;
@ -139,6 +157,23 @@ export const pageTranslationFragment = gql`
language
}
}
attributeValues {
id
name
richText
attributeValue {
id
}
translation(languageCode: $language) {
id
name
richText
language {
code
language
}
}
}
}
`;
export const pageTranslatableFragment = gql`
@ -148,7 +183,6 @@ export const pageTranslatableFragment = gql`
seoDescription
seoTitle
title
translation(languageCode: $language) {
id
content
@ -188,6 +222,8 @@ export const attributeChoicesTranslationFragment = gql`
export const attributeTranslationFragment = gql`
fragment AttributeTranslationFragment on AttributeTranslatableContent {
id
name
translation(languageCode: $language) {
id
name
@ -203,6 +239,30 @@ export const attributeTranslationFragment = gql`
export const attributeTranslationDetailsFragment = gql`
${attributeChoicesTranslationFragment}
fragment AttributeTranslationDetailsFragment on AttributeTranslatableContent {
translation(languageCode: $language) {
id
name
}
attribute {
id
name
inputType
withChoices
choices(
first: $firstValues
after: $afterValues
last: $lastValues
before: $beforeValues
) {
...AttributeChoicesTranslationFragment
}
}
}
`;
export const attributeValueTranslatableContentFragment = gql`
${attributeChoicesTranslationFragment}
fragment AttributeValueTranslatableContentFragment on AttributeTranslatableContent {
translation(languageCode: $language) {
id
name

View file

@ -56,6 +56,7 @@ export interface AttributeTranslationDetailsFragment_attribute {
id: string;
name: string | null;
inputType: AttributeInputTypeEnum | null;
withChoices: boolean;
choices: AttributeTranslationDetailsFragment_attribute_choices | null;
}

View file

@ -24,6 +24,8 @@ export interface AttributeTranslationFragment_attribute {
export interface AttributeTranslationFragment {
__typename: "AttributeTranslatableContent";
id: string;
name: string;
translation: AttributeTranslationFragment_translation | null;
attribute: AttributeTranslationFragment_attribute | null;
}

View file

@ -0,0 +1,66 @@
/* tslint:disable */
/* eslint-disable */
// @generated
// This file was automatically generated and should not be edited.
import { AttributeInputTypeEnum } from "./../../types/globalTypes";
// ====================================================
// GraphQL fragment: AttributeValueTranslatableContentFragment
// ====================================================
export interface AttributeValueTranslatableContentFragment_translation {
__typename: "AttributeTranslation";
id: string;
name: string;
}
export interface AttributeValueTranslatableContentFragment_attribute_choices_pageInfo {
__typename: "PageInfo";
endCursor: string | null;
hasNextPage: boolean;
hasPreviousPage: boolean;
startCursor: string | null;
}
export interface AttributeValueTranslatableContentFragment_attribute_choices_edges_node_translation {
__typename: "AttributeValueTranslation";
id: string;
name: string;
richText: any | null;
}
export interface AttributeValueTranslatableContentFragment_attribute_choices_edges_node {
__typename: "AttributeValue";
id: string;
name: string | null;
richText: any | null;
inputType: AttributeInputTypeEnum | null;
translation: AttributeValueTranslatableContentFragment_attribute_choices_edges_node_translation | null;
}
export interface AttributeValueTranslatableContentFragment_attribute_choices_edges {
__typename: "AttributeValueCountableEdge";
cursor: string;
node: AttributeValueTranslatableContentFragment_attribute_choices_edges_node;
}
export interface AttributeValueTranslatableContentFragment_attribute_choices {
__typename: "AttributeValueCountableConnection";
pageInfo: AttributeValueTranslatableContentFragment_attribute_choices_pageInfo;
edges: AttributeValueTranslatableContentFragment_attribute_choices_edges[];
}
export interface AttributeValueTranslatableContentFragment_attribute {
__typename: "Attribute";
id: string;
name: string | null;
inputType: AttributeInputTypeEnum | null;
choices: AttributeValueTranslatableContentFragment_attribute_choices | null;
}
export interface AttributeValueTranslatableContentFragment {
__typename: "AttributeTranslatableContent";
translation: AttributeValueTranslatableContentFragment_translation | null;
attribute: AttributeValueTranslatableContentFragment_attribute | null;
}

View file

@ -34,8 +34,37 @@ export interface PageTranslationFragment_translation {
language: PageTranslationFragment_translation_language;
}
export interface PageTranslationFragment_attributeValues_attributeValue {
__typename: "AttributeValue";
id: string;
}
export interface PageTranslationFragment_attributeValues_translation_language {
__typename: "LanguageDisplay";
code: LanguageCodeEnum;
language: string;
}
export interface PageTranslationFragment_attributeValues_translation {
__typename: "AttributeValueTranslation";
id: string;
name: string;
richText: any | null;
language: PageTranslationFragment_attributeValues_translation_language;
}
export interface PageTranslationFragment_attributeValues {
__typename: "AttributeValueTranslatableContent";
id: string;
name: string;
richText: any | null;
attributeValue: PageTranslationFragment_attributeValues_attributeValue | null;
translation: PageTranslationFragment_attributeValues_translation | null;
}
export interface PageTranslationFragment {
__typename: "PageTranslatableContent";
page: PageTranslationFragment_page | null;
translation: PageTranslationFragment_translation | null;
attributeValues: PageTranslationFragment_attributeValues[];
}

View file

@ -27,15 +27,44 @@ export interface ProductTranslationFragment_translation_language {
export interface ProductTranslationFragment_translation {
__typename: "ProductTranslation";
id: string;
seoTitle: string | null;
seoDescription: string | null;
name: string | null;
description: any | null;
language: ProductTranslationFragment_translation_language;
name: string | null;
seoDescription: string | null;
seoTitle: string | null;
}
export interface ProductTranslationFragment_attributeValues_attributeValue {
__typename: "AttributeValue";
id: string;
}
export interface ProductTranslationFragment_attributeValues_translation_language {
__typename: "LanguageDisplay";
code: LanguageCodeEnum;
language: string;
}
export interface ProductTranslationFragment_attributeValues_translation {
__typename: "AttributeValueTranslation";
id: string;
name: string;
richText: any | null;
language: ProductTranslationFragment_attributeValues_translation_language;
}
export interface ProductTranslationFragment_attributeValues {
__typename: "AttributeValueTranslatableContent";
id: string;
name: string;
richText: any | null;
attributeValue: ProductTranslationFragment_attributeValues_attributeValue | null;
translation: ProductTranslationFragment_attributeValues_translation | null;
}
export interface ProductTranslationFragment {
__typename: "ProductTranslatableContent";
product: ProductTranslationFragment_product | null;
translation: ProductTranslationFragment_translation | null;
attributeValues: ProductTranslationFragment_attributeValues[];
}

View file

@ -99,6 +99,9 @@ export const commonMessages = defineMessages({
summary: {
defaultMessage: "Summary"
},
translationAttributes: {
defaultMessage: "Attributes"
},
unauthorizedDashboardAccess: {
defaultMessage: "Only staff users can access the dashboard"
},

View file

@ -18,7 +18,7 @@ const props: TranslationsEntitiesListPageProps = {
onCategoriesTabClick: () => undefined,
onCollectionsTabClick: () => undefined,
onPagesTabClick: () => undefined,
onProductTypesTabClick: () => undefined,
onAttributesTabClick: () => undefined,
onProductsTabClick: () => undefined,
onSalesTabClick: () => undefined,
onShippingMethodsTabClick: () => undefined,

View file

@ -15,6 +15,7 @@ import Skeleton from "@saleor/components/Skeleton";
import TablePagination from "@saleor/components/TablePagination";
import { buttonMessages } from "@saleor/intl";
import { makeStyles } from "@saleor/macaw-ui";
import { TranslationField } from "@saleor/translations/types";
import { ListProps } from "@saleor/types";
import classNames from "classnames";
import React from "react";
@ -24,14 +25,6 @@ import TranslationFieldsLong from "./TranslationFieldsLong";
import TranslationFieldsRich from "./TranslationFieldsRich";
import TranslationFieldsShort from "./TranslationFieldsShort";
export interface TranslationField {
displayName: string;
name: string;
translation: string;
type: "short" | "long" | "rich";
value: string;
}
type Pagination = Pick<
ListProps,
Exclude<keyof ListProps, "onRowClick" | "disabled">
@ -47,7 +40,7 @@ export interface TranslationFieldsProps {
pagination?: Pagination;
onEdit: (field: string) => void;
onDiscard: () => void;
onSubmit: (field: string, data: string | OutputData) => void;
onSubmit: (field: TranslationField, data: string | OutputData) => void;
}
const useStyles = makeStyles(
@ -215,7 +208,7 @@ const TranslationFields: React.FC<TranslationFieldsProps> = props => {
initial={field.translation}
saveButtonState={saveButtonState}
onDiscard={onDiscard}
onSubmit={data => onSubmit(field.name, data)}
onSubmit={data => onSubmit(field, data)}
/>
) : field.type === "long" ? (
<TranslationFieldsLong
@ -224,7 +217,7 @@ const TranslationFields: React.FC<TranslationFieldsProps> = props => {
initial={field.translation}
saveButtonState={saveButtonState}
onDiscard={onDiscard}
onSubmit={data => onSubmit(field.name, data)}
onSubmit={data => onSubmit(field, data)}
/>
) : (
<TranslationFieldsRich
@ -233,7 +226,7 @@ const TranslationFields: React.FC<TranslationFieldsProps> = props => {
initial={field.translation}
saveButtonState={saveButtonState}
onDiscard={onDiscard}
onSubmit={data => onSubmit(field.name, data)}
onSubmit={data => onSubmit(field, data)}
/>
)
) : (

View file

@ -7,16 +7,16 @@ import { AttributeTranslationDetailsFragment } from "@saleor/fragments/types/Att
import { commonMessages, sectionNames } from "@saleor/intl";
import { Backlink } from "@saleor/macaw-ui";
import { getStringOrPlaceholder } from "@saleor/misc";
import { TranslationsEntitiesPageProps } from "@saleor/translations/types";
import {
TranslationField,
TranslationsEntitiesPageProps
} from "@saleor/translations/types";
import { ListSettings } from "@saleor/types";
import React from "react";
import { defineMessages, useIntl } from "react-intl";
import {
AttributeInputTypeEnum,
LanguageCodeEnum
} from "../../../types/globalTypes";
import TranslationFields, { TranslationField } from "../TranslationFields";
import { LanguageCodeEnum } from "../../../types/globalTypes";
import TranslationFields from "../TranslationFields";
export const messages = defineMessages({
values: {
@ -25,7 +25,7 @@ export const messages = defineMessages({
}
});
export interface TranslationsProductTypesPageProps
export interface TranslationsAttributesPageProps
extends TranslationsEntitiesPageProps {
data: AttributeTranslationDetailsFragment;
settings?: ListSettings;
@ -44,7 +44,7 @@ export const fieldNames = {
richTextValue: "attributeRichTextValue"
};
const TranslationsProductTypesPage: React.FC<TranslationsProductTypesPageProps> = ({
const TranslationsAttributesPage: React.FC<TranslationsAttributesPageProps> = ({
activeField,
disabled,
languages,
@ -64,6 +64,8 @@ const TranslationsProductTypesPage: React.FC<TranslationsProductTypesPageProps>
}) => {
const intl = useIntl();
const withChoices = data?.attribute?.withChoices;
return (
<Container>
<Backlink onClick={onBack}>
@ -110,64 +112,50 @@ const TranslationsProductTypesPage: React.FC<TranslationsProductTypesPageProps>
onSubmit={onSubmit}
/>
<CardSpacer />
<TranslationFields
activeField={activeField}
disabled={disabled}
initialState={true}
title={intl.formatMessage(messages.values)}
fields={
data?.attribute?.choices?.edges?.map(
({ node: attributeValue }, attributeValueIndex) => {
const isRichText =
attributeValue?.inputType === AttributeInputTypeEnum.RICH_TEXT;
const displayName = isRichText
? intl.formatMessage({
defaultMessage: "Text",
description: "attribute richtext value"
})
: intl.formatMessage(
{
defaultMessage: "Value {number}",
description: "attribute values"
},
{
number: attributeValueIndex + 1
}
);
{data?.attribute?.choices.edges.length > 0 && withChoices && (
<TranslationFields
activeField={activeField}
disabled={disabled}
initialState={true}
title={intl.formatMessage(messages.values)}
fields={
data?.attribute?.choices?.edges?.map(
({ node: attributeValue }, attributeValueIndex) => {
const displayName = intl.formatMessage(
{
defaultMessage: "Value {number}",
description: "attribute values"
},
{
number: attributeValueIndex + 1
}
);
return {
displayName,
name: `${
isRichText ? fieldNames.richTextValue : fieldNames.value
}:${attributeValue.id}`,
translation:
(isRichText
? attributeValue?.translation?.richText
: attributeValue?.translation?.name) || null,
type: (isRichText
? "rich"
: "short") as TranslationField["type"],
value: isRichText
? attributeValue?.richText
: attributeValue?.name
};
}
) || []
}
saveButtonState={saveButtonState}
pagination={{
settings,
onUpdateListSettings,
pageInfo,
onNextPage,
onPreviousPage
}}
onEdit={onEdit}
onDiscard={onDiscard}
onSubmit={onSubmit}
/>
return {
displayName,
name: `${fieldNames.value}:${attributeValue.id}`,
translation: attributeValue?.translation?.name || null,
type: "short" as TranslationField["type"],
value: attributeValue?.name
};
}
) || []
}
saveButtonState={saveButtonState}
pagination={{
settings,
onUpdateListSettings,
pageInfo,
onNextPage,
onPreviousPage
}}
onEdit={onEdit}
onDiscard={onDiscard}
onSubmit={onSubmit}
/>
)}
</Container>
);
};
TranslationsProductTypesPage.displayName = "TranslationsProductTypesPage";
export default TranslationsProductTypesPage;
TranslationsAttributesPage.displayName = "TranslationsAttributesPage";
export default TranslationsAttributesPage;

View file

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

View file

@ -25,7 +25,7 @@ export interface TranslationsEntitiesFilters {
onSalesTabClick: () => void;
onVouchersTabClick: () => void;
onPagesTabClick: () => void;
onProductTypesTabClick: () => void;
onAttributesTabClick: () => void;
onShippingMethodsTabClick: () => void;
}
@ -38,7 +38,7 @@ const tabs: TranslationsEntitiesListFilterTab[] = [
"sales",
"vouchers",
"pages",
"productTypes",
"attributes",
"shippingMethods"
];
@ -109,7 +109,7 @@ const TranslationsEntitiesListPage: React.FC<TranslationsEntitiesListPageProps>
label={intl.formatMessage({
defaultMessage: "Attributes"
})}
onClick={filters.onProductTypesTabClick}
onClick={filters.onAttributesTabClick}
/>
<FilterTab
label={intl.formatMessage({

View file

@ -19,6 +19,7 @@ import TranslationFields from "../TranslationFields";
export interface TranslationsPagesPageProps
extends TranslationsEntitiesPageProps {
data: PageTranslationFragment;
onAttributeValueSubmit: TranslationsEntitiesPageProps["onSubmit"];
}
const TranslationsPagesPage: React.FC<TranslationsPagesPageProps> = ({
@ -32,7 +33,8 @@ const TranslationsPagesPage: React.FC<TranslationsPagesPageProps> = ({
onDiscard,
onEdit,
onLanguageChange,
onSubmit
onSubmit,
onAttributeValueSubmit
}) => {
const intl = useIntl();
@ -90,6 +92,7 @@ const TranslationsPagesPage: React.FC<TranslationsPagesPageProps> = ({
onDiscard={onDiscard}
onSubmit={onSubmit}
/>
<CardSpacer />
<TranslationFields
activeField={activeField}
@ -123,6 +126,40 @@ const TranslationsPagesPage: React.FC<TranslationsPagesPageProps> = ({
onDiscard={onDiscard}
onSubmit={onSubmit}
/>
<CardSpacer />
{data?.attributeValues?.length > 0 && (
<>
<TranslationFields
activeField={activeField}
disabled={disabled}
initialState={true}
title={intl.formatMessage(commonMessages.translationAttributes)}
fields={
data.attributeValues.map((attrVal, i) => ({
id: attrVal.attributeValue.id,
displayName: intl.formatMessage(
{
defaultMessage: "Attribute {number}",
description: "attribute list"
},
{
number: i + 1
}
),
name: attrVal?.name,
translation: attrVal?.translation?.richText || null,
type: "rich" as "rich",
value: attrVal?.richText
})) || []
}
saveButtonState={saveButtonState}
onEdit={onEdit}
onDiscard={onDiscard}
onSubmit={onAttributeValueSubmit}
/>
<CardSpacer />
</>
)}
</Container>
);
};

View file

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

View file

@ -19,6 +19,7 @@ import TranslationFields from "../TranslationFields";
export interface TranslationsProductsPageProps
extends TranslationsEntitiesPageProps {
data: ProductTranslationFragment;
onAttributeValueSubmit: TranslationsEntitiesPageProps["onSubmit"];
}
const TranslationsProductsPage: React.FC<TranslationsProductsPageProps> = ({
@ -32,7 +33,8 @@ const TranslationsProductsPage: React.FC<TranslationsProductsPageProps> = ({
onDiscard,
onEdit,
onLanguageChange,
onSubmit
onSubmit,
onAttributeValueSubmit
}) => {
const intl = useIntl();
@ -123,6 +125,40 @@ const TranslationsProductsPage: React.FC<TranslationsProductsPageProps> = ({
onDiscard={onDiscard}
onSubmit={onSubmit}
/>
<CardSpacer />
{data?.attributeValues?.length > 0 && (
<>
<TranslationFields
activeField={activeField}
disabled={disabled}
initialState={true}
title={intl.formatMessage(commonMessages.translationAttributes)}
fields={
data.attributeValues.map((attrVal, i) => ({
id: attrVal.attributeValue.id,
displayName: intl.formatMessage(
{
defaultMessage: "Attribute {number}",
description: "attribute list"
},
{
number: i + 1
}
),
name: attrVal?.name,
translation: attrVal?.translation?.richText || null,
type: "rich" as "rich",
value: attrVal?.richText
})) || []
}
saveButtonState={saveButtonState}
onEdit={onEdit}
onDiscard={onDiscard}
onSubmit={onAttributeValueSubmit}
/>
<CardSpacer />
</>
)}
</Container>
);
};

View file

@ -12,6 +12,9 @@ import {
languageListPath,
TranslatableEntities
} from "./urls";
import TranslationsAttributesComponent, {
TranslationsAttributesQueryParams
} from "./views/TranslationsAttributes";
import TranslationsCategoriesComponent, {
TranslationsCategoriesQueryParams
} from "./views/TranslationsCategories";
@ -26,9 +29,6 @@ import TranslationsPagesComponent, {
import TranslationsProductsComponent, {
TranslationsProductsQueryParams
} from "./views/TranslationsProducts";
import TranslationsProductTypesComponent, {
TranslationsProductTypesQueryParams
} from "./views/TranslationsProductTypes";
import TranslationsSaleComponent, {
TranslationsSalesQueryParams
} from "./views/TranslationsSales";
@ -155,16 +155,16 @@ const TranslationsPages: React.FC<TranslationsEntityRouteProps> = ({
/>
);
};
const TranslationsProductTypes: React.FC<TranslationsEntityRouteProps> = ({
const TranslationsAttributes: React.FC<TranslationsEntityRouteProps> = ({
location,
match
}) => {
const qs = parseQs(location.search.substr(1));
const params: TranslationsProductTypesQueryParams = {
const params: TranslationsAttributesQueryParams = {
activeField: qs.activeField
};
return (
<TranslationsProductTypesComponent
<TranslationsAttributesComponent
id={decodeURIComponent(match.params.id)}
languageCode={LanguageCodeEnum[match.params.languageCode]}
params={params}
@ -263,10 +263,10 @@ const TranslationsRouter: React.FC = () => {
exact
path={languageEntityPath(
":languageCode",
TranslatableEntities.productTypes,
TranslatableEntities.attributes,
":id"
)}
component={TranslationsProductTypes}
component={TranslationsAttributes}
/>
<Route
exact

View file

@ -276,6 +276,7 @@ const updateAttributeValueTranslations = gql`
attributeValue {
id
name
richText
translation(languageCode: $language) {
id
name

View file

@ -2,6 +2,31 @@ import { OutputData } from "@editorjs/editorjs";
import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton";
import { ShopInfo_shop_languages } from "@saleor/components/Shop/types/ShopInfo";
export enum TranslationInputFieldName {
description = "description",
name = "name",
seoDescription = "seoDescription",
seoTitle = "seoTitle",
richText = "richText"
}
export enum PageTranslationInputFieldName {
content = "content",
title = "title",
seoDescription = "seoDescription",
seoTitle = "seoTitle",
richText = "richText"
}
export interface TranslationField<T extends string = string> {
id?: string;
displayName: string;
name: T;
translation: string;
type: "short" | "long" | "rich";
value: string;
}
export interface TranslationsEntitiesPageProps {
activeField: string;
disabled: boolean;
@ -12,19 +37,5 @@ export interface TranslationsEntitiesPageProps {
onEdit: (field: string) => void;
onDiscard: () => void;
onLanguageChange: (lang: string) => void;
onSubmit: (field: string, data: string | OutputData) => void;
}
export enum TranslationInputFieldName {
description = "description",
name = "name",
seoDescription = "seoDescription",
seoTitle = "seoTitle"
}
export enum PageTranslationInputFieldName {
content = "content",
title = "title",
seoDescription = "seoDescription",
seoTitle = "seoTitle"
onSubmit: (field: TranslationField, data: string | OutputData) => void;
}

View file

@ -60,6 +60,7 @@ export interface AttributeTranslationDetails_translation_AttributeTranslatableCo
id: string;
name: string | null;
inputType: AttributeInputTypeEnum | null;
withChoices: boolean;
choices: AttributeTranslationDetails_translation_AttributeTranslatableContent_attribute_choices | null;
}

View file

@ -28,6 +28,8 @@ export interface AttributeTranslations_translations_edges_node_AttributeTranslat
export interface AttributeTranslations_translations_edges_node_AttributeTranslatableContent {
__typename: "AttributeTranslatableContent";
id: string;
name: string;
translation: AttributeTranslations_translations_edges_node_AttributeTranslatableContent_translation | null;
attribute: AttributeTranslations_translations_edges_node_AttributeTranslatableContent_attribute | null;
}

View file

@ -38,10 +38,39 @@ export interface PageTranslationDetails_translation_PageTranslatableContent_tran
language: PageTranslationDetails_translation_PageTranslatableContent_translation_language;
}
export interface PageTranslationDetails_translation_PageTranslatableContent_attributeValues_attributeValue {
__typename: "AttributeValue";
id: string;
}
export interface PageTranslationDetails_translation_PageTranslatableContent_attributeValues_translation_language {
__typename: "LanguageDisplay";
code: LanguageCodeEnum;
language: string;
}
export interface PageTranslationDetails_translation_PageTranslatableContent_attributeValues_translation {
__typename: "AttributeValueTranslation";
id: string;
name: string;
richText: any | null;
language: PageTranslationDetails_translation_PageTranslatableContent_attributeValues_translation_language;
}
export interface PageTranslationDetails_translation_PageTranslatableContent_attributeValues {
__typename: "AttributeValueTranslatableContent";
id: string;
name: string;
richText: any | null;
attributeValue: PageTranslationDetails_translation_PageTranslatableContent_attributeValues_attributeValue | null;
translation: PageTranslationDetails_translation_PageTranslatableContent_attributeValues_translation | null;
}
export interface PageTranslationDetails_translation_PageTranslatableContent {
__typename: "PageTranslatableContent";
page: PageTranslationDetails_translation_PageTranslatableContent_page | null;
translation: PageTranslationDetails_translation_PageTranslatableContent_translation | null;
attributeValues: PageTranslationDetails_translation_PageTranslatableContent_attributeValues[];
}
export type PageTranslationDetails_translation = PageTranslationDetails_translation_ProductTranslatableContent | PageTranslationDetails_translation_PageTranslatableContent;

View file

@ -38,10 +38,39 @@ export interface PageTranslations_translations_edges_node_PageTranslatableConten
language: PageTranslations_translations_edges_node_PageTranslatableContent_translation_language;
}
export interface PageTranslations_translations_edges_node_PageTranslatableContent_attributeValues_attributeValue {
__typename: "AttributeValue";
id: string;
}
export interface PageTranslations_translations_edges_node_PageTranslatableContent_attributeValues_translation_language {
__typename: "LanguageDisplay";
code: LanguageCodeEnum;
language: string;
}
export interface PageTranslations_translations_edges_node_PageTranslatableContent_attributeValues_translation {
__typename: "AttributeValueTranslation";
id: string;
name: string;
richText: any | null;
language: PageTranslations_translations_edges_node_PageTranslatableContent_attributeValues_translation_language;
}
export interface PageTranslations_translations_edges_node_PageTranslatableContent_attributeValues {
__typename: "AttributeValueTranslatableContent";
id: string;
name: string;
richText: any | null;
attributeValue: PageTranslations_translations_edges_node_PageTranslatableContent_attributeValues_attributeValue | null;
translation: PageTranslations_translations_edges_node_PageTranslatableContent_attributeValues_translation | null;
}
export interface PageTranslations_translations_edges_node_PageTranslatableContent {
__typename: "PageTranslatableContent";
page: PageTranslations_translations_edges_node_PageTranslatableContent_page | null;
translation: PageTranslations_translations_edges_node_PageTranslatableContent_translation | null;
attributeValues: PageTranslations_translations_edges_node_PageTranslatableContent_attributeValues[];
}
export type PageTranslations_translations_edges_node = PageTranslations_translations_edges_node_ProductTranslatableContent | PageTranslations_translations_edges_node_PageTranslatableContent;

View file

@ -31,17 +31,46 @@ export interface ProductTranslationDetails_translation_ProductTranslatableConten
export interface ProductTranslationDetails_translation_ProductTranslatableContent_translation {
__typename: "ProductTranslation";
id: string;
seoTitle: string | null;
seoDescription: string | null;
name: string | null;
description: any | null;
language: ProductTranslationDetails_translation_ProductTranslatableContent_translation_language;
name: string | null;
seoDescription: string | null;
seoTitle: string | null;
}
export interface ProductTranslationDetails_translation_ProductTranslatableContent_attributeValues_attributeValue {
__typename: "AttributeValue";
id: string;
}
export interface ProductTranslationDetails_translation_ProductTranslatableContent_attributeValues_translation_language {
__typename: "LanguageDisplay";
code: LanguageCodeEnum;
language: string;
}
export interface ProductTranslationDetails_translation_ProductTranslatableContent_attributeValues_translation {
__typename: "AttributeValueTranslation";
id: string;
name: string;
richText: any | null;
language: ProductTranslationDetails_translation_ProductTranslatableContent_attributeValues_translation_language;
}
export interface ProductTranslationDetails_translation_ProductTranslatableContent_attributeValues {
__typename: "AttributeValueTranslatableContent";
id: string;
name: string;
richText: any | null;
attributeValue: ProductTranslationDetails_translation_ProductTranslatableContent_attributeValues_attributeValue | null;
translation: ProductTranslationDetails_translation_ProductTranslatableContent_attributeValues_translation | null;
}
export interface ProductTranslationDetails_translation_ProductTranslatableContent {
__typename: "ProductTranslatableContent";
product: ProductTranslationDetails_translation_ProductTranslatableContent_product | null;
translation: ProductTranslationDetails_translation_ProductTranslatableContent_translation | null;
attributeValues: ProductTranslationDetails_translation_ProductTranslatableContent_attributeValues[];
}
export type ProductTranslationDetails_translation = ProductTranslationDetails_translation_CollectionTranslatableContent | ProductTranslationDetails_translation_ProductTranslatableContent;

View file

@ -31,17 +31,46 @@ export interface ProductTranslations_translations_edges_node_ProductTranslatable
export interface ProductTranslations_translations_edges_node_ProductTranslatableContent_translation {
__typename: "ProductTranslation";
id: string;
seoTitle: string | null;
seoDescription: string | null;
name: string | null;
description: any | null;
language: ProductTranslations_translations_edges_node_ProductTranslatableContent_translation_language;
name: string | null;
seoDescription: string | null;
seoTitle: string | null;
}
export interface ProductTranslations_translations_edges_node_ProductTranslatableContent_attributeValues_attributeValue {
__typename: "AttributeValue";
id: string;
}
export interface ProductTranslations_translations_edges_node_ProductTranslatableContent_attributeValues_translation_language {
__typename: "LanguageDisplay";
code: LanguageCodeEnum;
language: string;
}
export interface ProductTranslations_translations_edges_node_ProductTranslatableContent_attributeValues_translation {
__typename: "AttributeValueTranslation";
id: string;
name: string;
richText: any | null;
language: ProductTranslations_translations_edges_node_ProductTranslatableContent_attributeValues_translation_language;
}
export interface ProductTranslations_translations_edges_node_ProductTranslatableContent_attributeValues {
__typename: "AttributeValueTranslatableContent";
id: string;
name: string;
richText: any | null;
attributeValue: ProductTranslations_translations_edges_node_ProductTranslatableContent_attributeValues_attributeValue | null;
translation: ProductTranslations_translations_edges_node_ProductTranslatableContent_attributeValues_translation | null;
}
export interface ProductTranslations_translations_edges_node_ProductTranslatableContent {
__typename: "ProductTranslatableContent";
product: ProductTranslations_translations_edges_node_ProductTranslatableContent_product | null;
translation: ProductTranslations_translations_edges_node_ProductTranslatableContent_translation | null;
attributeValues: ProductTranslations_translations_edges_node_ProductTranslatableContent_attributeValues[];
}
export type ProductTranslations_translations_edges_node = ProductTranslations_translations_edges_node_CollectionTranslatableContent | ProductTranslations_translations_edges_node_ProductTranslatableContent;

View file

@ -26,6 +26,7 @@ export interface UpdateAttributeValueTranslations_attributeValueTranslate_attrib
__typename: "AttributeValue";
id: string;
name: string | null;
richText: any | null;
translation: UpdateAttributeValueTranslations_attributeValueTranslate_attributeValue_translation | null;
}

View file

@ -40,10 +40,39 @@ export interface UpdatePageTranslations_pageTranslate_page_translation {
language: UpdatePageTranslations_pageTranslate_page_translation_language;
}
export interface UpdatePageTranslations_pageTranslate_page_attributeValues_attributeValue {
__typename: "AttributeValue";
id: string;
}
export interface UpdatePageTranslations_pageTranslate_page_attributeValues_translation_language {
__typename: "LanguageDisplay";
code: LanguageCodeEnum;
language: string;
}
export interface UpdatePageTranslations_pageTranslate_page_attributeValues_translation {
__typename: "AttributeValueTranslation";
id: string;
name: string;
richText: any | null;
language: UpdatePageTranslations_pageTranslate_page_attributeValues_translation_language;
}
export interface UpdatePageTranslations_pageTranslate_page_attributeValues {
__typename: "AttributeValueTranslatableContent";
id: string;
name: string;
richText: any | null;
attributeValue: UpdatePageTranslations_pageTranslate_page_attributeValues_attributeValue | null;
translation: UpdatePageTranslations_pageTranslate_page_attributeValues_translation | null;
}
export interface UpdatePageTranslations_pageTranslate_page {
__typename: "PageTranslatableContent";
page: UpdatePageTranslations_pageTranslate_page_page | null;
translation: UpdatePageTranslations_pageTranslate_page_translation | null;
attributeValues: UpdatePageTranslations_pageTranslate_page_attributeValues[];
}
export interface UpdatePageTranslations_pageTranslate {

View file

@ -11,7 +11,7 @@ export enum TranslatableEntities {
sales = "sales",
vouchers = "vouchers",
pages = "pages",
productTypes = "productTypes",
attributes = "attributes",
shippingMethods = "shippingMethods"
}

View file

@ -14,14 +14,15 @@ import { useIntl } from "react-intl";
import { getMutationState, maybe } from "../../misc";
import { LanguageCodeEnum } from "../../types/globalTypes";
import TranslationsProductTypesPage, {
import TranslationsAttributesPage, {
fieldNames
} from "../components/TranslationsProductTypesPage";
} from "../components/TranslationsAttributesPage";
import {
TypedUpdateAttributeTranslations,
TypedUpdateAttributeValueTranslations
} from "../mutations";
import { useAttributeTranslationDetails } from "../queries";
import { TranslationField } from "../types";
import { UpdateAttributeTranslations } from "../types/UpdateAttributeTranslations";
import { UpdateAttributeValueTranslations } from "../types/UpdateAttributeValueTranslations";
import {
@ -30,16 +31,16 @@ import {
TranslatableEntities
} from "../urls";
export interface TranslationsProductTypesQueryParams extends Pagination {
export interface TranslationsAttributesQueryParams extends Pagination {
activeField: string;
}
export interface TranslationsProductTypesProps {
export interface TranslationsAttributesProps {
id: string;
languageCode: LanguageCodeEnum;
params: TranslationsProductTypesQueryParams;
params: TranslationsAttributesQueryParams;
}
const TranslationsProductTypes: React.FC<TranslationsProductTypesProps> = ({
const TranslationsAttributes: React.FC<TranslationsAttributesProps> = ({
id,
languageCode,
params
@ -121,8 +122,11 @@ const TranslationsProductTypes: React.FC<TranslationsProductTypesProps> = ({
updateAttributeValueTranslations,
updateAttributeValueTranslationsOpts
) => {
const handleSubmit = (field: string, data: string | OutputData) => {
const [fieldName, fieldId] = field.split(":");
const handleSubmit = (
{ name }: TranslationField,
data: string | OutputData
) => {
const [fieldName, fieldId] = name.split(":");
if (fieldName === fieldNames.attribute) {
updateAttributeTranslations({
@ -168,7 +172,7 @@ const TranslationsProductTypes: React.FC<TranslationsProductTypesProps> = ({
);
return (
<TranslationsProductTypesPage
<TranslationsAttributesPage
activeField={params.activeField}
disabled={
attributeTranslations.loading ||
@ -181,7 +185,7 @@ const TranslationsProductTypes: React.FC<TranslationsProductTypesProps> = ({
onBack={() =>
navigate(
languageEntitiesUrl(languageCode, {
tab: TranslatableEntities.productTypes
tab: TranslatableEntities.attributes
})
)
}
@ -189,11 +193,7 @@ const TranslationsProductTypes: React.FC<TranslationsProductTypesProps> = ({
onDiscard={onDiscard}
onLanguageChange={lang =>
navigate(
languageEntityUrl(
lang,
TranslatableEntities.productTypes,
id
)
languageEntityUrl(lang, TranslatableEntities.attributes, id)
)
}
onSubmit={handleSubmit}
@ -211,5 +211,5 @@ const TranslationsProductTypes: React.FC<TranslationsProductTypesProps> = ({
</TypedUpdateAttributeTranslations>
);
};
TranslationsProductTypes.displayName = "TranslationsProductTypes";
export default TranslationsProductTypes;
TranslationsAttributes.displayName = "TranslationsAttributes";
export default TranslationsAttributes;

View file

@ -11,7 +11,7 @@ import { LanguageCodeEnum } from "../../types/globalTypes";
import TranslationsCategoriesPage from "../components/TranslationsCategoriesPage";
import { TypedUpdateCategoryTranslations } from "../mutations";
import { useCategoryTranslationDetails } from "../queries";
import { TranslationInputFieldName } from "../types";
import { TranslationField, TranslationInputFieldName } from "../types";
import { UpdateCategoryTranslations } from "../types/UpdateCategoryTranslations";
import {
languageEntitiesUrl,
@ -69,13 +69,16 @@ const TranslationsCategories: React.FC<TranslationsCategoriesProps> = ({
<TypedUpdateCategoryTranslations onCompleted={onUpdate}>
{(updateTranslations, updateTranslationsOpts) => {
const handleSubmit = (
fieldName: TranslationInputFieldName,
{ name: fieldName }: TranslationField<TranslationInputFieldName>,
data: string | OutputData
) => {
updateTranslations({
variables: {
id,
input: getParsedTranslationInputData({ data, fieldName }),
input: getParsedTranslationInputData({
data,
fieldName
}),
language: languageCode
}
});

View file

@ -11,7 +11,7 @@ import { LanguageCodeEnum } from "../../types/globalTypes";
import TranslationsCollectionsPage from "../components/TranslationsCollectionsPage";
import { TypedUpdateCollectionTranslations } from "../mutations";
import { useCollectionTranslationDetails } from "../queries";
import { TranslationInputFieldName } from "../types";
import { TranslationField, TranslationInputFieldName } from "../types";
import { UpdateCollectionTranslations } from "../types/UpdateCollectionTranslations";
import {
languageEntitiesUrl,
@ -70,13 +70,16 @@ const TranslationsCollections: React.FC<TranslationsCollectionsProps> = ({
<TypedUpdateCollectionTranslations onCompleted={onUpdate}>
{(updateTranslations, updateTranslationsOpts) => {
const handleSubmit = (
fieldName: TranslationInputFieldName,
{ name: fieldName }: TranslationField<TranslationInputFieldName>,
data: string
) => {
updateTranslations({
variables: {
id,
input: getParsedTranslationInputData({ data, fieldName }),
input: getParsedTranslationInputData({
data,
fieldName
}),
language: languageCode
}
});

View file

@ -76,11 +76,11 @@ const TranslationsEntities: React.FC<TranslationsEntitiesProps> = ({
tab: TranslatableEntities.pages
})
),
onProductTypesTabClick: () =>
onAttributesTabClick: () =>
navigate(
"?" +
stringifyQs({
tab: TranslatableEntities.productTypes
tab: TranslatableEntities.attributes
})
),
onProductsTabClick: () =>
@ -380,7 +380,7 @@ const TranslationsEntities: React.FC<TranslationsEntitiesProps> = ({
);
}}
</TypedPageTranslations>
) : params.tab === "productTypes" ? (
) : params.tab === "attributes" ? (
<TypedAttributeTranslations variables={queryVariables}>
{({ data, loading }) => {
const { loadNextPage, loadPreviousPage, pageInfo } = paginate(
@ -403,7 +403,7 @@ const TranslationsEntities: React.FC<TranslationsEntitiesProps> = ({
navigate(
languageEntityUrl(
language,
TranslatableEntities.productTypes,
TranslatableEntities.attributes,
id
)
)

View file

@ -1,3 +1,4 @@
import { OutputData } from "@editorjs/editorjs";
import useNavigator from "@saleor/hooks/useNavigator";
import useNotifier from "@saleor/hooks/useNotifier";
import useShop from "@saleor/hooks/useShop";
@ -8,10 +9,12 @@ import { useIntl } from "react-intl";
import { LanguageCodeEnum } from "../../types/globalTypes";
import TranslationsPagesPage from "../components/TranslationsPagesPage";
import { TypedUpdatePageTranslations } from "../mutations";
import {
TypedUpdateAttributeValueTranslations,
TypedUpdatePageTranslations
} from "../mutations";
import { usePageTranslationDetails } from "../queries";
import { PageTranslationInputFieldName } from "../types";
import { UpdatePageTranslations } from "../types/UpdatePageTranslations";
import { PageTranslationInputFieldName, TranslationField } from "../types";
import {
languageEntitiesUrl,
languageEntityUrl,
@ -50,8 +53,9 @@ const TranslationsPages: React.FC<TranslationsPagesProps> = ({
}),
true
);
const onUpdate = (data: UpdatePageTranslations) => {
if (data.pageTranslate.errors.length === 0) {
const onUpdate = (errors: unknown[]) => {
if (errors.length === 0) {
pageTranslations.refetch();
notify({
status: "success",
@ -60,57 +64,88 @@ const TranslationsPages: React.FC<TranslationsPagesProps> = ({
navigate("?", true);
}
};
const onDiscard = () => {
navigate("?", true);
};
return (
<TypedUpdatePageTranslations onCompleted={onUpdate}>
{(updateTranslations, updateTranslationsOpts) => {
const handleSubmit = (
fieldName: PageTranslationInputFieldName,
data: string
) => {
updateTranslations({
variables: {
id,
input: getParsedTranslationInputData({ data, fieldName }),
language: languageCode
}
});
};
const translation = pageTranslations?.data?.translation;
<TypedUpdatePageTranslations
onCompleted={data => onUpdate(data.pageTranslate.errors)}
>
{(updateTranslations, updateTranslationsOpts) => (
<TypedUpdateAttributeValueTranslations
onCompleted={data => onUpdate(data.attributeValueTranslate.errors)}
>
{updateAttributeValueTranslations => {
const handleSubmit = (
{
name: fieldName
}: TranslationField<PageTranslationInputFieldName>,
data: string | any
) => {
updateTranslations({
variables: {
id,
input: getParsedTranslationInputData({
data,
fieldName
}),
language: languageCode
}
});
};
return (
<TranslationsPagesPage
activeField={params.activeField}
disabled={
pageTranslations.loading || updateTranslationsOpts.loading
}
languageCode={languageCode}
languages={shop?.languages || []}
saveButtonState={updateTranslationsOpts.status}
onBack={() =>
navigate(
languageEntitiesUrl(languageCode, {
tab: TranslatableEntities.pages
})
)
}
onEdit={onEdit}
onDiscard={onDiscard}
onLanguageChange={lang =>
navigate(languageEntityUrl(lang, TranslatableEntities.pages, id))
}
onSubmit={handleSubmit}
data={
translation?.__typename === "PageTranslatableContent"
? translation
: null
}
/>
);
}}
const handleAttributeValueSubmit = (
{ id }: TranslationField<PageTranslationInputFieldName>,
data: OutputData
) => {
updateAttributeValueTranslations({
variables: {
id,
input: { richText: JSON.stringify(data) },
language: languageCode
}
});
};
const translation = pageTranslations?.data?.translation;
return (
<TranslationsPagesPage
activeField={params.activeField}
disabled={
pageTranslations.loading || updateTranslationsOpts.loading
}
languageCode={languageCode}
languages={shop?.languages || []}
saveButtonState={updateTranslationsOpts.status}
onBack={() =>
navigate(
languageEntitiesUrl(languageCode, {
tab: TranslatableEntities.pages
})
)
}
onEdit={onEdit}
onDiscard={onDiscard}
onLanguageChange={lang =>
navigate(
languageEntityUrl(lang, TranslatableEntities.pages, id)
)
}
onSubmit={handleSubmit}
onAttributeValueSubmit={handleAttributeValueSubmit}
data={
translation?.__typename === "PageTranslatableContent"
? translation
: null
}
/>
);
}}
</TypedUpdateAttributeValueTranslations>
)}
</TypedUpdatePageTranslations>
);
};

View file

@ -1,3 +1,4 @@
import { OutputData } from "@editorjs/editorjs";
import useNavigator from "@saleor/hooks/useNavigator";
import useNotifier from "@saleor/hooks/useNotifier";
import useShop from "@saleor/hooks/useShop";
@ -9,10 +10,12 @@ import { useIntl } from "react-intl";
import { maybe } from "../../misc";
import { LanguageCodeEnum } from "../../types/globalTypes";
import TranslationsProductsPage from "../components/TranslationsProductsPage";
import { TypedUpdateProductTranslations } from "../mutations";
import {
TypedUpdateAttributeValueTranslations,
TypedUpdateProductTranslations
} from "../mutations";
import { useProductTranslationDetails } from "../queries";
import { TranslationInputFieldName } from "../types";
import { UpdateProductTranslations } from "../types/UpdateProductTranslations";
import { TranslationField, TranslationInputFieldName } from "../types";
import {
languageEntitiesUrl,
languageEntityUrl,
@ -51,8 +54,9 @@ const TranslationsProducts: React.FC<TranslationsProductsProps> = ({
}),
true
);
const onUpdate = (data: UpdateProductTranslations) => {
if (data.productTranslate.errors.length === 0) {
const onUpdate = (errors: unknown[]) => {
if (errors.length === 0) {
productTranslations.refetch();
notify({
status: "success",
@ -61,59 +65,86 @@ const TranslationsProducts: React.FC<TranslationsProductsProps> = ({
navigate("?", true);
}
};
const onDiscard = () => {
navigate("?", true);
};
return (
<TypedUpdateProductTranslations onCompleted={onUpdate}>
{(updateTranslations, updateTranslationsOpts) => {
const handleSubmit = (
fieldName: TranslationInputFieldName,
data: string
) => {
updateTranslations({
variables: {
id,
input: getParsedTranslationInputData({ data, fieldName }),
language: languageCode
}
});
};
const translation = productTranslations?.data?.translation;
<TypedUpdateProductTranslations
onCompleted={data => onUpdate(data.productTranslate.errors)}
>
{(updateTranslations, updateTranslationsOpts) => (
<TypedUpdateAttributeValueTranslations
onCompleted={data => onUpdate(data.attributeValueTranslate.errors)}
>
{updateAttributeValueTranslations => {
const handleSubmit = (
{ name: fieldName }: TranslationField<TranslationInputFieldName>,
data: string
) => {
updateTranslations({
variables: {
id,
input: getParsedTranslationInputData({
data,
fieldName
}),
language: languageCode
}
});
};
return (
<TranslationsProductsPage
activeField={params.activeField}
disabled={
productTranslations.loading || updateTranslationsOpts.loading
}
languageCode={languageCode}
languages={maybe(() => shop.languages, [])}
saveButtonState={updateTranslationsOpts.status}
onBack={() =>
navigate(
languageEntitiesUrl(languageCode, {
tab: TranslatableEntities.products
})
)
}
onEdit={onEdit}
onDiscard={onDiscard}
onLanguageChange={lang =>
navigate(
languageEntityUrl(lang, TranslatableEntities.products, id)
)
}
onSubmit={handleSubmit}
data={
translation?.__typename === "ProductTranslatableContent"
? translation
: null
}
/>
);
}}
const handleAttributeValueSubmit = (
{ id }: TranslationField<TranslationInputFieldName>,
data: OutputData
) => {
updateAttributeValueTranslations({
variables: {
id,
input: { richText: JSON.stringify(data) },
language: languageCode
}
});
};
const translation = productTranslations?.data?.translation;
return (
<TranslationsProductsPage
activeField={params.activeField}
disabled={
productTranslations.loading || updateTranslationsOpts.loading
}
languageCode={languageCode}
languages={maybe(() => shop.languages, [])}
saveButtonState={updateTranslationsOpts.status}
onBack={() =>
navigate(
languageEntitiesUrl(languageCode, {
tab: TranslatableEntities.products
})
)
}
onEdit={onEdit}
onDiscard={onDiscard}
onLanguageChange={lang =>
navigate(
languageEntityUrl(lang, TranslatableEntities.products, id)
)
}
onSubmit={handleSubmit}
onAttributeValueSubmit={handleAttributeValueSubmit}
data={
translation?.__typename === "ProductTranslatableContent"
? translation
: null
}
/>
);
}}
</TypedUpdateAttributeValueTranslations>
)}
</TypedUpdateProductTranslations>
);
};

View file

@ -6,21 +6,18 @@ import { stringify as stringifyQs } from "qs";
import React from "react";
import { useIntl } from "react-intl";
import {
LanguageCodeEnum,
NameTranslationInput
} from "../../types/globalTypes";
import TranslationsSalesPage, {
fieldNames
} from "../components/TranslationsSalesPage";
import { LanguageCodeEnum } from "../../types/globalTypes";
import TranslationsSalesPage from "../components/TranslationsSalesPage";
import { TypedUpdateSaleTranslations } from "../mutations";
import { useSaleTranslationDetails } from "../queries";
import { TranslationField, TranslationInputFieldName } from "../types";
import { UpdateSaleTranslations } from "../types/UpdateSaleTranslations";
import {
languageEntitiesUrl,
languageEntityUrl,
TranslatableEntities
} from "../urls";
import { getParsedTranslationInputData } from "../utils";
export interface TranslationsSalesQueryParams {
activeField: string;
@ -70,15 +67,17 @@ const TranslationsSales: React.FC<TranslationsSalesProps> = ({
return (
<TypedUpdateSaleTranslations onCompleted={onUpdate}>
{(updateTranslations, updateTranslationsOpts) => {
const handleSubmit = (field: string, data: string) => {
const input: NameTranslationInput = {};
if (field === fieldNames.name) {
input.name = data;
}
const handleSubmit = (
{ name: fieldName }: TranslationField<TranslationInputFieldName>,
data: string
) => {
updateTranslations({
variables: {
id,
input,
input: getParsedTranslationInputData({
data,
fieldName
}),
language: languageCode
}
});

View file

@ -10,7 +10,7 @@ import { LanguageCodeEnum } from "../../types/globalTypes";
import TranslationsShippingMethodPage from "../components/TranslationsShippingMethodPage";
import { TypedUpdateShippingMethodTranslations } from "../mutations";
import { useShippingMethodTranslationDetails } from "../queries";
import { TranslationInputFieldName } from "../types";
import { TranslationField, TranslationInputFieldName } from "../types";
import { UpdateShippingMethodTranslations } from "../types/UpdateShippingMethodTranslations";
import {
languageEntitiesUrl,
@ -68,13 +68,13 @@ const TranslationsShippingMethod: React.FC<TranslationsShippingMethodProps> = ({
<TypedUpdateShippingMethodTranslations onCompleted={onUpdate}>
{(updateTranslations, updateTranslationsOpts) => {
const handleSubmit = (
field: TranslationInputFieldName,
{ name: fieldName }: TranslationField<TranslationInputFieldName>,
data: string
) => {
updateTranslations({
variables: {
id,
input: getParsedTranslationInputData({ fieldName: field, data }),
input: getParsedTranslationInputData({ fieldName, data }),
language: languageCode
}
});

View file

@ -7,21 +7,18 @@ import React from "react";
import { useIntl } from "react-intl";
import { maybe } from "../../misc";
import {
LanguageCodeEnum,
NameTranslationInput
} from "../../types/globalTypes";
import TranslationsVouchersPage, {
fieldNames
} from "../components/TranslationsVouchersPage";
import { LanguageCodeEnum } from "../../types/globalTypes";
import TranslationsVouchersPage from "../components/TranslationsVouchersPage";
import { TypedUpdateVoucherTranslations } from "../mutations";
import { useVoucherTranslationDetails } from "../queries";
import { TranslationField, TranslationInputFieldName } from "../types";
import { UpdateVoucherTranslations } from "../types/UpdateVoucherTranslations";
import {
languageEntitiesUrl,
languageEntityUrl,
TranslatableEntities
} from "../urls";
import { getParsedTranslationInputData } from "../utils";
export interface TranslationsVouchersQueryParams {
activeField: string;
@ -71,15 +68,17 @@ const TranslationsVouchers: React.FC<TranslationsVouchersProps> = ({
return (
<TypedUpdateVoucherTranslations onCompleted={onUpdate}>
{(updateTranslations, updateTranslationsOpts) => {
const handleSubmit = (field: string, data: string) => {
const input: NameTranslationInput = {};
if (field === fieldNames.name) {
input.name = data;
}
const handleSubmit = (
{ name: fieldName }: TranslationField<TranslationInputFieldName>,
data: string
) => {
updateTranslations({
variables: {
id,
input,
input: getParsedTranslationInputData({
data,
fieldName
}),
language: languageCode
}
});