Skip to content

Commit 143ea2d

Browse files
Merge pull request #582 from contentstack/dev
Dev
2 parents 997b9f4 + 7152c2d commit 143ea2d

File tree

13 files changed

+299
-63
lines changed

13 files changed

+299
-63
lines changed

fileUpdate.js

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
const fs = require('fs');
2+
const path = require('path');
3+
const { cliux, messageHandler } = require('@contentstack/cli-utilities');
4+
const isEmpty = (value) => value === null || value === undefined ||
5+
(typeof value === 'object' && Object.keys(value).length === 0) ||
6+
(typeof value === 'string' && value.trim().length === 0);;
7+
const config = {
8+
plan: {
9+
dropdown: { optionLimit: 100 }
10+
},
11+
cmsType: null,
12+
isLocalPath: true,
13+
awsData: {
14+
awsRegion: 'us-east-2',
15+
awsAccessKeyId: '',
16+
awsSecretAccessKey: '',
17+
awsSessionToken: '',
18+
bucketName: 'migartion-test',
19+
buketKey: 'project/package 45.zip'
20+
},
21+
localPath: null
22+
};
23+
24+
const configFilePath = path.resolve(path?.join?.('upload-api', 'src', 'config', 'index.ts'));
25+
26+
const ensureDirectoryExists = (filePath) => {
27+
const dir = path.dirname(filePath);
28+
if (!fs.existsSync(dir)) {
29+
fs.mkdirSync(dir, { recursive: true });
30+
console.log('📂 Created missing directory:', dir);
31+
}
32+
};
33+
34+
const inquireRequireFieldValidation = (input) => {
35+
if (isEmpty(input)) {
36+
return messageHandler.parse('Please enter the path');
37+
}
38+
if (!fs.existsSync(input)) {
39+
return messageHandler.parse('The specified path does not exist. Please enter a valid path.');
40+
}
41+
return true;
42+
};
43+
44+
const typeSwitcher = async (type) => {
45+
switch (type) {
46+
case 'Aws S3': {
47+
const awsData = {
48+
awsRegion: await cliux.inquire({
49+
type: 'input',
50+
message: 'Enter AWS Region',
51+
name: 'awsRegion',
52+
validate: inquireRequireFieldValidation
53+
}),
54+
awsAccessKeyId: await cliux.inquire({
55+
type: 'input',
56+
message: 'Enter AWS Access Key Id',
57+
name: 'awsAccessKeyId',
58+
validate: inquireRequireFieldValidation
59+
}),
60+
awsSecretAccessKey: await cliux.inquire({
61+
type: 'input',
62+
message: 'Enter AWS Secret Access Key',
63+
name: 'awsSecretAccessKey',
64+
validate: inquireRequireFieldValidation
65+
}),
66+
};
67+
const isSessionToken = await cliux.inquire({
68+
choices: ['yes', 'no'],
69+
type: 'list',
70+
name: 'isSessionToken',
71+
message: 'Do you have a Session Token?'
72+
});
73+
if (isSessionToken === 'yes') {
74+
awsData.awsSessionToken = await cliux.inquire({
75+
type: 'input',
76+
message: 'Enter AWS Session Token',
77+
name: 'awsSessionToken',
78+
validate: inquireRequireFieldValidation
79+
});
80+
}
81+
return awsData;
82+
}
83+
case 'Locale Path': {
84+
return await cliux.inquire({
85+
type: 'input',
86+
message: 'Enter file path',
87+
name: 'filePath',
88+
validate: inquireRequireFieldValidation
89+
});
90+
}
91+
default:
92+
console.log('⚠️ Invalid type provided');
93+
return;
94+
}
95+
};
96+
97+
const XMLMigration = async () => {
98+
const typeOfcms = await cliux.inquire({
99+
choices: ['sitecore', 'contentful'],
100+
type: 'list',
101+
name: 'value',
102+
message: 'Choose the option to proceed with your legacy CMS:'
103+
});
104+
105+
const data = await typeSwitcher('Locale Path');
106+
if (typeof typeOfcms === 'string') {
107+
config.cmsType = typeOfcms;
108+
} else {
109+
console.log('⚠️ Error: Expected a string for typeOfcms but got an object.');
110+
}
111+
if (typeof data === 'string') {
112+
config.localPath = data;
113+
} else {
114+
console.log('⚠️ Error: Expected a string for localPath but got an object.');
115+
}
116+
ensureDirectoryExists(configFilePath);
117+
fs.writeFileSync(configFilePath, `export default ${JSON.stringify(config, null, 2)};`, 'utf8');
118+
};
119+
120+
XMLMigration();

