diff --git a/api/src/routes/org.routes.ts b/api/src/routes/org.routes.ts index d4c2216bd..2e8a3c571 100644 --- a/api/src/routes/org.routes.ts +++ b/api/src/routes/org.routes.ts @@ -6,7 +6,7 @@ import validator from "../validators/index.js"; const router = express.Router({ mergeParams: true }); // GET all org stacks route -router.get("/stacks", asyncRouter(orgController.getAllStacks)); +router.get("/stacks/:searchText?", asyncRouter(orgController.getAllStacks)); // Create a new stack route router.post( diff --git a/api/src/services/migration.service.ts b/api/src/services/migration.service.ts index 631f12d6e..84c182f39 100644 --- a/api/src/services/migration.service.ts +++ b/api/src/services/migration.service.ts @@ -23,7 +23,7 @@ const createTestStack = async (req: Request): Promise => { await ProjectModelLowdb.read(); const projectData = ProjectModelLowdb.chain.get("projects").value(); - const testStackCount = projectData[0].test_stacks.length + 1; + const testStackCount = projectData[0]?.test_stacks?.length + 1; const newName = name + "-" + testStackCount; const [err, res] = await safePromise( diff --git a/api/src/services/org.service.ts b/api/src/services/org.service.ts index ccff68042..bc69192e8 100644 --- a/api/src/services/org.service.ts +++ b/api/src/services/org.service.ts @@ -13,6 +13,7 @@ const getAllStacks = async (req: Request): Promise => { const srcFun = "getAllStacks"; const orgId = req?.params?.orgId; const { token_payload } = req.body; + const search: string = req?.params?.searchText?.toLowerCase(); try { const authtoken = await getAuthtoken( @@ -42,13 +43,21 @@ const getAllStacks = async (req: Request): Promise => { err.response.data ) ); - return { data: err.response.data, status: err.response.status, }; } - let locale = await getStackLocal(token_payload, res.data.stacks); + let stacks = res?.data?.stacks; + if(search){ + stacks = stacks.filter((stack:{name: string, description:string})=>{ + const stackName = stack?.name?.toLowerCase(); + const stackDescription = stack?.description?.toLowerCase(); + return stackName?.includes(search) || stackDescription?.includes(search); + + }) + } + const locale = await getStackLocal(token_payload, stacks); return { data: { stacks: locale, diff --git a/ui/src/App.tsx b/ui/src/App.tsx index 5221fac64..207741364 100644 --- a/ui/src/App.tsx +++ b/ui/src/App.tsx @@ -1,16 +1,19 @@ +// Libraries +import { Suspense } from 'react'; +import { Provider} from 'react-redux'; +import { PersistGate } from 'redux-persist/integration/react'; +import { FullPageLoader } from '@contentstack/venus-components'; + +import { persistor, store } from './store'; + +// Components import AppRouter from './components/Common/router'; import ErrorBoundary from './components/ErrorBoundary'; -import AppContextProvider from './context/app/app.provider'; import AppLayout from './components/layout/AppLayout'; -import { Suspense, useEffect } from 'react'; -import { FullPageLoader } from '@contentstack/venus-components'; -import { persistor, store } from './store'; // Styles import '@contentstack/venus-components/build/main.css'; import './scss/App.scss'; -import { Provider} from 'react-redux'; -import { PersistGate } from 'redux-persist/integration/react'; function App() { diff --git a/ui/src/components/Common/Settings/Settings.scss b/ui/src/components/Common/Settings/Settings.scss index cfb8d60e0..4c6377a39 100644 --- a/ui/src/components/Common/Settings/Settings.scss +++ b/ui/src/components/Common/Settings/Settings.scss @@ -1,44 +1,42 @@ @import '../../../scss/variables'; -.icon-wrapper { - background-color: $color-base-white-10 !important; -} -.setting-wrapper { - width: 100%; - margin: 0 !important; -} #setting-page { display: flex; width: 100%; + .SectionHeader { + color: $color-stepper-title; + font-weight: $font-weight-semi-bold; + margin-bottom: 2rem; + } .PageLayout { width: 100%; } - .PageLayout__head { - border-left: 0 none; + .PageLayout__head, .PageLayout__leftSidebar { + border-top: 0 none; + } + .PageLayout--primary { + .PageLayout__content { + .PageLayout__body { + background: none; + margin-left: 15rem; + padding-top: $px-8; + } + } + } + .action-component-title { + justify-content: space-between; + width: calc(100vw - 326px); + } + .content-block { + margin-right: 0; + padding: 1.5rem; + width: 100%; } -} -.deleteButton { - position: fixed !important; - right: $px-40; - top: $px-80; } .Field { margin-bottom: $px-40; } -.settings-body { - padding-left: 120px !important; -} - -#page_header { - margin-left: 50px !important; -} - -.pagehead-wrapper { - margin-left: 240px; - width: calc(100% - 15rem) !important ; - z-index: 10 !important; -} .PageLayout__leftSidebar--hide { display: none; } @@ -47,16 +45,16 @@ margin-top: 0 !important; } -.content-body .white-box-container { - background-color: $color-brand-white-base; - padding: 20px; - margin-top: 50px !important; - margin-left: 240px; - margin-right: auto; - position: relative; - z-index: 10; - height: 600px; -} +// .content-body .white-box-container { +// background-color: $color-brand-white-base; +// padding: 20px; +// margin-top: 50px !important; +// margin-left: 240px; +// margin-right: auto; +// position: relative; +// z-index: 10; +// height: 600px; +// } .stack-settings__heading { color: $color-base-black-base; @@ -67,22 +65,22 @@ margin-bottom: $px-20; } -.toggle-class { - width: calc(100% - 18.4375rem) !important; -} -.layout-container.specific-context .PageLayout__head { - z-index: 10 !important; - margin-left: 240px; - width: 100% !important; -} -.SaveButton { - padding: 30px 10px; -} +// .toggle-class { +// width: calc(100% - 18.4375rem) !important; +// } +// .layout-container.specific-context .PageLayout__head { +// z-index: 10 !important; +// margin-left: 240px; +// width: 100% !important; +// } +// .SaveButton { +// padding: 30px 10px; +// } -.layout-container.content-body .PageLayout__body { - margin-top: 90px !important; - margin-left: 227px !important; -} +// .layout-container.content-body .PageLayout__body { +// margin-top: 90px !important; +// margin-left: 227px !important; +// } .PageLayout__leftSidebar { background-color: #f7f9fc !important; diff --git a/ui/src/components/Common/Settings/index.tsx b/ui/src/components/Common/Settings/index.tsx index e019f5892..7103fb796 100644 --- a/ui/src/components/Common/Settings/index.tsx +++ b/ui/src/components/Common/Settings/index.tsx @@ -142,26 +142,22 @@ const Settings = () => { const pageActions = [ { label: ( -
-
- +
+ ) } ]; @@ -170,7 +166,7 @@ const Settings = () => { component: (
{active === cmsData?.project?.title && ( -
+
{cmsData?.project?.general}
@@ -207,28 +203,6 @@ const Settings = () => {
- -
-
- - {cmsData?.project?.email} - -
-
- - -
- -
-
-
-
-
@@ -267,7 +231,7 @@ const Settings = () => { const leftSidebar = { component: ( -
+
{ }} version="v2" /> -
- } - onClick={() => { - setActive(cmsData?.execution_logs?.title); - setCurrentHeader(cmsData?.execution_logs?.title); - }} - version="v2" - /> -
) }; diff --git a/ui/src/components/Common/router.tsx b/ui/src/components/Common/router.tsx index 82f61ea82..6df9932c2 100644 --- a/ui/src/components/Common/router.tsx +++ b/ui/src/components/Common/router.tsx @@ -17,6 +17,7 @@ const LoginLazyLoad = lazy(() => import('../../pages/Login')); const RegionalLoginLazyLoad = lazy(() => import('../../pages/RegionalLogin')); const MigrationLazyLoad = lazy(() => import('../../pages/Migration')); const ProjectsLazyLoad = lazy(() => import('../../pages/Projects')); +const SettingsLazyLoad = lazy(() => import ('../Common/Settings')) const AppRouter = () => { return ( @@ -34,9 +35,9 @@ const AppRouter = () => { } - > + /> - + } /> } /> diff --git a/ui/src/components/ContentMapper/contentMapper.interface.ts b/ui/src/components/ContentMapper/contentMapper.interface.ts index 2708d800c..7f07c28b6 100644 --- a/ui/src/components/ContentMapper/contentMapper.interface.ts +++ b/ui/src/components/ContentMapper/contentMapper.interface.ts @@ -86,7 +86,7 @@ export interface FieldMetadata { export interface ContentTypesSchema { uid?: string; display_name?: string; - data_type?: 'text' | 'number' | 'isodate' | 'json' | 'file'; + data_type?: 'text' | 'number' | 'isodate' | 'json' | 'file' | 'reference' | 'group'; field_metadata?: FieldMetadata; enum?: any; } diff --git a/ui/src/components/ContentMapper/index.scss b/ui/src/components/ContentMapper/index.scss index 591460fed..3249fe800 100644 --- a/ui/src/components/ContentMapper/index.scss +++ b/ui/src/components/ContentMapper/index.scss @@ -29,6 +29,7 @@ border-bottom: 1px solid $color-brand-secondary-lightest; padding: $px-8 $px-12; .Search__v2 { + background-color: $color-brand-white-base; height: 2.5rem; width: 100%!important; .Search-input-show { diff --git a/ui/src/components/ContentMapper/index.tsx b/ui/src/components/ContentMapper/index.tsx index 19680ce80..f3f3def51 100644 --- a/ui/src/components/ContentMapper/index.tsx +++ b/ui/src/components/ContentMapper/index.tsx @@ -537,31 +537,6 @@ const ContentMapper = () => { } }); }; - - const handleValidateOnClick = async () => { - setisButtonLoading(true); - const data = { - name: newMigrationData?.destination_stack?.selectedStack?.label, - description: 'test migration stack', - master_locale: newMigrationData?.destination_stack?.selectedStack?.master_locale - }; - const res = await createTestStack( - newMigrationData?.destination_stack?.selectedOrg?.value, - projectId, - data - ); - const newMigrationDataObj: INewMigration = { - ...newMigrationData, - test_migration: { stack_link: res?.data?.data?.url } - }; - - dispatch(updateNewMigrationData((newMigrationDataObj))); - if (res?.status) { - setisButtonLoading(false); - const url = `/projects/${projectId}/migration/steps/4`; - navigate(url, { replace: true }); - } - }; const SelectAccessor = (data: FieldMapType) => { const OptionsForRow = Fields[data?.backupFieldType as keyof Mapping]; @@ -666,17 +641,18 @@ const ContentMapper = () => { 'multiline': 'multiline', 'HTML Rich text Editor': 'allow_rich_text', 'JSON Rich Text Editor': 'json', - group: 'Group', - URL: 'url', - file: 'file', - number: 'number', - Date: 'isodate', - boolean: 'boolean', - link: 'link', - reference: 'reference', - dropdown: 'enum', - radio: 'enum', - CheckBox: 'enum' + 'Rich Text':'json', + 'Group': 'Group', + 'URL': 'url', + 'file': 'file', + 'number': 'number', + 'Date': 'isodate', + 'boolean': 'boolean', + 'link': 'link', + 'reference': 'reference', + 'dropdown': 'enum', + 'radio': 'enum', + 'CheckBox': 'enum' }; const OptionsForRow: optionsType[] = []; // let ContentTypeSchema: ContentTypesSchema | undefined; @@ -691,7 +667,7 @@ const ContentMapper = () => { if (contentTypeSchema && validateArray(contentTypeSchema)) { const fieldTypeToMatch = fieldsOfContentstack[data?.otherCmsType as keyof Mapping]; - contentTypeSchema.forEach((value) => { + contentTypeSchema.forEach((value) => { switch (fieldTypeToMatch) { case 'text': if ( @@ -745,8 +721,16 @@ const ContentMapper = () => { } break; case 'Group': + if (value?.data_type === 'group') { OptionsForRow.push({ label: value?.display_name, value: value, isDisabled: false }); + } break; + case 'reference': + if (value?.data_type === 'reference') { + OptionsForRow.push({ label: value?.display_name, value: value, isDisabled: false }); + } + break; + default: OptionsForRow.push({ label: 'No matches found', @@ -769,6 +753,7 @@ const ContentMapper = () => { ...option, isDisabled: selectedOptions?.includes(option?.label ?? '') })); + return (
diff --git a/ui/src/components/DestinationStack/Actions/LoadOrganisation.tsx b/ui/src/components/DestinationStack/Actions/LoadOrganisation.tsx index 2dba6f8cb..cc31ab3d3 100644 --- a/ui/src/components/DestinationStack/Actions/LoadOrganisation.tsx +++ b/ui/src/components/DestinationStack/Actions/LoadOrganisation.tsx @@ -1,6 +1,6 @@ import { ChangeEvent, useEffect, useState } from 'react'; import { useDispatch, useSelector } from 'react-redux'; -import { INewMigration } from '../../../context/app/app.interface'; +import { IDropDown, INewMigration } from '../../../context/app/app.interface'; import { TextInput } from '@contentstack/venus-components'; import '../DestinationStack.scss'; @@ -23,8 +23,7 @@ const LoadOrganisation = (props: LoadOrganisationProps) => { const dispatch = useDispatch(); - const [selectedOrg, setSelectedOrg] = useState(); - + const [selectedOrg, setSelectedOrg] = useState(); /**** ALL METHODS HERE ****/ //update new Migration Data @@ -32,7 +31,6 @@ const LoadOrganisation = (props: LoadOrganisationProps) => { dispatch(updateNewMigrationData((data))); }; - const textInput = newMigrationData?.destination_stack?.selectedOrg?.label //Handle Organisation selection // const handleDropdownChange = (data: ChangeEvent) => { @@ -87,7 +85,7 @@ const LoadOrganisation = (props: LoadOrganisationProps) => {
*/} { ? newMigrationData?.destination_stack?.selectedStack : DEFAULT_DROPDOWN ); + const [allStack, setAllStack] = useState([]); const [allLocales, setAllLocales] = useState([]); const [isSaving, setIsSaving] = useState(false); const [isLoading, setisLoading] = useState(false); + const { projectId = '' }: Params = useParams(); + useEffect(()=>{ + if(! isEmptyString(newMigrationData?.destination_stack?.selectedStack?.value)){ + setSelectedStack(newMigrationData?.destination_stack?.selectedStack); + } + },[newMigrationData?.destination_stack?.selectedStack]) + //Handle new stack details const handleOnSave = async (data: Stack) => { if (isSaving) return false; @@ -103,6 +111,7 @@ const LoadStacks = (props: LoadFileFormatProps) => { /**** ALL METHODS HERE ****/ + const [placeholder, setPlaceholder] = useState('Select a stack'); //Handle Legacy cms selection const handleDropdownChange = (name: string) => (data: IDropDown) => { const stackChanged = selectedStack?.value !== data?.value; @@ -110,6 +119,11 @@ const LoadStacks = (props: LoadFileFormatProps) => { if (data?.value == '+ Create a new Stack') { handleCreateNewStack() } + if (stackCleared === true) { + setPlaceholder('Select a stack'); + } + + if (name === 'stacks' && data?.value != '+ Create a new Stack') { setSelectedStack(() => ({ ...data })); @@ -121,8 +135,8 @@ const LoadStacks = (props: LoadFileFormatProps) => { } }; - dispatch(updateNewMigrationData((newMigrationDataObj))); + dispatch(updateNewMigrationData((newMigrationDataObj))); if (!stackCleared) { if (props?.handleStepChange) { props?.handleStepChange(props?.currentStep, true); @@ -134,7 +148,7 @@ const LoadStacks = (props: LoadFileFormatProps) => { const fetchData = async () => { setisLoading(true); const stackData = await getAllStacksInOrg( - newMigrationData?.destination_stack?.selectedOrg?.value + newMigrationData?.destination_stack?.selectedOrg?.value,'' ); //org id will always be there const stackArray = validateArray(stackData?.data?.stacks) @@ -212,7 +226,7 @@ const LoadStacks = (props: LoadFileFormatProps) => { limit: number; }) => { const stackData = await getAllStacksInOrg( - newMigrationData?.destination_stack?.selectedOrg?.value + selectedOrganisation?.value, search ); //org id will always be there const stackArray = validateArray(stackData?.data?.stacks) @@ -240,28 +254,31 @@ const LoadStacks = (props: LoadFileFormatProps) => { } stackArray.push(addLabel) - setAllStack(stackArray); - //Set selected Stack - const selectedStackData = validateArray(stackArray) - ? stackArray.find( - (stack: IDropDown) => - stack?.value === newMigrationData?.destination_stack?.selectedStack?.value - ) - : DEFAULT_DROPDOWN; - - setSelectedStack(selectedStackData); - - const newMigrationDataObj: INewMigration = { - ...newMigrationData, - destination_stack: { - ...newMigrationData?.destination_stack, - selectedStack: selectedStackData - } - }; - - dispatch(updateNewMigrationData((newMigrationDataObj))); + // //Set selected Stack + // const selectedStackData = validateArray(stackArray) + // ? stackArray.find( + // (stack: IDropDown) =>{ + // console.log("stack :::", selectedStack?.value) + + // return stack?.value === selectedStack?.value} + // ) + // : DEFAULT_DROPDOWN; + + // setSelectedStack(selectedStackData); + // console.log("inload more ::::", selectedStackData); + + + // const newMigrationDataObj: INewMigration = { + // ...newMigrationData, + // destination_stack: { + // ...newMigrationData?.destination_stack, + // selectedStack: selectedStackData + // } + // }; + + // dispatch(updateNewMigrationData((newMigrationDataObj))); return { options: stackArray }; }; @@ -272,7 +289,6 @@ const LoadStacks = (props: LoadFileFormatProps) => { } } }; - return (
@@ -287,12 +303,13 @@ const LoadStacks = (props: LoadFileFormatProps) => { onBlur={onBlurDropdown} canEditOption={true} value={selectedStack} - isSearchable={true} isClearable={true} + isSearchable={true} width="600px" isDisabled={props?.stepComponentProps?.isSummary || false} - placeholder={'Select a stack'} + placeholder={placeholder} limit={10} + updateOption={()=> undefined} />
diff --git a/ui/src/components/DestinationStack/DestinationStack.scss b/ui/src/components/DestinationStack/DestinationStack.scss index 35113f8e7..726a0d15b 100644 --- a/ui/src/components/DestinationStack/DestinationStack.scss +++ b/ui/src/components/DestinationStack/DestinationStack.scss @@ -25,7 +25,12 @@ .pl-40 { padding-left: $px-40; } - +.Dropdown-wrapper { + .css-b8ldur-Input { + // border: 1px solid red; + cursor: not-allowed; + } +} .stackselect { min-width: 600px !important; max-width: 600px !important; diff --git a/ui/src/components/DestinationStack/index.tsx b/ui/src/components/DestinationStack/index.tsx index 0440151d1..76cd29810 100644 --- a/ui/src/components/DestinationStack/index.tsx +++ b/ui/src/components/DestinationStack/index.tsx @@ -96,7 +96,7 @@ const DestinationStackComponent = ({ //If stack is already selected and exist in backend, then fetch all stack list and filter selected stack. if (!isEmptyString(destination_stack)) { const stackData: any = await getAllStacksInOrg( - selectedOrganisationData?.value || selectedOrganisation?.value + selectedOrganisationData?.value || selectedOrganisation?.value,'' ); const stack = diff --git a/ui/src/components/LegacyCms/Actions/LoadUploadFile.tsx b/ui/src/components/LegacyCms/Actions/LoadUploadFile.tsx index 314ec21e6..7311d0bc4 100644 --- a/ui/src/components/LegacyCms/Actions/LoadUploadFile.tsx +++ b/ui/src/components/LegacyCms/Actions/LoadUploadFile.tsx @@ -27,7 +27,7 @@ const FileComponent = ({fileDetails}:Props ) => {
{fileDetails?.isLocalPath && (!isEmptyString(fileDetails?.localPath) || !isEmptyString(fileDetails?.awsData?.awsRegion)) ? (
- +
) : ( @@ -55,7 +55,7 @@ const LoadUploadFile = (props: LoadUploadFileProps) => { const [showMessage, setShowMessage] = useState(!!newMigrationData?.legacy_cms?.uploadedFile?.isValidated); const [validationMessgae, setValidationMessage] = useState(''); const [isValidationAttempted, setIsValidationAttempted] = useState(false); - const [isDasabled, setIsDisabled] = useState(false); + const [isDisabled, setIsDisabled] = useState(false); const [isConfigLoading, setIsConfigLoading] = useState(true); const [cmsType, setCmsType]= useState(''); const [fileDetails, setFileDetails] = useState(newMigrationData?.legacy_cms?.uploadedFile?.file_details || {}); @@ -76,7 +76,7 @@ const LoadUploadFile = (props: LoadUploadFileProps) => { setProgressPercentage(30); setShowProgress(true); - const res: any = await fileValidation(); + const res: any = await fileValidation(projectId); if(res?.status === 200){ setIsValidated(true); setValidationMessage('Validated'); @@ -301,11 +301,17 @@ const LoadUploadFile = (props: LoadUploadFileProps) => {
} - +
diff --git a/ui/src/components/LegacyCms/legacyCms.scss b/ui/src/components/LegacyCms/legacyCms.scss index aa682eada..f4fe01167 100644 --- a/ui/src/components/LegacyCms/legacyCms.scss +++ b/ui/src/components/LegacyCms/legacyCms.scss @@ -104,7 +104,7 @@ font-size: 12px; } .validation-cta{ - margin: 10px 20px; + margin: $space-24 $space-20 0; } .success{ color: $color-brand-success-base; diff --git a/ui/src/components/MainHeader/index.scss b/ui/src/components/MainHeader/index.scss index b330fa47b..fad380d74 100644 --- a/ui/src/components/MainHeader/index.scss +++ b/ui/src/components/MainHeader/index.scss @@ -2,21 +2,22 @@ .mainheader { background-color: $color-brand-white-base; - border-bottom: 1px solid $color-brand-secondary-lightest; + // border-bottom: 1px solid $color-brand-secondary-lightest; height: 3.5rem; + justify-content: space-between; position: fixed; width: 100%; top: 0; display: flex; align-items: center; - z-index: 9; + z-index: 100; button { border: 0 none; } .logo { - margin-right: 1.063rem; position: relative; - width: 3rem; + text-align: center; + width: 3.5rem; a { align-items: center; display: flex; @@ -30,9 +31,12 @@ box-shadow: 0 0 1px $color-brand-primary-base, 0 0 0 4px #bbb4f4; } } - .organisationWrapper:focus { - box-shadow: 0 0 1px $color-brand-primary-base, 0 0 0 4px #bbb4f4; - } + .organisationWrapper { + margin-left: 1.063rem; + &:focus { + box-shadow: 0 0 1px $color-brand-primary-base, 0 0 0 4px #bbb4f4; + } + } .Dropdown-wrapper { padding: 0 18px; } diff --git a/ui/src/components/MainHeader/index.tsx b/ui/src/components/MainHeader/index.tsx index 52e9d1c3f..1061a0712 100644 --- a/ui/src/components/MainHeader/index.tsx +++ b/ui/src/components/MainHeader/index.tsx @@ -97,9 +97,7 @@ const MainHeader = () => { }; return (
-
-
-
+
{logo?.image?.url ? (
@@ -126,7 +124,7 @@ const MainHeader = () => {
}
- {(location.pathname == '/projects' || location.pathname.includes('/projects/')) &&
+ {(location.pathname == '/projects' || location.pathname.includes('/projects/')) &&
{
} -
-
); }; diff --git a/ui/src/components/MigrationExecution/index.scss b/ui/src/components/MigrationExecution/index.scss index 09cc16c8b..42f81c48b 100644 --- a/ui/src/components/MigrationExecution/index.scss +++ b/ui/src/components/MigrationExecution/index.scss @@ -4,8 +4,12 @@ .select-wrapper { display: flex; align-items: center; - justify-content: space-around; - margin-left: 5px; + .Field { + margin-bottom: 0; + } +} +.content-body.step-desc { + padding: 1rem 1.5rem; } .terminal-container { background-color: #000; @@ -39,12 +43,17 @@ div .step-component .action-component-body { padding: 5px 10px; margin: 5px; } -.icon-wrapper { +.arrow-wrapper { + align-items: center; display: flex; + height: 19.5px; margin-left: 30px; /* Adds space to the left of the icon */ margin-right: 30px; - margin-top: 20px; - align-items: center; + width: 23.5px; + &.Icon--original { + height: auto; + width: auto; + } } .execution-wrapper { diff --git a/ui/src/components/MigrationExecution/index.tsx b/ui/src/components/MigrationExecution/index.tsx index b3b82b73c..2706f78c4 100644 --- a/ui/src/components/MigrationExecution/index.tsx +++ b/ui/src/components/MigrationExecution/index.tsx @@ -1,25 +1,23 @@ -import { useEffect, useContext } from 'react'; -import { Icon, Button, Field, TextInput, FieldLabel } from '@contentstack/venus-components'; -import { UseDispatch, useSelector } from 'react-redux'; +import { useEffect } from 'react'; +import { Icon, Field, TextInput, FieldLabel } from '@contentstack/venus-components'; +import { useSelector, useDispatch } from 'react-redux'; // Services import { getCMSDataFromFile } from '../../cmsData/cmsSelector'; +// Redux +import { RootState } from '../../store'; +import { setMigrationData, updateMigrationData } from '../../store/slice/migrationDataSlice'; + // Utilities import { CS_ENTRIES } from '../../utilities/constants'; import { validateArray } from '../../utilities/functions'; -// Context -import { AppContext } from '../../context/app/app.context'; - // Interface import { DEFAULT_MIGRATION_EXECUTION } from '../../context/app/app.interface'; //stylesheet import './index.scss'; -import { useDispatch } from 'react-redux'; -import { RootState } from '../../store'; -import { setMigrationData, updateMigrationData } from '../../store/slice/migrationDataSlice'; const MigrationExecution = () => { //const { migrationData, updateMigrationData, newMigrationData } = useContext(AppContext); @@ -67,27 +65,36 @@ const MigrationExecution = () => { }; return ( -
-
- {MigrationInformation && - validateArray(MigrationInformation) && - MigrationInformation?.map((item, index) => ( -
- - - {item?.title} - - {getPlaceHolder(item?.title)} - - {index < MigrationInformation?.length - 1 && ( - - )} -
- ))} -
-
-
- +
+
+
Path
+
Select your organization maintained on Contentstack.
+
+
+ {MigrationInformation && + validateArray(MigrationInformation) && + MigrationInformation?.map((item, index) => ( +
+ + + {item?.title} + + + + {index < MigrationInformation?.length - 1 && ( + + )} +
+ ))} +
+
); diff --git a/ui/src/components/MigrationFlowHeader/index.tsx b/ui/src/components/MigrationFlowHeader/index.tsx index bd7d0a04f..1b081efcf 100644 --- a/ui/src/components/MigrationFlowHeader/index.tsx +++ b/ui/src/components/MigrationFlowHeader/index.tsx @@ -18,9 +18,10 @@ import './index.scss'; type MigrationFlowHeaderProps = { handleOnClick: (event: MouseEvent, handleStepChange: (currentStep: number) => void) => void; + isLoading: boolean; }; -const MigrationFlowHeader = ({ handleOnClick }: MigrationFlowHeaderProps) => { +const MigrationFlowHeader = ({ handleOnClick, isLoading }: MigrationFlowHeaderProps) => { const [projectName, setProjectName] = useState(''); const navigate = useNavigate(); @@ -50,6 +51,7 @@ const MigrationFlowHeader = ({ handleOnClick }: MigrationFlowHeaderProps) => { dispatch(updateNewMigrationData(DEFAULT_NEW_MIGRATION)) navigate(-1); } + return (
@@ -73,8 +75,9 @@ const MigrationFlowHeader = ({ handleOnClick }: MigrationFlowHeaderProps) => { onClick={handleOnClick} version="v2" aria-label='Save and Continue' + isLoading={isLoading} > - Save and Continue + {params?.stepId === '5' ? 'Start' : 'Save and Continue'}
) diff --git a/ui/src/components/SchemaModal/index.scss b/ui/src/components/SchemaModal/index.scss index 6cbf7e627..8065e9dd7 100644 --- a/ui/src/components/SchemaModal/index.scss +++ b/ui/src/components/SchemaModal/index.scss @@ -69,7 +69,7 @@ } } } - .title { + .field-title { color: $color-font-base; font-size: $size-font-large; font-weight: $font-weight-regular; diff --git a/ui/src/components/SchemaModal/index.tsx b/ui/src/components/SchemaModal/index.tsx index 120f657fd..27bf9b88f 100644 --- a/ui/src/components/SchemaModal/index.tsx +++ b/ui/src/components/SchemaModal/index.tsx @@ -38,7 +38,7 @@ const getTopLevelIcons = (field: FieldMapType) => { return icons['title']; } - if (field?.ContentstackFieldType === 'URL') { + if (field?.ContentstackFieldType === 'URL' || field?.ContentstackFieldType === 'single_line_text') { return icons['text']; } @@ -170,7 +170,7 @@ const TreeView = ({ schema = [] }: schemaType) => { )} - + {getChildFieldName(field?.otherCmsField, item?.otherCmsField)}
@@ -220,7 +220,7 @@ const TreeView = ({ schema = [] }: schemaType) => { {hasNested && } - {item?.otherCmsField} + {item?.otherCmsField}
{hasNested && generateNestedOutline(item, index)} diff --git a/ui/src/components/SideBar/index.tsx b/ui/src/components/SideBar/index.tsx index a273915ac..149ca958a 100644 --- a/ui/src/components/SideBar/index.tsx +++ b/ui/src/components/SideBar/index.tsx @@ -1,12 +1,30 @@ // Libraries -import { Icon } from '@contentstack/venus-components'; +import { Tooltip, Icon, Link } from '@contentstack/venus-components'; +import { useNavigate } from 'react-router'; + // Styles import './index.scss'; -const SideBar = () => { +type SettingIconProp = { + projectId: string; +} + +const SideBar = ({projectId}: SettingIconProp) => { + const navigate = useNavigate(); + + const settingsNavigate = () => { + const url = `/projects/${projectId}/settings`; + navigate(url, { replace: true }); + } return ( -
- {location.pathname.includes('/projects/') && } +
+ {location.pathname.includes('/projects/') && + + + + + + }
); }; diff --git a/ui/src/components/Stepper/HorizontalStepper/HorizontalStepper.scss b/ui/src/components/Stepper/HorizontalStepper/HorizontalStepper.scss index d7016620f..ad2d6a9b4 100644 --- a/ui/src/components/Stepper/HorizontalStepper/HorizontalStepper.scss +++ b/ui/src/components/Stepper/HorizontalStepper/HorizontalStepper.scss @@ -119,6 +119,7 @@ z-index: 9; } .stepContent { + background-color: $color-base-white-10; height: calc(100vh - 56px); padding-top: 190px; background: $color-base-white-10; diff --git a/ui/src/components/Stepper/VerticalStepper/AutoVerticalStepper.tsx b/ui/src/components/Stepper/VerticalStepper/AutoVerticalStepper.tsx index af961eca4..2e247e48c 100644 --- a/ui/src/components/Stepper/VerticalStepper/AutoVerticalStepper.tsx +++ b/ui/src/components/Stepper/VerticalStepper/AutoVerticalStepper.tsx @@ -88,13 +88,13 @@ const AutoVerticalStepper = React.forwardRef<
{data.titleNote ? data.titleNote : ''}
- {data?.lock ? ( + {/* {data?.lock ? (
lock-icon
- ) : null} + ) : null} */}
{data.description &&
{data.description}
} diff --git a/ui/src/components/TestMigration/index.scss b/ui/src/components/TestMigration/index.scss index 5d6d4c6cb..d7711aea0 100644 --- a/ui/src/components/TestMigration/index.scss +++ b/ui/src/components/TestMigration/index.scss @@ -1,61 +1,11 @@ @import '../../scss/App.scss'; @import '../../scss/variables'; -.test { - background-color: #000000; - color: $color-brand-white-base; - height: 469px; - padding: 20px; - overflow-y: auto; - white-space: pre-wrap; - width: 100% !important; - box-sizing: border-box; -} - -div .step-component .action-component-body { - //margin-top: 60px !important; - width: 100% !important; - margin-left: 0px !important; -} -.cta-wrapper-test-migration { - border-top: 1px solid $color-base-gray-40; - bottom: 0; - left: 0; - padding: $space-12 $space-24 $space-12 $space-12; - position: fixed; - right: 0; - text-align: right; - width: 100%; - z-index: 1; -} -.selectedOptions { - color: $color-base-gray-20; - font-size: $size-font-large; - font-weight: $font-weight-semi-bold; - padding: 5px 0; - margin: 20px 0; -} -.icon-wrapper { - display: flex; - margin-left: 30px; /* Adds space to the left of the icon */ - margin-right: 30px; - margin-top: 20px; - align-items: center; -} - -.execution-wrapper { - display: flex; - background-color: $color-base-white-5; - color: $color-font-base; - height: $px-40; - justify-content: center; - align-items: center; - width: 100%; - text-align: center !important; - padding: 0 !important; - border: 1px solid $color-brand-secondary-lightest; - border-radius: var(--TermCount, 5px); -} -.stack-link { - padding: 10px 10px; -} + + + + + + + + diff --git a/ui/src/components/TestMigration/index.tsx b/ui/src/components/TestMigration/index.tsx index 007eca4c6..d3360734c 100644 --- a/ui/src/components/TestMigration/index.tsx +++ b/ui/src/components/TestMigration/index.tsx @@ -1,7 +1,7 @@ -import { useContext, useEffect, useState } from 'react'; -import { Link, useNavigate, useParams } from 'react-router-dom'; -import { Button } from '@contentstack/venus-components'; -import { UseDispatch,useSelector } from 'react-redux'; +import { useEffect, useState } from 'react'; +import { useNavigate, useParams } from 'react-router-dom'; +import { Field, FieldLabel, TextInput, Link, Icon, Tooltip } from '@contentstack/venus-components'; +import { useSelector } from 'react-redux'; // Services import { getCMSDataFromFile } from '../../cmsData/cmsSelector'; @@ -12,18 +12,11 @@ import { CS_ENTRIES } from '../../utilities/constants'; // Interface import { MigrationType } from './testMigration.interface'; -//stylesheet -import './index.scss'; -import { AppContext } from '../../context/app/app.context'; - const TestMigration = () => { const [data, setData] = useState({}); - const newMigrationData = useSelector((state:any)=>state?.migration?.newMigration); - - /** ALL HOOKS Here */ - const { projectId = '' } = useParams(); - const navigate = useNavigate(); + const newMigrationData = useSelector((state:any)=>state?.migration?.newMigrationData); + /********** ALL USEEFFECT HERE *************/ useEffect(() => { @@ -36,33 +29,53 @@ const TestMigration = () => { }); }, []); - const { subtitle, cta } = data; - return ( -
-
-
- {subtitle}: - - - {newMigrationData?.test_migration?.stack_link} - - +
+
+
UID
+
+

Select your current Content Management system from the available options.

+ + + Uploaded CMS + +
+ {newMigrationData?.test_migration?.stack_api_key && ( + + )} + + {newMigrationData?.test_migration?.stack_link && ( + + + + + + )} +
+
-
-
- {cta && cta?.title && ( - - - - )} + +
+
Execution Logs
+
+ +
); diff --git a/ui/src/components/layout/AppLayout/index.tsx b/ui/src/components/layout/AppLayout/index.tsx index 059dac487..9fe955566 100644 --- a/ui/src/components/layout/AppLayout/index.tsx +++ b/ui/src/components/layout/AppLayout/index.tsx @@ -1,11 +1,13 @@ // Libraries import { FC, ReactNode, useEffect } from 'react'; -import { useLocation } from 'react-router'; +import { Params, useLocation, useParams } from 'react-router'; +import { useDispatch } from 'react-redux'; + +import { getUserDetails } from '../../../store/slice/authSlice'; + // Component import MainHeader from '../../MainHeader'; import SideBar from '../../SideBar'; -import { getUserDetails } from '../../../store/slice/authSlice'; -import { useDispatch } from 'react-redux'; type IProps = { children?: ReactNode; @@ -15,6 +17,8 @@ const AppLayout: FC = ({ children }) => { const location = useLocation(); const dispatch = useDispatch(); + const projectId = location?.pathname?.split('/')?.[2]; + useEffect(()=>{ dispatch(getUserDetails()); @@ -25,7 +29,7 @@ const AppLayout: FC = ({ children }) => { {location.pathname.includes('projects') && <> - + }
diff --git a/ui/src/context/app/app.interface.ts b/ui/src/context/app/app.interface.ts index 6cf0c653c..12fec62d3 100644 --- a/ui/src/context/app/app.interface.ts +++ b/ui/src/context/app/app.interface.ts @@ -188,6 +188,7 @@ export interface IDropDown { } export interface ITestMigration { stack_link: string; + stack_api_key: string; } export interface IAppContext { authToken: string; @@ -287,7 +288,8 @@ export const DEFAULT_CONTENT_MAPPER: IContentMapper = { }; export const DEFAULT_TEST_MIGRATION: ITestMigration = { - stack_link: '' + stack_link: '', + stack_api_key: '' }; export const DEFAULT_NEW_MIGRATION: INewMigration = { diff --git a/ui/src/pages/Migration/index.tsx b/ui/src/pages/Migration/index.tsx index 85ae8fd31..5c0ebb747 100644 --- a/ui/src/pages/Migration/index.tsx +++ b/ui/src/pages/Migration/index.tsx @@ -98,8 +98,7 @@ const Migration = () => { } }; - const createStepper = (projectData:any,handleStepChange: (currentStep: number) => void) => { - + const createStepper = (projectData: MigrationResponse,handleStepChange: (currentStep: number) => void) => { const steps = [ { data: { // handle on proceed to destination stack const handleOnClickLegacyCms = async (event: MouseEvent ) => { + setIsLoading(true); + if(isCompleted){ event.preventDefault(); @@ -175,12 +176,16 @@ const Migration = () => { const res = await updateCurrentStepData(selectedOrganisation.value, projectId); handleStepChange(1); if (res) { + setIsLoading(false); + const url = `/projects/${projectId}/migration/steps/2`; navigate(url, { replace: true }); } } else{ + setIsLoading(false); + Notification({ notificationContent: { text: 'Please complete all steps' }, type: 'warning' @@ -190,6 +195,8 @@ const Migration = () => { }; // handle on proceed to content mapping const handleOnClickDestinationStack = async (event: MouseEvent) => { + setIsLoading(true); + if(isCompleted){ event?.preventDefault(); //Update Data in backend @@ -199,55 +206,73 @@ const Migration = () => { handleStepChange(2); const res = await updateCurrentStepData(selectedOrganisation?.value, projectId); if (res) { + setIsLoading(false); + const url = `/projects/${projectId}/migration/steps/3`; navigate(url, { replace: true }); } + } else{ + Notification({ + notificationContent: { text: 'Please complete all steps' }, + type: 'warning' + }); } }; const handleOnClickContentMapper = async (event: MouseEvent) => { - if (isCompleted) { - event.preventDefault(); + setIsLoading(true); + + event.preventDefault(); + + const data = { + name: newMigrationData?.destination_stack?.selectedStack?.label, + description: 'test migration stack', + master_locale: newMigrationData?.destination_stack?.selectedStack?.master_locale + }; + + const res = await createTestStack( + newMigrationData?.destination_stack?.selectedOrg?.value, + projectId, + data + ); + + const newMigrationDataObj: INewMigration = { + ...newMigrationData, + test_migration: { stack_link: res?.data?.data?.url, stack_api_key: res?.data?.data?.data?.stack?.api_key } + }; + + dispatch(updateNewMigrationData((newMigrationDataObj))); + if (res?.status) { + setIsLoading(false); - const data = { - name: newMigrationData?.destination_stack?.selectedStack?.label, - description: 'test migration stack', - master_locale: newMigrationData?.destination_stack?.selectedStack?.master_locale - }; - - const res = await createTestStack( - newMigrationData?.destination_stack?.selectedOrg?.value, - projectId, - data - ); - - const newMigrationDataObj: INewMigration = { - ...newMigrationData, - test_migration: { stack_link: res?.data?.data?.url } - }; - - dispatch(updateNewMigrationData((newMigrationDataObj))); - if (res?.status) { - const url = `/projects/${projectId}/migration/steps/4`; - navigate(url, { replace: true }); - } - } else { - Notification({ - notificationContent: { text: 'Please complete all steps' }, - type: 'warning' - }); + const url = `/projects/${projectId}/migration/steps/4`; + navigate(url, { replace: true }); + + await updateCurrentStepData(selectedOrganisation.value, projectId); + handleStepChange(3); } } + const handleOnClickTestMigration = async () => { + setIsLoading(false); + + const url = `/projects/${projectId}/migration/steps/5`; + navigate(url, { replace: true }); + + await updateCurrentStepData(selectedOrganisation.value, projectId); + handleStepChange(4); + } + const handleOnClickFunctions = [ handleOnClickLegacyCms, handleOnClickDestinationStack, - handleOnClickContentMapper + handleOnClickContentMapper, + handleOnClickTestMigration ]; return (
- +
{ projectData && diff --git a/ui/src/pages/Projects/index.tsx b/ui/src/pages/Projects/index.tsx index e26d3b92c..ca05ff583 100644 --- a/ui/src/pages/Projects/index.tsx +++ b/ui/src/pages/Projects/index.tsx @@ -61,7 +61,9 @@ const Projects = () => { const [loadStatus, setLoadStatus] = useState(true); const [searchText, setSearchText] = useState(search); - + useEffect(()=>{ + dispatch(getUserDetails()); + },[]); const fetchProjects = async () => { if (selectedOrganisation?.value) { @@ -85,10 +87,14 @@ const Projects = () => { // fetchProjects(); }; + useEffect(()=>{ dispatch(getUserDetails()); + },[dispatch]); - },[dispatch]) + useEffect(()=>{ + dispatch(getUserDetails()); + },[]); useEffect(() => { fetchData(); diff --git a/ui/src/scss/App.scss b/ui/src/scss/App.scss index b76ecbd76..5a960be43 100644 --- a/ui/src/scss/App.scss +++ b/ui/src/scss/App.scss @@ -45,6 +45,7 @@ display: flex; height: 100vh; margin-left: auto; + overflow: hidden; .Icon--original { height: 1.25rem; width: 1.25rem; @@ -336,6 +337,7 @@ h2 { margin-bottom: $space-30; } .migration-steps-wrapper { + border-top: 1px solid $color-brand-secondary-lightest; margin-top: 3.5rem; h1 { color: $color-black-2121; @@ -387,6 +389,28 @@ h2 { } } } +.content-block { + background-color: $color-brand-white-base; + border: 1px solid $color-base-gray-40; + border-radius: $px-4; + margin: $px-24 $px-20 $px-32; + + .content-header { + font-size: $size-font-large; + font-weight: $font-weight-semi-bold; + padding: $px-12 $px-24; + } + .content-body { + border-top: 1px solid $color-base-gray-40; + line-height: $line-height-default; + padding: $px-24 $px-24; + } +} +.layout-container { + .PageLayout__content { + border-top: 1px solid $color-brand-secondary-lightest; + } +} ::-webkit-input-placeholder { color: $color-stepper-title !important; } diff --git a/ui/src/services/api/stacks.service.ts b/ui/src/services/api/stacks.service.ts index abb79029e..334b2b7a6 100644 --- a/ui/src/services/api/stacks.service.ts +++ b/ui/src/services/api/stacks.service.ts @@ -8,9 +8,9 @@ const options = { } }; -export const getAllStacksInOrg = async (orgId: string) => { +export const getAllStacksInOrg = async (orgId: string,searchText: string) => { try { - return await getCall(`${API_VERSION}/org/${orgId}/stacks`, options); + return await getCall(`${API_VERSION}/org/${orgId}/stacks/${searchText}?`, options); } catch (error) { return error; } diff --git a/ui/src/services/api/upload.service.ts b/ui/src/services/api/upload.service.ts index 67ada600d..ead7f3f28 100644 --- a/ui/src/services/api/upload.service.ts +++ b/ui/src/services/api/upload.service.ts @@ -2,6 +2,7 @@ import axios from 'axios'; import { UPLOAD_FILE_RELATIVE_URL } from '../../utilities/constants'; import { User, SmsToken } from '../../pages/Login/login.interface'; import { API_VERSION } from '../../utilities/constants'; +import { getDataFromLocalStorage } from '../../utilities/functions'; //Axios Calls for Upload server export const getCall = async (url: string, options?: any) => { @@ -36,9 +37,16 @@ export const uploadFilePath = () => { return `${UPLOAD_FILE_RELATIVE_URL}upload`; }; -export const fileValidation = () => { +export const fileValidation = (projectId: string) => { try { - return getCall(`${UPLOAD_FILE_RELATIVE_URL}validator`); + const options = { + headers: { + 'app_token': getDataFromLocalStorage('app_token'), + 'projectId': projectId + }, + + }; + return getCall(`${UPLOAD_FILE_RELATIVE_URL}validator`, options); } catch (error) { return error; } diff --git a/uplaode-api/.env b/uplaode-api/.env index 5f3a84b6c..2c50b6496 100644 --- a/uplaode-api/.env +++ b/uplaode-api/.env @@ -1,2 +1,2 @@ PORT=4002 -NODE_BACKEND_API =http://localhost:5000 \ No newline at end of file +NODE_BACKEND_API =http://localhost:5001 \ No newline at end of file diff --git a/uplaode-api/src/routes/index.ts b/uplaode-api/src/routes/index.ts index 32a46b61a..b66241dbb 100644 --- a/uplaode-api/src/routes/index.ts +++ b/uplaode-api/src/routes/index.ts @@ -91,7 +91,7 @@ router.post('/upload', upload.single('file'), async function (req: Request, res: // deepcode ignore NoRateLimitingForExpensiveWebOperation: router.get('/validator', express.json(), fileOperationLimiter, async function (req: Request, res: Response) { try { - const projectId: string | string[] = req?.body?.projectId ?? ""; + const projectId: string | string[] = req?.headers?.projectid ?? ""; const app_token: string | string[] = req?.headers?.app_token ?? ""; const cmsType = config?.cmsType?.toLowerCase();