diff --git a/ui/src/components/DestinationStack/Actions/LoadLanguageMapper.tsx b/ui/src/components/DestinationStack/Actions/LoadLanguageMapper.tsx new file mode 100644 index 000000000..23c302040 --- /dev/null +++ b/ui/src/components/DestinationStack/Actions/LoadLanguageMapper.tsx @@ -0,0 +1,474 @@ +// Import library +import { + Button, + CircularLoader, + Icon, + Info, + MiniScrollableTable, + Select, + Tooltip +} from '@contentstack/venus-components'; +import { useEffect, useState } from 'react'; +import TableHeader from './tableHeader'; +import { useDispatch, useSelector } from 'react-redux'; +import { RootState } from '../../../store'; +import { updateNewMigrationData } from '../../../store/slice/migrationDataSlice'; +import { INewMigration } from '../../../context/app/app.interface'; + +export type ExistingFieldType = { + [key: string]: { label: string ; value: string }; +}; + +/** + * A functional component that displays selection for language mapping. + * + * @param {Array<{ label: string; value: string }>} cmsLocaleOptions - An array to dispaly number of locales select. + * @param {Function} handleLangugeDelete - a function to delete the mapping. + * @param {Array<{ label: string; value: string }>} options - option array of contentstack locales. + * @param {Array<{ label: string; value: string }>} sourceOptions - option array of source locales. + * @returns {JSX.Element | null} - Returns a JSX element if empty, otherwise null. + */ +const Mapper = ({ + cmsLocaleOptions, + handleLangugeDelete, + options, + sourceOptions +}: { + cmsLocaleOptions: Array<{ label: string; value: string }>; + handleLangugeDelete: (index: number, locale: { label: string; value: string }) => void; + options: Array<{ label: string; value: string }>; + sourceOptions: Array<{ label: string; value: string }>; +}) => { + const [selectedMappings, setSelectedMappings] = useState<{ [key: string]: string }>({}); + const [existingField, setExistingField] = useState({}); + const [existingLocale, setexistingLocale] = useState({}); + const [selectedCsOptions, setselectedCsOption] = useState([]); + const [selectedSourceOption, setselectedSourceOption] = useState([]); + const [csOptions, setcsOptions] = useState(options); + const [sourceoptions, setsourceoptions] = useState(sourceOptions); + const newMigrationData = useSelector((state: RootState) => state?.migration?.newMigrationData); + const dispatch = useDispatch(); + const [placeholder] = useState('Select language'); + + useEffect(() => { + const newMigrationDataObj: INewMigration = { + ...newMigrationData, + destination_stack: { + ...newMigrationData?.destination_stack, + localeMapping: selectedMappings + } + }; + + dispatch(updateNewMigrationData(newMigrationDataObj)); + }, [selectedMappings]); + + useEffect(() => { + if (selectedCsOptions?.length === 0) { + setcsOptions(options); + } + }, [options]); + + useEffect(() => { + if (selectedSourceOption?.length === 0) { + setsourceoptions(sourceOptions); + } + }, [sourceOptions]); + + useEffect(() => { + const formattedoptions = options?.filter( + (item: { label: string; value: string }) => !selectedCsOptions?.some((selected: string) => selected === item?.value) + ); + const adjustedOptions = sourceOptions?.filter( + (item: { label: string; value: string }) => !selectedSourceOption?.some((selected: string) => selected === item?.label) + ); + setcsOptions(formattedoptions); + setsourceoptions(adjustedOptions); + }, [selectedCsOptions, selectedSourceOption]); + + useEffect(() => { + setExistingField((prevExisting: ExistingFieldType) => { + const updatedExisting = { ...prevExisting }; + + cmsLocaleOptions?.forEach((locale: { label: string; value: string }, index: number) => { + if (locale?.value === 'master_locale' && !updatedExisting?.[index]) { + setSelectedMappings((prev) => ({ + ...prev, + [`${locale?.label}-master_locale`]: '' + })); + updatedExisting[index] = { label: locale?.label, value: `${locale?.label}-master_locale` }; + } + }); + + return updatedExisting; + }); + }, [cmsLocaleOptions]); + + // function for change select value + const handleSelectedCsLocale = ( + selectedValue: { label: string; value: string }, + index: number, + type: 'csLocale' | 'sourceLocale' + ) => { + const selectedLocaleKey = selectedValue?.value; + if (!selectedLocaleKey) return; + + setExistingField((prevOptions: ExistingFieldType) => { + const updatedOptions = { + ...prevOptions, + [index]: { label: selectedValue?.label || null, value: selectedValue?.label } + }; + // setselectedOption((prevSelected) => + // prevSelected.filter((item) => + // Object.values(updatedOptions).some((opt: any) => opt.label === item) + // ) + // ); + + return updatedOptions; + }); + setselectedCsOption((prevSelected) => { + const newSelectedOptions: string[] = prevSelected?.filter((item) => item !== selectedValue?.label); + const newValue: string = selectedValue?.label; + if (!newSelectedOptions?.includes(newValue)) { + newSelectedOptions.push(newValue); + } + return newSelectedOptions; + }); + + setSelectedMappings((prev) => { + const updatedMappings = { ...prev }; + + if (type === 'csLocale') { + updatedMappings[selectedLocaleKey] = existingLocale[index]?.label + ? existingLocale[index]?.label + : ''; + } + + return updatedMappings; + }); + }; + const handleSelectedSourceLocale = ( + selectedValue: { label: string; value: string }, + index: number, + type: 'csLocale' | 'sourceLocale', + label: any + ) => { + const csLocaleKey = existingField?.[index]?.value; + + //const selectedLocaleKey = selectedMappings[index]; + + if (!selectedValue?.label) { + setselectedSourceOption((prevSelected) => + prevSelected?.filter((item) => item !== existingField?.[index]?.label) + ); + } + setexistingLocale((prevOptions: ExistingFieldType) => { + const updatedOptions: ExistingFieldType = { + ...prevOptions, + [index]: { label: selectedValue?.label || null, value: selectedValue?.label } + }; + + // Ensure selectedOption only contains values that exist in updatedOptions + setselectedSourceOption((prevSelected) => + prevSelected?.filter((item) => + Object.values(updatedOptions)?.some((opt: {label: string, value: string}) => opt?.label === item) + ) + ); + + return updatedOptions; + }); + + setselectedSourceOption((prevSelected) => { + const newSelectedOptions = prevSelected?.filter((item) => item !== selectedValue?.label); + const newValue: string = selectedValue?.label; + if (!newSelectedOptions?.includes(newValue)) { + newSelectedOptions?.push(newValue); + } + return newSelectedOptions; + }); + + csLocaleKey && + setSelectedMappings((prev) => ({ + ...prev, + [csLocaleKey]: selectedValue?.label || '' + })); + }; + const handleLanguageDeletaion = (index: number, locale: {label: string, value: string}) => { + + // Remove item at index from existingField + let csLocale = ''; + + setExistingField( + (prevOptions: Record | undefined) => { + if (!prevOptions) return {}; // Ensure it's an object + + const updatedOptions = { ...prevOptions }; // Create a shallow copy + csLocale = updatedOptions[index]?.label; + delete updatedOptions[index]; // Remove the key + + return updatedOptions; + } + ); + + // Remove item at index from existingLocale + setexistingLocale((prevLocales: ExistingFieldType) => { + if (!prevLocales) return {}; + const updatedOptions = { ...prevLocales }; // Create a shallow copy + delete updatedOptions[index]; // Remove the key + return updatedOptions; + }); + + setSelectedMappings((prev) => { + const updatedMappings = { ...prev }; + + delete updatedMappings[csLocale]; + + return updatedMappings; + }); + + handleLangugeDelete(index, locale); + }; + + return ( + <> + {cmsLocaleOptions?.length > 0 ? ( + cmsLocaleOptions?.map((locale: any, index: number) => ( +
+ {locale?.value === 'master_locale' ? ( + +
+ { + handleSelectedCsLocale(key, index, 'csLocale'); + }} + options={csOptions} + placeholder={placeholder} + isSearchable + maxMenuHeight={150} + multiDisplayLimit={5} + menuPortalTarget={document.querySelector('.language-mapper')} + width="270px" + version="v2" + hideSelectedOptions={true} + isClearable={true} + isDisabled={false} + className="select-container" + /> + )} + - + { + /* + handleSelectedSourceLocale(data, index, 'sourceLocale', locale) + } + options={sourceoptions} + placeholder={placeholder} + isSearchable + maxMenuHeight={150} + multiDisplayLimit={5} + menuPortalTarget={document.querySelector('.language-mapper')} + width="270px" + version="v2" + hideSelectedOptions={true} + isClearable={true} + isDisabled={false} + className="select-container" + /> + } +
+ {locale?.value !== 'master_locale' && ( + + { + handleLanguageDeletaion(index, locale); + }} + hover + hoverType="secondary" + shadow="medium" + /> + + )} +
+
+ )) + ) : ( + } + //version="v2" + content="No langauges configured" + type="light" + /> + )} + + ); +}; + +const LanguageMapper = () => { + const newMigrationData = useSelector((state: RootState) => state?.migration?.newMigrationData); + const [options, setoptions] = useState<{ label: string; value: string }[]>([]); + const [cmsLocaleOptions, setcmsLocaleOptions] = useState<{ label: string; value: string }[]>([]); + const [sourceLocales, setsourceLocales] = useState<{ label: string; value: string }[]>([]); + const [isLoading, setisLoading] = useState(false); + + useEffect(() => { + const fetchData = async () => { + try { + setisLoading(true); + const allLocales: { label: string; value: string }[] = Object.entries( + newMigrationData?.destination_stack?.csLocale ?? {} + ).map(([key]) => ({ + label: key, + value: key + })); + const sourceLocale = newMigrationData?.destination_stack?.sourceLocale?.map((item) => ({ + label: item, + value: item + })); + setsourceLocales(sourceLocale); + + setoptions(allLocales); + setcmsLocaleOptions((prevList: { label: string; value: string }[]) => { + const newLabel = newMigrationData?.destination_stack?.selectedStack?.master_locale; + + const isPresent = prevList.some((item: { label: string; value: string }) => item?.value === 'master_locale'); + + if (!isPresent) { + return [ + ...prevList, + { + label: newLabel, + value: 'master_locale' + } + ]; + } + + return prevList; + }); + setisLoading(false); + } catch (error) { + console.error('Error fetching locales:', error); + } + }; + + fetchData(); + }, []); + + // const fetchLocales = async () => { + // return await getStackLocales(newMigrationData?.destination_stack?.selectedOrg?.value); + // }; + const addRowComp = () => { + setcmsLocaleOptions((prevList: { label: string; value: string }[]) => [ + ...prevList, // Keep existing elements + { + label: `${prevList.length + 1}`, // Generate new label + value: '' + } + ]); + }; + + const handleDeleteLocale = (id: number, locale: { label: string; value: string }) => { + setcmsLocaleOptions((prevList) => { + return prevList?.filter((item: { label: string; value: string }) => item?.label !== locale?.label); + }); + }; + + return ( +
+ {isLoading ? ( + + ) : ( + <> + + } + rowComponent={ + + } + // footerComponent={ + // + + // } + type="Secondary" + /> + + + )} +
+ ); +}; + +export default LanguageMapper; diff --git a/ui/src/components/DestinationStack/Actions/singleRowComp.tsx b/ui/src/components/DestinationStack/Actions/singleRowComp.tsx new file mode 100644 index 000000000..7a1bd711c --- /dev/null +++ b/ui/src/components/DestinationStack/Actions/singleRowComp.tsx @@ -0,0 +1,77 @@ +/* Import React modules */ +import React, { useState } from "react"; +/* Import other node modules */ +import { Select, Tooltip, Icon } from "@contentstack/venus-components"; +/* Import our modules */ +//import { TypeMultiSelectObj, TypeSingleRowComp } from "../../common/types"; +//import localeTexts from "../locale/en-us"; +/* Import node module CSS */ +/* Import our CSS */ + +const SingleRowComp: React.FC = function () { + const [contentTypes, setContentTypes] = useState(); + const [metaFields, setMetaFields] = useState(); + + const saveData = () => { + if (contentTypes?.length && metaFields?.length) { + const contentTypesData = contentTypes.map( + (item: any) => item?.label + ); + const metaFieldsData = metaFields.map( + (item: any) => item?.label + ); + // setList([ + // ...list, + // { content_types: contentTypesData, meta_fields: metaFieldsData }, + // ]); + // setContentTypes([]); + // setMetaFields([]); + // removeRowComp(); + } + }; + + return ( +
+ + + + +
+ ); +}; + +export default SingleRowComp; diff --git a/ui/src/components/DestinationStack/Actions/tableHeader.tsx b/ui/src/components/DestinationStack/Actions/tableHeader.tsx new file mode 100644 index 000000000..9f7c92190 --- /dev/null +++ b/ui/src/components/DestinationStack/Actions/tableHeader.tsx @@ -0,0 +1,30 @@ +// Importing Library +import { FieldLabel } from "@contentstack/venus-components"; + +// TableHeader component of language-mapper tabel +const TableHeader = ({cms}:{cms:string}) => { + return ( +
+ + Contentstack + + +
+ + {cms} + +
+
+ ); +} +export default TableHeader; \ No newline at end of file diff --git a/ui/src/components/DestinationStack/DestinationStack.scss b/ui/src/components/DestinationStack/DestinationStack.scss index cfe630cec..a4650b1a9 100644 --- a/ui/src/components/DestinationStack/DestinationStack.scss +++ b/ui/src/components/DestinationStack/DestinationStack.scss @@ -45,7 +45,13 @@ border-radius: 4px; } .destination-stack-container { - padding: 20px; + padding-left: 25px !important; + padding-top: 26px; + padding-right: 30px; + + overflow-y: auto; + overflow-x: hidden; + max-height: 80vh; .migration-vertical-stepper { padding: 24px 30px; border: 1px solid $color-brand-secondary-lightest; @@ -156,8 +162,15 @@ color: $color-brand-warning-medium; font-size: $size-font-small; } - - + .table-content-section { + .Field { + &.Field--full { + .field-content { + border-left: none !important; + } + } + } + } } } .action-summary-wrapper { @@ -175,7 +188,6 @@ } } - .locale-container { display: flex; background-color: $color-base-white-5; @@ -183,3 +195,76 @@ align-items: center; padding: $px-10; } +.lang-container { + //display: flex; + //flex-wrap: wrap; + //padding: $px-20; + //padding-bottom: 50px; +} +.language-mapper { + //padding-top:20px; + //margin-top: 20px; + //padding: 24px 30px; + // height: 150px; + border: 1px solid $color-brand-secondary-lightest; + border-radius: 4px; + background-color: $color-brand-white-base; + white-space: nowrap; + //z-index: 999 !important; + // min-height: auto; + // max-height: none; + // overflow: visible; + // flex-grow: 1; + height: auto; + margin-bottom: 120px; + //padding: 24px 30px, 24px, 30px; + gap: 24px; + //margin-bottom: 40px; + //padding: 10px 50px; + .table-content-section { + .Field { + &.Field--full { + .field-content { + width: 100% !important; + //border-left: none !important; + } + } + } + } + .span { + padding: 10px 20px; + } + .field-label { + padding: 10px 10px; + } +} + +.language-title { + margin-top: 10px; + //margin-left: 2px; +} +.info-lang { + display: flex; + gap: 10px; +} +.help-text { + margin-top: -5px; + margin-left: 0px; +} +.mini-table { + margin-left: 40px; + margin-top: 10px; + //width: 120px; +} +.lang-container { + margin-bottom: 30px; + margin-left: 10px; + margin-top: 10px; + display: flex; +} +.info-tag { + max-width: 500px; +} +.info-language-mapper { + margin-bottom: 120px; +} diff --git a/ui/src/components/DestinationStack/index.tsx b/ui/src/components/DestinationStack/index.tsx index 148971126..ec16c76b9 100644 --- a/ui/src/components/DestinationStack/index.tsx +++ b/ui/src/components/DestinationStack/index.tsx @@ -2,11 +2,17 @@ import { useEffect, useRef, useState } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import AutoVerticalStepper from '../Stepper/VerticalStepper/AutoVerticalStepper'; import { getDestinationStackSteps } from './StepperSteps'; -import { CircularLoader } from '@contentstack/venus-components'; +import { + CircularLoader, + HelpText, + Icon, + Info, + Tooltip +} from '@contentstack/venus-components'; import { CS_ENTRIES } from '../../utilities/constants'; import { DEFAULT_DESTINATION_STACK_DATA, - IDestinationStackComponent, + IDestinationStackComponent } from '../../context/app/app.interface'; import './DestinationStack.scss'; import { MigrationResponse } from '../../services/api/service.interface'; @@ -14,6 +20,7 @@ import { getCMSDataFromFile } from '../../cmsData/cmsSelector'; import { RootState } from '../../store'; import { updateMigrationData } from '../../store/slice/migrationDataSlice'; import { AutoVerticalStepperRef } from '../LegacyCms'; +import LanguageMapper from './Actions/LoadLanguageMapper'; type DestinationStackComponentProps = { isCompleted: boolean; @@ -103,7 +110,9 @@ const DestinationStackComponent = ({ ) : (
{migrationData?.destinationStackData?.title}
- +
+ + +
+
+ +
+
Language configuration
+ + + +
+ + Contentstack and {newMigrationData?.legacy_cms?.selectedCms?.parent} Languages Mapping + + + {newMigrationData?.destination_stack?.selectedStack?.value ? ( +
+ +
+ ) : ( + } + version="v2" + content="Please select the stack to proceed with language mapping" + type="light" + /> + )}
)} ); }; -export default DestinationStackComponent; \ No newline at end of file +export default DestinationStackComponent; diff --git a/ui/src/context/app/app.interface.ts b/ui/src/context/app/app.interface.ts index a65d447a3..583aff8b7 100644 --- a/ui/src/context/app/app.interface.ts +++ b/ui/src/context/app/app.interface.ts @@ -173,7 +173,9 @@ export interface IDestinationStack { selectedStack: IDropDown; stackArray: IDropDown[]; migratedStacks: string[]; - + sourceLocale: string[]; + localeMapping: {}; + csLocale: string[]; } export interface IContentMapper { existingGlobal: ContentTypeList[] | (() => ContentTypeList[]); @@ -337,6 +339,9 @@ export const DEFAULT_DESTINATION_STACK: IDestinationStack = { selectedStack: DEFAULT_DROPDOWN, stackArray: [], migratedStacks: [], + sourceLocale: [], + localeMapping: {}, + csLocale: [] }; export const DEFAULT_CONTENT_MAPPER: IContentMapper = { diff --git a/ui/src/pages/Migration/index.tsx b/ui/src/pages/Migration/index.tsx index cb1deffb9..70613b22c 100644 --- a/ui/src/pages/Migration/index.tsx +++ b/ui/src/pages/Migration/index.tsx @@ -9,7 +9,22 @@ import { RootState } from '../../store'; import { updateMigrationData, updateNewMigrationData } from '../../store/slice/migrationDataSlice'; // Services -import { getMigrationData, updateCurrentStepData, updateLegacyCMSData, updateDestinationStack, updateAffixData, fileformatConfirmation, updateFileFormatData, affixConfirmation, updateStackDetails, getExistingContentTypes, getExistingGlobalFields, startMigration, updateMigrationKey } from '../../services/api/migration.service'; +import { + getMigrationData, + updateCurrentStepData, + updateLegacyCMSData, + updateDestinationStack, + updateAffixData, + fileformatConfirmation, + updateFileFormatData, + affixConfirmation, + updateStackDetails, + getExistingContentTypes, + getExistingGlobalFields, + startMigration, + updateMigrationKey, + updateLocaleMapper +} from '../../services/api/migration.service'; import { getCMSDataFromFile } from '../../cmsData/cmsSelector'; // Utilities @@ -23,7 +38,14 @@ import { DEFAULT_IFLOWSTEP, IFlowStep } from '../../components/Stepper/FlowStepper/flowStep.interface'; -import { IDropDown, INewMigration, ICMSType, ILegacyCMSComponent, DEFAULT_CMS_TYPE, TestStacks } from '../../context/app/app.interface'; +import { + IDropDown, + INewMigration, + ICMSType, + ILegacyCMSComponent, + DEFAULT_CMS_TYPE, + TestStacks +} from '../../context/app/app.interface'; import { ContentTypeSaveHandles } from '../../components/ContentMapper/contentMapper.interface'; import { ICardType } from "../../components/Common/Card/card.interface"; import { ModalObj } from '../../components/Modal/modal.interface'; @@ -38,6 +60,7 @@ import TestMigration from '../../components/TestMigration'; import MigrationExecution from '../../components/MigrationExecution'; import SaveChangesModal from '../../components/Common/SaveChangesModal'; import { getMigratedStacks } from '../../services/api/project.service'; +import { getStackLocales } from '../../services/api/stacks.service'; type StepperComponentRef = { handleStepChange: (step: number) => void; @@ -116,7 +139,6 @@ const Migration = () => { } catch (error) { // return error; console.log(error); - } } @@ -163,7 +185,7 @@ const Migration = () => { const data = await getMigrationData(selectedOrganisation?.value, params?.projectId ?? ''); const migratedstacks = await getMigratedStacks(selectedOrganisation?.value, projectId ); - + const csLocales = await getStackLocales(selectedOrganisation?.value); if (data) { setIsLoading(false); setProjectData(data?.data); @@ -233,8 +255,10 @@ const Migration = () => { destination_stack: { selectedOrg: selectedOrganisationData, selectedStack: selectedStackData, - stackArray:[], + stackArray: [], migratedStacks: migratedstacks?.data?.destinationStacks, + sourceLocale: projectData?.source_locales, + csLocale: csLocales?.data?.locales }, content_mapping: { isDropDownChanged: false, @@ -413,40 +437,66 @@ const Migration = () => { const handleOnClickDestinationStack = async (event: MouseEvent) => { setIsLoading(true); - if(isCompleted && !isEmptyString(newMigrationData?.destination_stack?.selectedStack?.value)){ + const hasNonEmptyMapping = + newMigrationData?.destination_stack?.localeMapping && + Object.values(newMigrationData?.destination_stack?.localeMapping)?.some( + (value) => value !== '' || value !== null || value !== undefined + ); + console.log(hasNonEmptyMapping); + + const master_locale:any = {}; + const locales: any= {}; + Object.entries(newMigrationData?.destination_stack?.localeMapping).forEach(([key, value]) => { + if (key.includes("master_locale")) { + master_locale[key.replace("-master_locale", "")] = value; + } else { + locales[key] = value; + } + }); + if ( + isCompleted && + !isEmptyString(newMigrationData?.destination_stack?.selectedStack?.value) && + hasNonEmptyMapping + ) { event?.preventDefault(); //Update Data in backend await updateDestinationStack(selectedOrganisation?.value, projectId, { stack_api_key: newMigrationData?.destination_stack?.selectedStack?.value }); - await updateStackDetails(selectedOrganisation?.value, projectId,{ - label:newMigrationData?.destination_stack?.selectedStack?.label, - value:newMigrationData?.destination_stack?.selectedStack?.value, - master_locale:newMigrationData?.destination_stack?.selectedStack?.master_locale, - created_at:newMigrationData?.destination_stack?.selectedStack?.created_at, + await updateStackDetails(selectedOrganisation?.value, projectId, { + label: newMigrationData?.destination_stack?.selectedStack?.label, + value: newMigrationData?.destination_stack?.selectedStack?.value, + master_locale: newMigrationData?.destination_stack?.selectedStack?.master_locale, + created_at: newMigrationData?.destination_stack?.selectedStack?.created_at, isNewStack: newMigrationData?.destination_stack?.selectedStack?.isNewStack - }) + }); + await updateLocaleMapper(projectId,{'master_locale': master_locale, locales:locales}) const res = await updateCurrentStepData(selectedOrganisation?.value, projectId); if (res?.status === 200) { handleStepChange(2); setIsLoading(false); const url = `/projects/${projectId}/migration/steps/3`; navigate(url, { replace: true }); - } - else{ + } else { setIsLoading(false); Notification({ - notificationContent: { text: res?.data?.error?.message}, + notificationContent: { text: res?.data?.error?.message }, type: 'error' }); } - } else{ + } else if (!isCompleted) { setIsLoading(false); Notification({ notificationContent: { text: 'Please select a stack to proceed further' }, type: 'warning' }); + } else if (! hasNonEmptyMapping) { + setIsLoading(false); + Notification({ + notificationContent: { text: 'Please complete the language mapping to preceed futher' }, + type: 'warning' + }); } }; diff --git a/ui/src/services/api/migration.service.ts b/ui/src/services/api/migration.service.ts index b3d7dd7d9..dba28037b 100644 --- a/ui/src/services/api/migration.service.ts +++ b/ui/src/services/api/migration.service.ts @@ -330,4 +330,13 @@ export const updateMigrationKey = async (orgId: string, projectId: string) => { } catch (error) { return error; } -}; \ No newline at end of file +}; + +export const updateLocaleMapper = async(projectId: string, data: any) => { + try { + return await postCall( + `${API_VERSION}/migration/updateLocales/${projectId}`, data, options); + } catch (error) { + return error; + } +} \ No newline at end of file diff --git a/ui/src/services/api/stacks.service.ts b/ui/src/services/api/stacks.service.ts index 429d92a1d..dd6b67497 100644 --- a/ui/src/services/api/stacks.service.ts +++ b/ui/src/services/api/stacks.service.ts @@ -43,3 +43,26 @@ export const getStackStatus = async (orgId: string, data: string) => { } } }; + +export const getStackLocales = async(orgId: string) => { +try { + + const updatedOptions = { + headers: { + app_token: getDataFromLocalStorage('app_token'), + //stack_api_key: api_key + } + }; + + + const res = await getCall(`${API_VERSION}/org/${orgId}/locales`, updatedOptions); + return res; + + } catch (error) { + if (error instanceof Error) { + throw new Error(`${error.message}`); + } else { + throw new Error('Unknown error'); + } + } +} \ No newline at end of file diff --git a/ui/src/services/api/upload.service.ts b/ui/src/services/api/upload.service.ts index 159aa43c3..691d27075 100644 --- a/ui/src/services/api/upload.service.ts +++ b/ui/src/services/api/upload.service.ts @@ -80,3 +80,25 @@ export const getRestrictedKeywords = async () => { } } } + +export const getLocales = async(api_key : string) => { + try { + const options = { + headers: { + 'authtoken': getDataFromLocalStorage('app_token'), + 'api_key': api_key , + //'affix': affix, + }, + + }; + + return await getCall(`https://api.contentstack.io/v3/locales`, options) + + } catch (error) { + if (error instanceof Error) { + throw new Error(`${error.message}`); + } else { + throw new Error('Unknown error'); + } + } +} \ No newline at end of file diff --git a/ui/src/utilities/functions.ts b/ui/src/utilities/functions.ts index d7d9ceabb..5e12ecf1d 100644 --- a/ui/src/utilities/functions.ts +++ b/ui/src/utilities/functions.ts @@ -145,7 +145,7 @@ export const getDays = (day: string | number | Date) => { }; export const isEmptyString = (str: string | undefined) => - str === undefined || str === null || str.trim().length < 1; + str === undefined || str === null || str?.trim()?.length < 1; export const shortName = (name: string) => { if (name && name.length > 25) {