package.json

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@
99
"api": "cd ./api && npm run dev",
1010
"upload": "cd ./upload-api && npm start",
1111
"ui": "cd ./ui && npm start",
12-
"start": "node index.js"
12+
"setup:file": "npm i && node fileUpdate.js",
13+
"create:env": "node index.js",
14+
"setup:mac": "bash setup.sh"
1315
},
1416
"repository": {
1517
"type": "git",
@@ -36,5 +38,8 @@
3638
"validate-branch-name": {
3739
"pattern": "^(feature|bugfix|hotfix)/[a-z0-9-]{5,30}$",
3840
"errorMsg": "Please add valid branch name!"
41+
},
42+
"dependencies": {
43+
"@contentstack/cli-utilities": "^1.8.4"
3944
}
40-
}
45+
}

setup.sh

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
#!/bin/bash
2+
3+
# Get the script's directory (ensures correct paths)
4+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
5+
cd "$SCRIPT_DIR" || exit 1
6+
7+
# Install NVM if not installed
8+
if ! command -v nvm &> /dev/null; then
9+
echo "Installing NVM..."
10+
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.4/install.sh | bash
11+
12+
export NVM_DIR="$HOME/.nvm"
13+
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
14+
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"
15+
else
16+
export NVM_DIR="$HOME/.nvm"
17+
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
18+
fi
19+
20+
# Ensure Node.js 21 is installed and used
21+
NODE_VERSION=$(node -v 2>/dev/null)
22+
if [[ "$NODE_VERSION" != v21.* ]]; then
23+
echo "Installing and using Node.js 21..."
24+
nvm install 21
25+
fi
26+
nvm use 21
27+
28+
Setup CLI
29+
echo "Setting up CLI repo..."
30+
cd "$SCRIPT_DIR/cli" || exit 1
31+
32+
# Check if current user can write to node_modules
33+
if [ -w node_modules ] || [ ! -d node_modules ]; then
34+
npm run setup-repo --force
35+
else
36+
echo "Permission issue detected. Trying with sudo..."
37+
sudo npm run setup-repo --force
38+
fi
39+
40+
# Return to script root
41+
cd "$SCRIPT_DIR" || exit 1
42+
43+
# Fix npm cache permissions
44+
echo "Fixing npm cache permissions..."
45+
sudo chown -R $(id -u):$(id -g) "$HOME/.npm"
46+
47+
# Start With Env File
48+
echo "Creating .env file..."
49+
npm run create:env
50+
51+
echo "Updating config file..."
52+
npm run setup:file
53+
54+
# Start services in new terminals
55+
echo "Starting services in new terminals..."
56+
57+
if [[ "$OSTYPE" == "darwin"* ]]; then
58+
# macOS
59+
osascript -e "tell application \"Terminal\" to do script \"
60+
source \$HOME/.nvm/nvm.sh && nvm use 21 &&
61+
cd '$SCRIPT_DIR/api' &&
62+
echo 'Cleaning API dependencies...' &&
63+
rm -rf node_modules package-lock.json &&
64+
npm install &&
65+
npm run dev
66+
\""
67+
osascript -e "tell application \"Terminal\" to do script \"
68+
source \$HOME/.nvm/nvm.sh && nvm use 21 &&
69+
cd '$SCRIPT_DIR/upload-api' &&
70+
echo 'Cleaning upload-api dependencies...' &&
71+
rm -rf node_modules package-lock.json &&
72+
rm -rf migration-sitecore/node_modules migration-sitecore/package-lock.json &&
73+
npm install &&
74+
npm run start
75+
\""
76+
osascript -e "tell application \"Terminal\" to do script \"
77+
source \$HOME/.nvm/nvm.sh && nvm use 21 &&
78+
cd '$SCRIPT_DIR/ui' &&
79+
echo 'Cleaning UI dependencies...' &&
80+
rm -rf node_modules package-lock.json &&
81+
npm install &&
82+
npm run start
83+
\""
84+
85+
elif [[ "$OSTYPE" == "linux-gnu"* ]]; then
86+
# Linux (GNOME Terminal)
87+
gnome-terminal -- bash -c "source $HOME/.nvm/nvm.sh && nvm use 21 && cd '$SCRIPT_DIR/api' && npm install && npm run dev; exec bash"
88+
gnome-terminal -- bash -c "source $HOME/.nvm/nvm.sh && nvm use 21 && cd '$SCRIPT_DIR/upload-api' && npm install && npm run start; exec bash"
89+
gnome-terminal -- bash -c "source $HOME/.nvm/nvm.sh && nvm use 21 && cd '$SCRIPT_DIR/ui' && npm install && npm run start; exec bash"
90+
else
91+
echo "Unsupported OS: $OSTYPE"
92+
exit 1
93+
fi
94+
95+
echo "All services started!"

ui/src/components/Common/DeleteProjectModal/index.tsx

Lines changed: 3 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,12 @@
22
import { useState } from 'react';
33
import {
44
Button,
5-
Notification,
65
ModalBody,
76
ModalHeader,
87
ModalFooter,
98
ButtonGroup
109
} from '@contentstack/venus-components';
1110

