Add shipping method description (#1058)

* Add shipping method description - WIP

* Wire up logic

* Handle more editorjs issues

* Fix minor issues

Co-authored-by: Dawid Tarasiuk <tarasiukdawid@gmail.com>
This commit is contained in:
Jakub Majorek 2021-04-16 14:33:14 +02:00 committed by GitHub
parent d5233b3131
commit e5df1b2dbf
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
48 changed files with 2762 additions and 2296 deletions

View file

@ -33,6 +33,7 @@ All notable, unreleased changes to this project will be documented in this file.
- Add multiline field plugins - #974 by @dominik-zeglen
- Handle limit reached error - #990 by @dominik-zeglen
- Display Cloud limits - #1004 by @dominik-zeglen
- Add shipping method description - #1058 by @jwm0
# 2.11.1

View file

@ -5804,6 +5804,10 @@
"src_dot_shipping_dot_components_dot_ShippingMethodProducts_dot_4190792473": {
"string": "Actions"
},
"src_dot_shipping_dot_components_dot_ShippingRateInfo_dot_description": {
"context": "label",
"string": "Shipping Rate Description"
},
"src_dot_shipping_dot_components_dot_ShippingRateInfo_dot_maxDays": {
"context": "label",
"string": "Max Delivery Time"
@ -6604,12 +6608,17 @@
"src_dot_translations_dot_components_dot_TranslationsSalesPage_dot_898281424": {
"string": "Sale Name"
},
"src_dot_translations_dot_components_dot_TranslationsShippingMethodPage_dot_3374163063": {
"context": "shipping method description",
"string": "Description"
},
"src_dot_translations_dot_components_dot_TranslationsShippingMethodPage_dot_3498202636": {
"context": "header",
"string": "Translation ShippingMethod \"{shippingMethodName}\" - {languageCode}"
},
"src_dot_translations_dot_components_dot_TranslationsShippingMethodPage_dot_99732714": {
"string": "ShippingMethod Name"
"src_dot_translations_dot_components_dot_TranslationsShippingMethodPage_dot_636461959": {
"context": "shipping method name",
"string": "Name"
},
"src_dot_translations_dot_components_dot_TranslationsVouchersPage_dot_2447510181": {
"context": "header",

2168
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -28,7 +28,7 @@
"@saleor/macaw-ui": "^0.1.1-9",
"@sentry/react": "^6.0.0",
"@types/faker": "^5.1.6",
"apollo": "^2.21.2",
"apollo": "^2.32.5",
"apollo-cache-inmemory": "^1.6.5",
"apollo-client": "^2.6.8",
"apollo-client-preset": "^1.0.6",

File diff suppressed because it is too large Load diff

View file

@ -1,12 +1,12 @@
import { WindowTitle } from "@saleor/components/WindowTitle";
import useNavigator from "@saleor/hooks/useNavigator";
import useNotifier from "@saleor/hooks/useNotifier";
import { getParsedDataForJsonStringField } from "@saleor/translations/utils";
import createMetadataCreateHandler from "@saleor/utils/handlers/metadataCreateHandler";
import {
useMetadataUpdate,
usePrivateMetadataUpdate
} from "@saleor/utils/metadata/updateMetadata";
import { getParsedDataForJsonStringField } from "@saleor/utils/richText/misc";
import React from "react";
import { useIntl } from "react-intl";

View file

@ -13,7 +13,6 @@ import usePaginator, {
createPaginationState
} from "@saleor/hooks/usePaginator";
import { commonMessages } from "@saleor/intl";
import { getParsedDataForJsonStringField } from "@saleor/translations/utils";
import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers";
import createMetadataUpdateHandler from "@saleor/utils/handlers/metadataUpdateHandler";
import { mapNodeToChoice } from "@saleor/utils/maps";
@ -21,6 +20,7 @@ import {
useMetadataUpdate,
usePrivateMetadataUpdate
} from "@saleor/utils/metadata/updateMetadata";
import { getParsedDataForJsonStringField } from "@saleor/utils/richText/misc";
import React from "react";
import { FormattedMessage, useIntl } from "react-intl";

View file

@ -7,13 +7,13 @@ import useChannels from "@saleor/hooks/useChannels";
import useNavigator from "@saleor/hooks/useNavigator";
import useNotifier from "@saleor/hooks/useNotifier";
import { commonMessages } from "@saleor/intl";
import { getParsedDataForJsonStringField } from "@saleor/translations/utils";
import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers";
import createMetadataCreateHandler from "@saleor/utils/handlers/metadataCreateHandler";
import {
useMetadataUpdate,
usePrivateMetadataUpdate
} from "@saleor/utils/metadata/updateMetadata";
import { getParsedDataForJsonStringField } from "@saleor/utils/richText/misc";
import React from "react";
import { useIntl } from "react-intl";

View file

@ -21,13 +21,13 @@ import usePaginator, {
} from "@saleor/hooks/usePaginator";
import { commonMessages } from "@saleor/intl";
import useProductSearch from "@saleor/searches/useProductSearch";
import { getParsedDataForJsonStringField } from "@saleor/translations/utils";
import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers";
import createMetadataUpdateHandler from "@saleor/utils/handlers/metadataUpdateHandler";
import {
useMetadataUpdate,
usePrivateMetadataUpdate
} from "@saleor/utils/metadata/updateMetadata";
import { getParsedDataForJsonStringField } from "@saleor/utils/richText/misc";
import { diff } from "fast-array-diff";
import React from "react";
import { FormattedMessage, useIntl } from "react-intl";

View file

@ -1,7 +1,9 @@
import { useAuth } from "@saleor/auth/AuthProvider";
import { useBaseChannelsList } from "@saleor/channels/queries";
import { BaseChannels_channels } from "@saleor/channels/types/BaseChannels";
import { ChannelFragment } from "@saleor/fragments/types/ChannelFragment";
import useLocalStorage from "@saleor/hooks/useLocalStorage";
import { getById } from "@saleor/orders/components/OrderReturnPage/utils";
import React from "react";
interface UseAppChannel {
@ -24,6 +26,17 @@ const AppChannelContext = React.createContext<AppChannelContextData>({
setPickerActive: () => undefined
});
const isValidChannel = (
channelId: string,
channelList?: BaseChannels_channels[]
) => {
if (!channelId) {
return false;
}
return channelList?.some(getById(channelId));
};
export const AppChannelProvider: React.FC = ({ children }) => {
const { isAuthenticated } = useAuth();
const [selectedChannel, setSelectedChannel] = useLocalStorage("channel", "");
@ -33,7 +46,10 @@ export const AppChannelProvider: React.FC = ({ children }) => {
const [isPickerActive, setPickerActive] = React.useState(false);
React.useEffect(() => {
if (!selectedChannel && channelData?.channels?.length > 0) {
if (
!isValidChannel(selectedChannel, channelData?.channels) &&
channelData?.channels?.length > 0
) {
setSelectedChannel(channelData.channels[0].id);
}
}, [channelData]);

View file

@ -34,10 +34,11 @@ const RichTextEditor: React.FC<RichTextEditorProps> = ({
const editor = React.useRef<EditorJS>();
const editorContainer = React.useRef<HTMLDivElement>();
const prevTogglePromise = React.useRef<Promise<boolean>>(); // used to await subsequent toggle invocations
const initialMount = React.useRef(true);
React.useEffect(
() => {
if (data) {
if (data !== undefined) {
editor.current = new EditorJS({
data,
holder: editorContainer.current,
@ -68,6 +69,11 @@ const RichTextEditor: React.FC<RichTextEditorProps> = ({
React.useEffect(() => {
const toggle = async () => {
if (!editor.current) {
return;
}
await editor.current.isReady;
if (editor.current?.readOnly) {
// readOnly.toggle() by itself does not enqueue the events and will result in a broken output if invocations overlap
// Remove this logic when this is fixed in EditorJS
@ -75,10 +81,21 @@ const RichTextEditor: React.FC<RichTextEditorProps> = ({
await prevTogglePromise.current;
}
prevTogglePromise.current = editor.current.readOnly.toggle(disabled);
// Switching to readOnly with empty blocks present causes the editor to freeze
// Remove this logic when this is fixed in EditorJS
if (!disabled && !data?.blocks?.length) {
await prevTogglePromise.current;
editor.current.clear();
}
}
};
toggle();
if (!initialMount.current) {
toggle();
} else {
initialMount.current = false;
}
}, [disabled]);
return (

View file

@ -46,6 +46,7 @@ export const shippingMethodFragment = gql`
minimumDeliveryDays
maximumDeliveryDays
name
description
type
channelListings {
id

View file

@ -82,6 +82,7 @@ export const saleTranslationFragment = gql`
`;
export const voucherTranslationFragment = gql`
fragment VoucherTranslationFragment on VoucherTranslatableContent {
name
voucher {
id
name
@ -98,11 +99,12 @@ export const voucherTranslationFragment = gql`
`;
export const shippingMethodTranslationFragment = gql`
fragment ShippingMethodTranslationFragment on ShippingMethodTranslatableContent {
id
name
description
shippingMethod {
id
}
id
name
translation(languageCode: $language) {
id
language {
@ -110,6 +112,7 @@ export const shippingMethodTranslationFragment = gql`
language
}
name
description
}
}
`;

View file

@ -86,6 +86,7 @@ export interface ShippingMethodFragment {
minimumDeliveryDays: number | null;
maximumDeliveryDays: number | null;
name: string;
description: any | null;
type: ShippingMethodTypeEnum | null;
channelListings: ShippingMethodFragment_channelListings[] | null;
}

View file

@ -25,12 +25,14 @@ export interface ShippingMethodTranslationFragment_translation {
id: string;
language: ShippingMethodTranslationFragment_translation_language;
name: string | null;
description: any | null;
}
export interface ShippingMethodTranslationFragment {
__typename: "ShippingMethodTranslatableContent";
shippingMethod: ShippingMethodTranslationFragment_shippingMethod | null;
id: string;
name: string;
description: any | null;
shippingMethod: ShippingMethodTranslationFragment_shippingMethod | null;
translation: ShippingMethodTranslationFragment_translation | null;
}

View file

@ -117,6 +117,7 @@ export interface ShippingMethodWithExcludedProductsFragment {
minimumDeliveryDays: number | null;
maximumDeliveryDays: number | null;
name: string;
description: any | null;
type: ShippingMethodTypeEnum | null;
channelListings: ShippingMethodWithExcludedProductsFragment_channelListings[] | null;
excludedProducts: ShippingMethodWithExcludedProductsFragment_excludedProducts | null;

View file

@ -104,6 +104,7 @@ export interface ShippingZoneDetailsFragment_shippingMethods {
minimumDeliveryDays: number | null;
maximumDeliveryDays: number | null;
name: string;
description: any | null;
type: ShippingMethodTypeEnum | null;
channelListings: ShippingZoneDetailsFragment_shippingMethods_channelListings[] | null;
}

View file

@ -30,6 +30,7 @@ export interface VoucherTranslationFragment_translation {
export interface VoucherTranslationFragment {
__typename: "VoucherTranslatableContent";
name: string | null;
voucher: VoucherTranslationFragment_voucher | null;
translation: VoucherTranslationFragment_translation | null;
}

View file

@ -19,7 +19,7 @@ export interface UseFormResult<T> {
data: T;
hasChanged: boolean;
reset: () => void;
set: (data: T) => void;
set: (data: Partial<T>) => void;
submit: () => void;
triggerChange: () => void;
toggleValue: FormChange;

View file

@ -12,12 +12,12 @@ import useNotifier from "@saleor/hooks/useNotifier";
import usePageSearch from "@saleor/searches/usePageSearch";
import usePageTypeSearch from "@saleor/searches/usePageTypeSearch";
import useProductSearch from "@saleor/searches/useProductSearch";
import { getParsedDataForJsonStringField } from "@saleor/translations/utils";
import createMetadataCreateHandler from "@saleor/utils/handlers/metadataCreateHandler";
import {
useMetadataUpdate,
usePrivateMetadataUpdate
} from "@saleor/utils/metadata/updateMetadata";
import { getParsedDataForJsonStringField } from "@saleor/utils/richText/misc";
import React from "react";
import { useIntl } from "react-intl";

View file

@ -23,12 +23,12 @@ import useNotifier from "@saleor/hooks/useNotifier";
import { commonMessages } from "@saleor/intl";
import usePageSearch from "@saleor/searches/usePageSearch";
import useProductSearch from "@saleor/searches/useProductSearch";
import { getParsedDataForJsonStringField } from "@saleor/translations/utils";
import createMetadataUpdateHandler from "@saleor/utils/handlers/metadataUpdateHandler";
import {
useMetadataUpdate,
usePrivateMetadataUpdate
} from "@saleor/utils/metadata/updateMetadata";
import { getParsedDataForJsonStringField } from "@saleor/utils/richText/misc";
import React from "react";
import { FormattedMessage, useIntl } from "react-intl";

View file

@ -37,7 +37,7 @@ import {
VariantCreateVariables
} from "@saleor/products/types/VariantCreate";
import { getAvailabilityVariables } from "@saleor/products/utils/handlers";
import { getParsedDataForJsonStringField } from "@saleor/translations/utils";
import { getParsedDataForJsonStringField } from "@saleor/utils/richText/misc";
import { MutationFetchResult } from "react-apollo";
const getChannelsVariables = (productId: string, channels: ChannelData[]) => ({

View file

@ -54,9 +54,9 @@ import {
VariantCreateVariables
} from "@saleor/products/types/VariantCreate";
import { mapFormsetStockToStockInput } from "@saleor/products/utils/data";
import { getParsedDataForJsonStringField } from "@saleor/translations/utils";
import { ReorderEvent } from "@saleor/types";
import { move } from "@saleor/utils/lists";
import { getParsedDataForJsonStringField } from "@saleor/utils/richText/misc";
import { MutationFetchResult } from "react-apollo";
import { arrayMove } from "react-sortable-hoc";

View file

@ -1,8 +1,12 @@
import { OutputData } from "@editorjs/editorjs";
import Card from "@material-ui/core/Card";
import CardContent from "@material-ui/core/CardContent";
import TextField from "@material-ui/core/TextField";
import CardSpacer from "@saleor/components/CardSpacer";
import CardTitle from "@saleor/components/CardTitle";
import RichTextEditor, {
RichTextEditorChange
} from "@saleor/components/RichTextEditor";
import { ShippingErrorFragment } from "@saleor/fragments/types/ShippingErrorFragment";
import { commonMessages } from "@saleor/intl";
import { makeStyles } from "@saleor/theme";
@ -23,6 +27,10 @@ const messages = defineMessages({
name: {
defaultMessage: "Shipping rate name",
description: "label"
},
description: {
defaultMessage: "Shipping Rate Description",
description: "label"
}
});
@ -45,19 +53,28 @@ const useStyles = makeStyles(
);
export interface ShippingRateInfoProps {
data: Record<"name" | "maxDays" | "minDays", string>;
data: {
description: OutputData;
name: string;
maxDays: string;
minDays: string;
};
disabled: boolean;
errors: ShippingErrorFragment[];
onChange: (event: React.ChangeEvent<any>) => void;
onDescriptionChange: RichTextEditorChange;
}
const ShippingRateInfo: React.FC<ShippingRateInfoProps> = props => {
const { data, disabled, errors, onChange } = props;
const { data, disabled, errors, onChange, onDescriptionChange } = props;
const intl = useIntl();
const classes = useStyles(props);
const formErrors = getFormErrors(["name", "minDays", "maxDays"], errors);
const formErrors = getFormErrors(
["name", "description", "minDays", "maxDays"],
errors
);
return (
<Card>
@ -76,6 +93,16 @@ const ShippingRateInfo: React.FC<ShippingRateInfoProps> = props => {
onChange={onChange}
/>
<CardSpacer />
<RichTextEditor
data={data.description}
disabled={disabled}
error={!!formErrors.description}
helperText={getShippingErrorMessage(formErrors.description, intl)}
label={intl.formatMessage(messages.description)}
name="description"
onChange={onDescriptionChange}
/>
<CardSpacer />
<div className={classes.deliveryTimeFields}>
<TextField
disabled={disabled}

View file

@ -1,3 +1,4 @@
import { OutputData } from "@editorjs/editorjs";
import { ChannelShippingData } from "@saleor/channels/utils";
import AppHeader from "@saleor/components/AppHeader";
import CardSpacer from "@saleor/components/CardSpacer";
@ -29,6 +30,7 @@ import ShippingZonePostalCodes from "../ShippingZonePostalCodes";
export interface FormData {
channelListings: ChannelShippingData[];
name: string;
description: OutputData;
noLimits: boolean;
minValue: string;
maxValue: string;
@ -87,13 +89,14 @@ export const ShippingZoneRatesCreatePage: React.FC<ShippingZoneRatesCreatePagePr
minDays: "",
minValue: "",
name: "",
description: null,
noLimits: false,
type: null
};
return (
<Form initial={initialForm} onSubmit={onSubmit}>
{({ change, data, hasChanged, submit, triggerChange }) => {
{({ change, data, hasChanged, submit, triggerChange, set }) => {
const handleChannelsChange = createChannelsChangeHandler(
shippingChannels,
onChannelsChange,
@ -102,6 +105,10 @@ export const ShippingZoneRatesCreatePage: React.FC<ShippingZoneRatesCreatePagePr
const formDisabled = data.channelListings?.some(channel =>
validatePrice(channel.price)
);
const onDescriptionChange = (description: OutputData) => {
set({ description });
triggerChange();
};
return (
<Container>
@ -128,6 +135,7 @@ export const ShippingZoneRatesCreatePage: React.FC<ShippingZoneRatesCreatePagePr
disabled={disabled}
errors={errors}
onChange={change}
onDescriptionChange={onDescriptionChange}
/>
<CardSpacer />
{isPriceVariant ? (

View file

@ -1,3 +1,4 @@
import { OutputData } from "@editorjs/editorjs";
import { ChannelShippingData } from "@saleor/channels/utils";
import AppHeader from "@saleor/components/AppHeader";
import CardSpacer from "@saleor/components/CardSpacer";
@ -39,6 +40,7 @@ import ShippingZonePostalCodes from "../ShippingZonePostalCodes";
export interface FormData extends MetadataFormData {
channelListings: ChannelShippingData[];
name: string;
description: OutputData;
noLimits: boolean;
minValue: string;
maxValue: string;
@ -108,6 +110,7 @@ export const ShippingZoneRatesPage: React.FC<ShippingZoneRatesPageProps> = ({
minDays: rate?.minimumDeliveryDays?.toString() || "",
minValue: rate?.minimumOrderWeight?.value.toString() || "",
name: rate?.name || "",
description: rate?.description && JSON.parse(rate.description),
noLimits: false,
privateMetadata: rate?.privateMetadata.map(mapMetadataItemToInput),
type: rate?.type || null
@ -119,7 +122,7 @@ export const ShippingZoneRatesPage: React.FC<ShippingZoneRatesPageProps> = ({
return (
<Form initial={initialForm} onSubmit={onSubmit}>
{({ change, data, hasChanged, submit, triggerChange }) => {
{({ change, data, hasChanged, submit, set, triggerChange }) => {
const handleChannelsChange = createChannelsChangeHandler(
shippingChannels,
onChannelsChange,
@ -128,6 +131,10 @@ export const ShippingZoneRatesPage: React.FC<ShippingZoneRatesPageProps> = ({
const formDisabled = data.channelListings?.some(channel =>
validatePrice(channel.price)
);
const onDescriptionChange = (description: OutputData) => {
set({ description });
triggerChange();
};
const changeMetadata = makeMetadataChangeHandler(change);
const formIsUnchanged =
@ -146,6 +153,7 @@ export const ShippingZoneRatesPage: React.FC<ShippingZoneRatesPageProps> = ({
disabled={disabled}
errors={errors}
onChange={change}
onDescriptionChange={onDescriptionChange}
/>
<CardSpacer />
{isPriceVariant ? (

View file

@ -1641,6 +1641,7 @@ export const shippingZone: ShippingZone_shippingZone = {
value: 0
},
name: "DB Schenker",
description: `{"time": 1618487908762, "blocks": [{"data": {"text": "General shipping method"}, "type": "paragraph"}], "version": "2.20.0"}`,
postalCodeRules: [
{
__typename: "ShippingMethodPostalCodeRule",
@ -1705,6 +1706,7 @@ export const shippingZone: ShippingZone_shippingZone = {
value: 0
},
name: "Registred priority",
description: `{"time": 1618487908762, "blocks": [{"data": {"text": "Priority shipping method"}, "type": "paragraph"}], "version": "2.20.0"}`,
postalCodeRules: [
{
__typename: "ShippingMethodPostalCodeRule",
@ -1769,6 +1771,7 @@ export const shippingZone: ShippingZone_shippingZone = {
value: 0
},
name: "UPS",
description: `{"time": 1618487908762, "blocks": [{"data": {"text": "Different shipping method"}, "type": "paragraph"}], "version": "2.20.0"}`,
postalCodeRules: [
{
__typename: "ShippingMethodPostalCodeRule",
@ -1820,6 +1823,7 @@ export const shippingZone: ShippingZone_shippingZone = {
value: 0
},
name: "DHL",
description: `{"time": 1618487908762, "blocks": [{"data": {"text": "Different shipping method"}, "type": "paragraph"}], "version": "2.20.0"}`,
postalCodeRules: [
{
__typename: "ShippingMethodPostalCodeRule",

View file

@ -13,6 +13,7 @@ import {
ShippingMethodTypeEnum,
ShippingPostalCodeRulesCreateInputRange
} from "@saleor/types/globalTypes";
import { getParsedDataForJsonStringField } from "@saleor/utils/richText/misc";
import { diff } from "fast-array-diff";
import { useIntl } from "react-intl";
@ -76,7 +77,8 @@ export function getCreateShippingPriceRateVariables(
minimumDeliveryDays: parsedMinDays,
name: data.name,
shippingZone: id,
type: ShippingMethodTypeEnum.PRICE
type: ShippingMethodTypeEnum.PRICE,
description: getParsedDataForJsonStringField(data.description)
}
};
}
@ -103,7 +105,8 @@ export function getCreateShippingWeightRateVariables(
minimumOrderWeight: isWeightSet ? parsedMinValue : null,
name: data.name,
shippingZone: id,
type: ShippingMethodTypeEnum.WEIGHT
type: ShippingMethodTypeEnum.WEIGHT,
description: getParsedDataForJsonStringField(data.description)
}
};
}
@ -130,7 +133,8 @@ export function getUpdateShippingPriceRateVariables(
minimumDeliveryDays: parsedMinDays,
name: data.name,
shippingZone: id,
type: ShippingMethodTypeEnum.PRICE
type: ShippingMethodTypeEnum.PRICE,
description: getParsedDataForJsonStringField(data.description)
}
};
}
@ -162,7 +166,8 @@ export function getUpdateShippingWeightRateVariables(
minimumOrderWeight: isWeightSet ? parsedMinValue : null,
name: data.name,
shippingZone: id,
type: ShippingMethodTypeEnum.WEIGHT
type: ShippingMethodTypeEnum.WEIGHT,
description: getParsedDataForJsonStringField(data.description)
}
};
}

View file

@ -110,6 +110,7 @@ export interface CreateShippingRate_shippingPriceCreate_shippingZone_shippingMet
minimumDeliveryDays: number | null;
maximumDeliveryDays: number | null;
name: string;
description: any | null;
type: ShippingMethodTypeEnum | null;
channelListings: CreateShippingRate_shippingPriceCreate_shippingZone_shippingMethods_channelListings[] | null;
}
@ -210,6 +211,7 @@ export interface CreateShippingRate_shippingPriceCreate_shippingMethod {
minimumDeliveryDays: number | null;
maximumDeliveryDays: number | null;
name: string;
description: any | null;
type: ShippingMethodTypeEnum | null;
channelListings: CreateShippingRate_shippingPriceCreate_shippingMethod_channelListings[] | null;
}

View file

@ -110,6 +110,7 @@ export interface DeleteShippingRate_shippingPriceDelete_shippingZone_shippingMet
minimumDeliveryDays: number | null;
maximumDeliveryDays: number | null;
name: string;
description: any | null;
type: ShippingMethodTypeEnum | null;
channelListings: DeleteShippingRate_shippingPriceDelete_shippingZone_shippingMethods_channelListings[] | null;
}

View file

@ -86,6 +86,7 @@ export interface ShippingMethodChannelListingUpdate_shippingMethodChannelListing
minimumDeliveryDays: number | null;
maximumDeliveryDays: number | null;
name: string;
description: any | null;
type: ShippingMethodTypeEnum | null;
channelListings: ShippingMethodChannelListingUpdate_shippingMethodChannelListingUpdate_shippingMethod_channelListings[] | null;
}

View file

@ -135,6 +135,7 @@ export interface ShippingZone_shippingZone_shippingMethods {
minimumDeliveryDays: number | null;
maximumDeliveryDays: number | null;
name: string;
description: any | null;
type: ShippingMethodTypeEnum | null;
channelListings: ShippingZone_shippingZone_shippingMethods_channelListings[] | null;
excludedProducts: ShippingZone_shippingZone_shippingMethods_excludedProducts | null;

View file

@ -92,6 +92,7 @@ export interface UpdateShippingRate_shippingPriceUpdate_shippingMethod {
minimumDeliveryDays: number | null;
maximumDeliveryDays: number | null;
name: string;
description: any | null;
type: ShippingMethodTypeEnum | null;
channelListings: UpdateShippingRate_shippingPriceUpdate_shippingMethod_channelListings[] | null;
}

View file

@ -193,7 +193,7 @@ export const PriceRatesUpdate: React.FC<PriceRatesUpdateProps> = ({
!loading &&
!state.postalCodeRules?.length &&
!state.codesToDelete?.length &&
rate.postalCodeRules?.length;
rate?.postalCodeRules?.length;
if (postalCodeRulesLoaded) {
dispatch({ postalCodeRules: rate.postalCodeRules });

View file

@ -110,7 +110,7 @@ export const WeightRatesUpdate: React.FC<WeightRatesUpdateProps> = ({
!loading &&
!state.postalCodeRules?.length &&
!state.codesToDelete?.length &&
rate.postalCodeRules?.length;
rate?.postalCodeRules?.length;
if (postalCodeRulesLoaded) {
dispatch({ postalCodeRules: rate.postalCodeRules });

View file

@ -18076,6 +18076,27 @@ exports[`Storyshots Shipping / ShippingZoneRatesCreatePage page create price 1`]
<div
class="CardSpacer-spacer-id"
/>
<div
class="MuiFormControl-root-id MuiFormControl-fullWidth-id"
data-test="richTextEditor"
data-test-id="description"
>
<label
class="MuiFormLabel-root-id MuiInputLabel-root-id MuiInputLabel-formControl-id MuiInputLabel-animated-id MuiInputLabel-shrink-id MuiInputLabel-outlined-id MuiFormLabel-focused-id MuiInputLabel-focused-id"
data-shrink="true"
>
Shipping Rate Description
</label>
<div
class="RichTextEditor-editor-id RichTextEditor-root-id"
/>
<p
class="MuiFormHelperText-root-id MuiFormHelperText-contained-id"
/>
</div>
<div
class="CardSpacer-spacer-id"
/>
<div
class="ShippingRateInfo-deliveryTimeFields-id"
>
@ -18978,6 +18999,27 @@ exports[`Storyshots Shipping / ShippingZoneRatesCreatePage page create weight 1`
<div
class="CardSpacer-spacer-id"
/>
<div
class="MuiFormControl-root-id MuiFormControl-fullWidth-id"
data-test="richTextEditor"
data-test-id="description"
>
<label
class="MuiFormLabel-root-id MuiInputLabel-root-id MuiInputLabel-formControl-id MuiInputLabel-animated-id MuiInputLabel-shrink-id MuiInputLabel-outlined-id MuiFormLabel-focused-id MuiInputLabel-focused-id"
data-shrink="true"
>
Shipping Rate Description
</label>
<div
class="RichTextEditor-editor-id RichTextEditor-root-id"
/>
<p
class="MuiFormHelperText-root-id MuiFormHelperText-contained-id"
/>
</div>
<div
class="CardSpacer-spacer-id"
/>
<div
class="ShippingRateInfo-deliveryTimeFields-id"
>
@ -19876,6 +19918,27 @@ exports[`Storyshots Shipping / ShippingZoneRatesCreatePage page loading 1`] = `
<div
class="CardSpacer-spacer-id"
/>
<div
class="MuiFormControl-root-id MuiFormControl-fullWidth-id"
data-test="richTextEditor"
data-test-id="description"
>
<label
class="MuiFormLabel-root-id MuiInputLabel-root-id MuiInputLabel-formControl-id MuiInputLabel-animated-id MuiInputLabel-shrink-id MuiInputLabel-outlined-id MuiFormLabel-disabled-id MuiInputLabel-disabled-id MuiFormLabel-focused-id MuiInputLabel-focused-id"
data-shrink="true"
>
Shipping Rate Description
</label>
<div
class="RichTextEditor-editor-id RichTextEditor-root-id RichTextEditor-rootDisabled-id"
/>
<p
class="MuiFormHelperText-root-id MuiFormHelperText-contained-id MuiFormHelperText-disabled-id"
/>
</div>
<div
class="CardSpacer-spacer-id"
/>
<div
class="ShippingRateInfo-deliveryTimeFields-id"
>
@ -222010,6 +222073,27 @@ exports[`Storyshots Views / Shipping / Shipping rate create price rate 1`] = `
<div
class="CardSpacer-spacer-id"
/>
<div
class="MuiFormControl-root-id MuiFormControl-fullWidth-id"
data-test="richTextEditor"
data-test-id="description"
>
<label
class="MuiFormLabel-root-id MuiInputLabel-root-id MuiInputLabel-formControl-id MuiInputLabel-animated-id MuiInputLabel-shrink-id MuiInputLabel-outlined-id MuiFormLabel-focused-id MuiInputLabel-focused-id"
data-shrink="true"
>
Shipping Rate Description
</label>
<div
class="RichTextEditor-editor-id RichTextEditor-root-id"
/>
<p
class="MuiFormHelperText-root-id MuiFormHelperText-contained-id"
/>
</div>
<div
class="CardSpacer-spacer-id"
/>
<div
class="ShippingRateInfo-deliveryTimeFields-id"
>
@ -223242,6 +223326,27 @@ exports[`Storyshots Views / Shipping / Shipping rate create weight rate 1`] = `
<div
class="CardSpacer-spacer-id"
/>
<div
class="MuiFormControl-root-id MuiFormControl-fullWidth-id"
data-test="richTextEditor"
data-test-id="description"
>
<label
class="MuiFormLabel-root-id MuiInputLabel-root-id MuiInputLabel-formControl-id MuiInputLabel-animated-id MuiInputLabel-shrink-id MuiInputLabel-outlined-id MuiFormLabel-focused-id MuiInputLabel-focused-id"
data-shrink="true"
>
Shipping Rate Description
</label>
<div
class="RichTextEditor-editor-id RichTextEditor-root-id"
/>
<p
class="MuiFormHelperText-root-id MuiFormHelperText-contained-id"
/>
</div>
<div
class="CardSpacer-spacer-id"
/>
<div
class="ShippingRateInfo-deliveryTimeFields-id"
>
@ -224392,6 +224497,27 @@ exports[`Storyshots Views / Shipping / Shipping rate loading 1`] = `
<div
class="CardSpacer-spacer-id"
/>
<div
class="MuiFormControl-root-id MuiFormControl-fullWidth-id"
data-test="richTextEditor"
data-test-id="description"
>
<label
class="MuiFormLabel-root-id MuiInputLabel-root-id MuiInputLabel-formControl-id MuiInputLabel-animated-id MuiInputLabel-shrink-id MuiInputLabel-outlined-id MuiFormLabel-disabled-id MuiInputLabel-disabled-id MuiFormLabel-focused-id MuiInputLabel-focused-id"
data-shrink="true"
>
Shipping Rate Description
</label>
<div
class="RichTextEditor-editor-id RichTextEditor-root-id RichTextEditor-rootDisabled-id"
/>
<p
class="MuiFormHelperText-root-id MuiFormHelperText-contained-id MuiFormHelperText-disabled-id"
/>
</div>
<div
class="CardSpacer-spacer-id"
/>
<div
class="ShippingRateInfo-deliveryTimeFields-id"
>
@ -225462,6 +225588,27 @@ exports[`Storyshots Views / Shipping / Shipping rate update price rate 1`] = `
<div
class="CardSpacer-spacer-id"
/>
<div
class="MuiFormControl-root-id MuiFormControl-fullWidth-id"
data-test="richTextEditor"
data-test-id="description"
>
<label
class="MuiFormLabel-root-id MuiInputLabel-root-id MuiInputLabel-formControl-id MuiInputLabel-animated-id MuiInputLabel-shrink-id MuiInputLabel-outlined-id MuiFormLabel-focused-id MuiInputLabel-focused-id"
data-shrink="true"
>
Shipping Rate Description
</label>
<div
class="RichTextEditor-editor-id RichTextEditor-root-id"
/>
<p
class="MuiFormHelperText-root-id MuiFormHelperText-contained-id"
/>
</div>
<div
class="CardSpacer-spacer-id"
/>
<div
class="ShippingRateInfo-deliveryTimeFields-id"
>
@ -226884,6 +227031,27 @@ exports[`Storyshots Views / Shipping / Shipping rate update weight rate 1`] = `
<div
class="CardSpacer-spacer-id"
/>
<div
class="MuiFormControl-root-id MuiFormControl-fullWidth-id"
data-test="richTextEditor"
data-test-id="description"
>
<label
class="MuiFormLabel-root-id MuiInputLabel-root-id MuiInputLabel-formControl-id MuiInputLabel-animated-id MuiInputLabel-shrink-id MuiInputLabel-outlined-id MuiFormLabel-focused-id MuiInputLabel-focused-id"
data-shrink="true"
>
Shipping Rate Description
</label>
<div
class="RichTextEditor-editor-id RichTextEditor-root-id"
/>
<p
class="MuiFormHelperText-root-id MuiFormHelperText-contained-id"
/>
</div>
<div
class="CardSpacer-spacer-id"
/>
<div
class="ShippingRateInfo-deliveryTimeFields-id"
>

View file

@ -4,7 +4,10 @@ import LanguageSwitch from "@saleor/components/LanguageSwitch";
import PageHeader from "@saleor/components/PageHeader";
import { ShippingMethodTranslationFragment } from "@saleor/fragments/types/ShippingMethodTranslationFragment";
import { commonMessages, sectionNames } from "@saleor/intl";
import { TranslationsEntitiesPageProps } from "@saleor/translations/types";
import {
TranslationInputFieldName,
TranslationsEntitiesPageProps
} from "@saleor/translations/types";
import React from "react";
import { useIntl } from "react-intl";
@ -16,10 +19,6 @@ export interface TranslationsShippingMethodPageProps
data: ShippingMethodTranslationFragment;
}
export const fieldNames = {
name: "name"
};
const TranslationsShippingMethodPage: React.FC<TranslationsShippingMethodPageProps> = ({
activeField,
disabled,
@ -67,12 +66,23 @@ const TranslationsShippingMethodPage: React.FC<TranslationsShippingMethodPagePro
fields={[
{
displayName: intl.formatMessage({
defaultMessage: "ShippingMethod Name"
defaultMessage: "Name",
description: "shipping method name"
}),
name: fieldNames.name,
name: TranslationInputFieldName.name,
translation: data?.translation?.name || null,
type: "short" as "short",
value: data?.name
},
{
displayName: intl.formatMessage({
defaultMessage: "Description",
description: "shipping method description"
}),
name: TranslationInputFieldName.description,
translation: data?.translation?.description || null,
type: "rich",
value: data?.description
}
]}
saveButtonState={saveButtonState}

View file

@ -293,7 +293,7 @@ export const TypedUpdateAttributeValueTranslations = TypedMutation<
const updateShippingMethodTranslations = gql`
mutation UpdateShippingMethodTranslations(
$id: ID!
$input: NameTranslationInput!
$input: ShippingPriceTranslationInput!
$language: LanguageCodeEnum!
) {
shippingPriceTranslate(id: $id, input: $input, languageCode: $language) {
@ -304,12 +304,14 @@ const updateShippingMethodTranslations = gql`
shippingMethod {
id
name
description
translation(languageCode: $language) {
id
language {
language
}
name
description
}
}
}

View file

@ -29,13 +29,15 @@ export interface ShippingMethodTranslationDetails_translation_ShippingMethodTran
id: string;
language: ShippingMethodTranslationDetails_translation_ShippingMethodTranslatableContent_translation_language;
name: string | null;
description: any | null;
}
export interface ShippingMethodTranslationDetails_translation_ShippingMethodTranslatableContent {
__typename: "ShippingMethodTranslatableContent";
shippingMethod: ShippingMethodTranslationDetails_translation_ShippingMethodTranslatableContent_shippingMethod | null;
id: string;
name: string;
description: any | null;
shippingMethod: ShippingMethodTranslationDetails_translation_ShippingMethodTranslatableContent_shippingMethod | null;
translation: ShippingMethodTranslationDetails_translation_ShippingMethodTranslatableContent_translation | null;
}

View file

@ -29,13 +29,15 @@ export interface ShippingMethodTranslations_translations_edges_node_ShippingMeth
id: string;
language: ShippingMethodTranslations_translations_edges_node_ShippingMethodTranslatableContent_translation_language;
name: string | null;
description: any | null;
}
export interface ShippingMethodTranslations_translations_edges_node_ShippingMethodTranslatableContent {
__typename: "ShippingMethodTranslatableContent";
shippingMethod: ShippingMethodTranslations_translations_edges_node_ShippingMethodTranslatableContent_shippingMethod | null;
id: string;
name: string;
description: any | null;
shippingMethod: ShippingMethodTranslations_translations_edges_node_ShippingMethodTranslatableContent_shippingMethod | null;
translation: ShippingMethodTranslations_translations_edges_node_ShippingMethodTranslatableContent_translation | null;
}

View file

@ -3,7 +3,7 @@
// @generated
// This file was automatically generated and should not be edited.
import { NameTranslationInput, LanguageCodeEnum } from "./../../types/globalTypes";
import { ShippingPriceTranslationInput, LanguageCodeEnum } from "./../../types/globalTypes";
// ====================================================
// GraphQL mutation operation: UpdateShippingMethodTranslations
@ -25,12 +25,14 @@ export interface UpdateShippingMethodTranslations_shippingPriceTranslate_shippin
id: string;
language: UpdateShippingMethodTranslations_shippingPriceTranslate_shippingMethod_translation_language;
name: string | null;
description: any | null;
}
export interface UpdateShippingMethodTranslations_shippingPriceTranslate_shippingMethod {
__typename: "ShippingMethod";
id: string;
name: string;
description: any | null;
translation: UpdateShippingMethodTranslations_shippingPriceTranslate_shippingMethod_translation | null;
}
@ -46,6 +48,6 @@ export interface UpdateShippingMethodTranslations {
export interface UpdateShippingMethodTranslationsVariables {
id: string;
input: NameTranslationInput;
input: ShippingPriceTranslationInput;
language: LanguageCodeEnum;
}

View file

@ -34,6 +34,7 @@ export interface VoucherTranslationDetails_translation_VoucherTranslatableConten
export interface VoucherTranslationDetails_translation_VoucherTranslatableContent {
__typename: "VoucherTranslatableContent";
name: string | null;
voucher: VoucherTranslationDetails_translation_VoucherTranslatableContent_voucher | null;
translation: VoucherTranslationDetails_translation_VoucherTranslatableContent_translation | null;
}

View file

@ -34,6 +34,7 @@ export interface VoucherTranslations_translations_edges_node_VoucherTranslatable
export interface VoucherTranslations_translations_edges_node_VoucherTranslatableContent {
__typename: "VoucherTranslatableContent";
name: string | null;
voucher: VoucherTranslations_translations_edges_node_VoucherTranslatableContent_voucher | null;
translation: VoucherTranslations_translations_edges_node_VoucherTranslatableContent_translation | null;
}

View file

@ -1,4 +1,5 @@
import { OutputData } from "@editorjs/editorjs";
import { getParsedDataForJsonStringField } from "@saleor/utils/richText/misc";
import {
PageTranslationInputFieldName,
@ -25,7 +26,3 @@ export const getParsedTranslationInputData = ({
return { [fieldName]: data as string };
};
export const getParsedDataForJsonStringField = (
data: OutputData
): string | null => (!!data.blocks?.length ? JSON.stringify(data) : null);

View file

@ -32,6 +32,9 @@ interface TranslationsEntitiesProps {
params: LanguageEntitiesUrlQueryParams;
}
const sumCompleted = (list: any[]) =>
list.reduce((acc, field) => acc + (field ? 1 : 0), 0);
const TranslationsEntities: React.FC<TranslationsEntitiesProps> = ({
language,
params
@ -145,17 +148,12 @@ const TranslationsEntities: React.FC<TranslationsEntitiesProps> = ({
node =>
node.__typename === "CategoryTranslatableContent" && {
completion: {
current: node.translation
? [
node.translation.description,
node.translation.name,
node.translation.seoDescription,
node.translation.seoTitle
].reduce(
(acc, field) => acc + (field !== null ? 1 : 0),
0
)
: 0,
current: sumCompleted([
node.translation?.description,
node.translation?.name,
node.translation?.seoDescription,
node.translation?.seoTitle
]),
max: 4
},
id: node?.category?.id,
@ -195,17 +193,12 @@ const TranslationsEntities: React.FC<TranslationsEntitiesProps> = ({
node =>
node.__typename === "ProductTranslatableContent" && {
completion: {
current: node.translation
? [
node.translation.description,
node.translation.name,
node.translation.seoDescription,
node.translation.seoTitle
].reduce(
(acc, field) => acc + (field !== null ? 1 : 0),
0
)
: 0,
current: sumCompleted([
node.translation?.description,
node.translation?.name,
node.translation?.seoDescription,
node.translation?.seoTitle
]),
max: 4
},
id: node?.product?.id,
@ -246,17 +239,12 @@ const TranslationsEntities: React.FC<TranslationsEntitiesProps> = ({
node =>
node.__typename === "CollectionTranslatableContent" && {
completion: {
current: node.translation
? [
node.translation.description,
node.translation.name,
node.translation.seoDescription,
node.translation.seoTitle
].reduce(
(acc, field) => acc + (field !== null ? 1 : 0),
0
)
: 0,
current: sumCompleted([
node.translation?.description,
node.translation?.name,
node.translation?.seoDescription,
node.translation?.seoTitle
]),
max: 4
},
id: node.collection.id,
@ -297,9 +285,7 @@ const TranslationsEntities: React.FC<TranslationsEntitiesProps> = ({
node =>
node.__typename === "SaleTranslatableContent" && {
completion: {
current: node.translation
? +!!node.translation.name
: 0,
current: sumCompleted([node.translation?.name]),
max: 1
},
id: node.sale?.id,
@ -340,9 +326,7 @@ const TranslationsEntities: React.FC<TranslationsEntitiesProps> = ({
node =>
node.__typename === "VoucherTranslatableContent" && {
completion: {
current: node.translation
? +!!node.translation.name
: 0,
current: sumCompleted([node.translation?.name]),
max: 1
},
id: node.voucher?.id,
@ -383,17 +367,12 @@ const TranslationsEntities: React.FC<TranslationsEntitiesProps> = ({
node =>
node.__typename === "PageTranslatableContent" && {
completion: {
current: node.translation
? [
node.translation.content,
node.translation.seoDescription,
node.translation.seoTitle,
node.translation.title
].reduce(
(acc, field) => acc + (field !== null ? 1 : 0),
0
)
: 0,
current: sumCompleted([
node.translation?.content,
node.translation?.seoDescription,
node.translation?.seoTitle,
node.translation?.title
]),
max: 4
},
id: node?.page.id,
@ -429,14 +408,12 @@ const TranslationsEntities: React.FC<TranslationsEntitiesProps> = ({
node =>
node.__typename === "AttributeTranslatableContent" && {
completion: {
current: node.translation
? +!!node.translation.name +
node.attribute.values.reduce(
(acc, attr) =>
acc + (!!attr.translation?.name ? 1 : 0),
0
)
: 0,
current: sumCompleted([
node.translation?.name,
...(node.attribute?.values.map(
attr => attr.translation?.name
) || [])
]),
max: node.attribute
? node.attribute.values.length + 1
: 0
@ -479,10 +456,11 @@ const TranslationsEntities: React.FC<TranslationsEntitiesProps> = ({
node.__typename ===
"ShippingMethodTranslatableContent" && {
completion: {
current: node.translation
? +!!node.translation.name
: 0,
max: 1
current: sumCompleted([
node.translation?.name,
node.translation?.description
]),
max: 2
},
id: node?.shippingMethod.id,
name: node?.name

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 TranslationsShippingMethodPage, {
fieldNames
} from "../components/TranslationsShippingMethodPage";
import { LanguageCodeEnum } from "../../types/globalTypes";
import TranslationsShippingMethodPage from "../components/TranslationsShippingMethodPage";
import { TypedUpdateShippingMethodTranslations } from "../mutations";
import { useShippingMethodTranslationDetails } from "../queries";
import { TranslationInputFieldName } from "../types";
import { UpdateShippingMethodTranslations } from "../types/UpdateShippingMethodTranslations";
import {
languageEntitiesUrl,
languageEntityUrl,
TranslatableEntities
} from "../urls";
import { getParsedTranslationInputData } from "../utils";
export interface TranslationsShippingMethodQueryParams {
activeField: string;
@ -70,15 +67,14 @@ const TranslationsShippingMethod: React.FC<TranslationsShippingMethodProps> = ({
return (
<TypedUpdateShippingMethodTranslations onCompleted={onUpdate}>
{(updateTranslations, updateTranslationsOpts) => {
const handleSubmit = (field: string, data: string) => {
const input: NameTranslationInput = {};
if (field === fieldNames.name) {
input.name = data;
}
const handleSubmit = (
field: TranslationInputFieldName,
data: string
) => {
updateTranslations({
variables: {
id,
input,
input: getParsedTranslationInputData({ fieldName: field, data }),
language: languageCode
}
});

View file

@ -1093,6 +1093,7 @@ export interface AttributeFilterInput {
filterableInStorefront?: boolean | null;
filterableInDashboard?: boolean | null;
availableInGrid?: boolean | null;
metadata?: (MetadataInput | null)[] | null;
search?: string | null;
ids?: (string | null)[] | null;
type?: AttributeTypeEnum | null;
@ -1159,6 +1160,7 @@ export interface CatalogueInput {
export interface CategoryFilterInput {
search?: string | null;
metadata?: (MetadataInput | null)[] | null;
ids?: (string | null)[] | null;
}
@ -1217,6 +1219,7 @@ export interface CollectionCreateInput {
export interface CollectionFilterInput {
published?: CollectionPublished | null;
search?: string | null;
metadata?: (MetadataInput | null)[] | null;
ids?: (string | null)[] | null;
channel?: string | null;
}
@ -1258,6 +1261,7 @@ export interface CustomerInput {
email?: string | null;
isActive?: boolean | null;
note?: string | null;
languageCode?: LanguageCodeEnum | null;
}
export interface DateRangeInput {
@ -1384,6 +1388,7 @@ export interface OrderDraftFilterInput {
customer?: string | null;
created?: DateRangeInput | null;
search?: string | null;
metadata?: (MetadataInput | null)[] | null;
channels?: (string | null)[] | null;
}
@ -1393,6 +1398,7 @@ export interface OrderFilterInput {
customer?: string | null;
created?: DateRangeInput | null;
search?: string | null;
metadata?: (MetadataInput | null)[] | null;
channels?: (string | null)[] | null;
}
@ -1620,6 +1626,7 @@ export interface ProductFilterInput {
productType?: string | null;
stocks?: ProductStockFilterInput | null;
search?: string | null;
metadata?: (MetadataInput | null)[] | null;
price?: PriceRangeInput | null;
minimalPrice?: PriceRangeInput | null;
productTypes?: (string | null)[] | null;
@ -1657,6 +1664,7 @@ export interface ProductTypeFilterInput {
search?: string | null;
configurable?: ProductTypeConfigurable | null;
productType?: ProductTypeEnum | null;
metadata?: (MetadataInput | null)[] | null;
ids?: (string | null)[] | null;
}
@ -1781,6 +1789,7 @@ export interface ShippingPriceExcludeProductsInput {
export interface ShippingPriceInput {
name?: string | null;
description?: any | null;
minimumOrderWeight?: any | null;
maximumOrderWeight?: any | null;
maximumDeliveryDays?: number | null;
@ -1792,6 +1801,11 @@ export interface ShippingPriceInput {
inclusionType?: PostalCodeRuleInclusionTypeEnum | null;
}
export interface ShippingPriceTranslationInput {
name?: string | null;
description?: any | null;
}
export interface ShippingZoneCreateInput {
name?: string | null;
description?: string | null;
@ -1878,6 +1892,7 @@ export interface UserCreateInput {
email?: string | null;
isActive?: boolean | null;
note?: string | null;
languageCode?: LanguageCodeEnum | null;
redirectUrl?: string | null;
}

View file

@ -0,0 +1,5 @@
import { OutputData } from "@editorjs/editorjs";
export const getParsedDataForJsonStringField = (
data: OutputData
): string | null => (data?.blocks?.length ? JSON.stringify(data) : null);