12-
// Service
13-
import { deleteProject } from '../../../services/api/project.service';
14-
1511
// Interfaces
1612
import { SettingsModalProps } from '../../../components/Modal/modal.interface';
1713

@@ -22,39 +18,11 @@ import { SettingsModalProps } from '../../../components/Modal/modal.interface';
2218
* @returns {JSX.Element} The rendered DeleteProjectModal component.
2319
*/
2420
const DeleteProjectModal = (props: SettingsModalProps) => {
25-
const { closeModal, navigate, projectId, projectName, selectedOrg } = props;
21+
const { closeModal, projectName, handleDeleteProject } = props;
2622

2723
const [isLoading, setIsLoading] = useState<boolean>(false);
2824

29-
/**
30-
* Handles the deletion of the project.
31-
*
32-
* @param {() => void} closeModal - A function to close the modal.
33-
* @returns {Promise<void>} A promise that resolves when the project is deleted.
34-
*/
35-
const handleDeleteProject = async (closeModal: () => void): Promise<void> => {
36-
setIsLoading(true);
37-
const response = await deleteProject(selectedOrg?.value || '', projectId ?? '');
38-
39-
if (response?.status === 200) {
40-
setIsLoading(false);
41-
closeModal();
42-
setTimeout(() => {
43-
navigate('/projects');
44-
}, 800);
45-
setTimeout(() => {
46-
Notification({
47-
notificationContent: { text: response?.data?.data?.message },
48-
notificationProps: {
49-
position: 'bottom-center',
50-
hideProgressBar: true
51-
},
52-
type: 'success'
53-
});
54-
}, 1200);
55-
}
56-
};
57-
25+
5826
return (
5927
<>
6028
<ModalHeader
@@ -83,7 +51,7 @@ const DeleteProjectModal = (props: SettingsModalProps) => {
8351
icon="v2-Delete"
8452
tabindex={0}
8553
isLoading={isLoading}
86-
onClick={() => handleDeleteProject(closeModal)}
54+
onClick={() => handleDeleteProject()}
8755
>
8856
Delete
8957
</Button>

ui/src/components/Common/Settings/index.tsx

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import { Setting } from './setting.interface';
2323
import { ModalObj } from '../../../components/Modal/modal.interface';
2424

2525
// Service
26-
import { getProject, updateProject } from '../../../services/api/project.service';
26+
import { deleteProject, getProject, updateProject } from '../../../services/api/project.service';
2727
import { CS_ENTRIES } from '../../../utilities/constants';
2828
import { getCMSDataFromFile } from '../../../cmsData/cmsSelector';
2929

@@ -32,6 +32,9 @@ import DeleteProjectModal from '../DeleteProjectModal';
3232

3333
//stylesheet
3434
import './Settings.scss';
35+
import { useDispatch } from 'react-redux';
36+
import { updateNewMigrationData } from '../../../store/slice/migrationDataSlice';
37+
import { DEFAULT_NEW_MIGRATION } from '../../../context/app/app.interface';
3538

3639
/**
3740
* Renders the Settings component.
@@ -51,6 +54,7 @@ const Settings = () => {
5154
);
5255

5356
const navigate = useNavigate();
57+
const dispatch = useDispatch()
5458

5559
useEffect(() => {
5660
const fetchData = async () => {
@@ -120,6 +124,29 @@ const Settings = () => {
120124
});
121125
}
122126
};
127+
const handleDeleteProject = async (closeModal: ()=> void): Promise<void> => {
128+
//setIsLoading(true);
129+
const response = await deleteProject(selectedOrganisation?.value, params?.projectId ?? '');
130+
131+
if (response?.status === 200) {
132+
//setIsLoading(false);
133+
closeModal();
134+
dispatch(updateNewMigrationData(DEFAULT_NEW_MIGRATION));
135+
setTimeout(() => {
136+
navigate('/projects');
137+
}, 800);
138+
setTimeout(() => {
139+
Notification({
140+
notificationContent: { text: response?.data?.data?.message },
141+
notificationProps: {
142+
position: 'bottom-center',
143+
hideProgressBar: true
144+
},
145+
type: 'success'
146+
});
147+
}, 1200);
148+
}
149+
};
123150

124151
const handleClick = () => {
125152
cbModal({
@@ -129,6 +156,7 @@ const Settings = () => {
129156
projectId={params?.projectId ?? ''}
130157
projectName={projectName}
131158
navigate={navigate}
159+
handleDeleteProject={() => handleDeleteProject(props?.closeModal)}
132160
{...props}
133161
/>
134162
),

ui/src/components/Common/router.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ const AppRouter = () => {
3333

3434
{/* ALL PROTECTED ROUTES HERE */}
3535
<Route element={<PrivateRoute redirectTo="/" />}>
36-
<Route path="/migrations" element={<MigrationLazyLoad />} />
3736
<Route path="/projects" element={<ProjectsLazyLoad />} />
3837

3938
<Route

0 commit comments

Comments
 (0)