Skip to content

Commit

Permalink
feat: git integration (#117)
Browse files Browse the repository at this point in the history
  • Loading branch information
rahulyadav-57 authored Dec 27, 2024
1 parent 0046745 commit 755c089
Show file tree
Hide file tree
Showing 43 changed files with 2,292 additions and 1,284 deletions.
1,974 changes: 770 additions & 1,204 deletions package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
"eslint": "^8.56.0",
"eslint-config-next": "13.1.6",
"eventemitter3": "^5.0.1",
"isomorphic-git": "^1.27.1",
"jsonwebtoken": "^9.0.0",
"lodash.clonedeep": "^4.5.0",
"mixpanel-browser": "^2.47.0",
Expand Down
8 changes: 8 additions & 0 deletions src/components/git/CommitChanges/CommitChanges.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.root {
margin-bottom: 1rem;
.form {
.formItem {
margin-bottom: 0.5rem;
}
}
}
80 changes: 80 additions & 0 deletions src/components/git/CommitChanges/CommitChanges.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import { useLogActivity } from '@/hooks/logActivity.hooks';
import { useProject } from '@/hooks/projectV2.hooks';
import GitManager from '@/lib/git';
import { getConfigValue } from '@/utility/git';
import { Button, Form, Input } from 'antd';
import { useForm } from 'antd/lib/form/Form';
import { FC, useState } from 'react';
import s from './CommitChanges.module.scss';

interface Props {
onCommit: (message: string) => void;
}

const CommitChanges: FC<Props> = ({ onCommit }) => {
const [form] = useForm();
const [isLoading, setIsLoading] = useState(false);
const { activeProject } = useProject();
const git = new GitManager();
const { createLog } = useLogActivity();

const commit = async ({ message }: { message: string }) => {
if (!activeProject?.path) return;
const [username, email] = await Promise.all([
getConfigValue('user.name', 'username', activeProject.path),
getConfigValue('user.email', 'email', activeProject.path),
]);

if (!username || !email) {
createLog('Please set username and email in git setting', 'error');
return;
}

try {
setIsLoading(true);

await git.commit(message, activeProject.path, {
name: username,
email: email,
});

onCommit(message);
} catch (error) {
if (error instanceof Error) {
createLog(error.message, 'error');
return;
}
createLog('Failed to commit changes', 'error');
} finally {
setIsLoading(false);
}
};

return (
<div className={s.root}>
<Form
form={form}
className={`${s.form} app-form`}
layout="vertical"
onFinish={commit}
autoComplete="off"
requiredMark="optional"
>
<Form.Item name="message" className={s.formItem}>
<Input placeholder="commit message" />
</Form.Item>

<Button
className={`w-100 item-center-align`}
loading={isLoading}
type="primary"
htmlType="submit"
>
Commit
</Button>
</Form>
</div>
);
};

export default CommitChanges;
1 change: 1 addition & 0 deletions src/components/git/CommitChanges/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './CommitChanges';
5 changes: 5 additions & 0 deletions src/components/git/GitRemote/GitRemote.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.root {
.formItem {
margin-bottom: 0.5rem;
}
}
81 changes: 81 additions & 0 deletions src/components/git/GitRemote/GitRemote.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import AppIcon from '@/components/ui/icon';
import { useProject } from '@/hooks/projectV2.hooks';
import GitManager from '@/lib/git';
import { delay } from '@/utility/utils';
import { Button, Form, Input } from 'antd';
import { FC, useEffect, useState } from 'react';
import s from './GitRemote.module.scss';

const GitRemote: FC = () => {
const git = new GitManager();

const [isLoading, setIsLoading] = useState(false);

const [form] = Form.useForm();

const { activeProject } = useProject();
const activeProjectPath = activeProject?.path ?? '';

const addRemote = async ({ url }: { url: string }) => {
try {
setIsLoading(true);
if (!url) {
await git.removeRemote(activeProjectPath);
return;
}
await git.addRemote(url, activeProjectPath);
} catch (error) {
console.error(error);
} finally {
await delay(500);
setIsLoading(false);
}
};

const getRemote = async () => {
try {
setIsLoading(true);
const remote = await git.getRemote(activeProjectPath);
let url = '';
if (remote.length !== 0) {
url = remote[0].url;
}
form.setFieldsValue({ url });
} catch (error) {
console.error(error);
} finally {
await delay(500);
setIsLoading(false);
}
};

useEffect(() => {
getRemote();
}, []);

return (
<div className={s.root}>
<Form
className={`${s.form} app-form`}
layout="vertical"
onFinish={addRemote}
requiredMark="optional"
form={form}
>
<Form.Item name="url" className={s.formItem}>
<Input placeholder="GitHub repository URL" />
</Form.Item>
<Button
type="primary"
className={`item-center-align w-100`}
htmlType="submit"
loading={isLoading}
>
<AppIcon name="Save" /> Save
</Button>
</Form>
</div>
);
};

export default GitRemote;
1 change: 1 addition & 0 deletions src/components/git/GitRemote/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './GitRemote';
6 changes: 6 additions & 0 deletions src/components/git/GitSetting/GitSetting.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.root {
padding: 0.5rem 0;
.formItem {
margin-bottom: 0.5rem;
}
}
113 changes: 113 additions & 0 deletions src/components/git/GitSetting/GitSetting.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
import AppIcon from '@/components/ui/icon';
import { useProject } from '@/hooks/projectV2.hooks';
import { getConfigValue, setConfigValue } from '@/utility/git';
import { delay } from '@/utility/utils';
import { Button, Form, Input } from 'antd';
import { FC, useEffect, useState } from 'react';
import s from './GitSetting.module.scss';

interface ISettings {
username: string;
email: string;
token: string;
}

const GitSetting: FC = () => {
const [isLoading, setIsLoading] = useState(false);

const [form] = Form.useForm();

const { activeProject } = useProject();
const activeProjectPath = activeProject?.path ?? '';

const onFormFinish = async (values: ISettings) => {
setIsLoading(true);
const { username, email } = values;
try {
await setConfigValue('user.name', username, activeProjectPath);
await delay(500);
setConfigValue('user.email', email, activeProjectPath);

localStorage.setItem('gitConfig', JSON.stringify(values));
// dummy delay to show loading
await delay(500);
} catch (error) {
console.error('Error saving Git settings', error);
} finally {
setIsLoading(false);
}
};

useEffect(() => {
(async () => {
setIsLoading(true);
const gitConfig = JSON.parse(localStorage.getItem('gitConfig') ?? '{}');

const [username, email, token] = await Promise.all([
getConfigValue('user.name', 'username', activeProjectPath),
getConfigValue('user.email', 'email', activeProjectPath),
gitConfig.token ?? '',
]);
form.setFieldsValue({ username, email, token });
setIsLoading(false);
})();
}, []);

if (!activeProjectPath) return <></>;

return (
<div className={s.root}>
<Form
className={`${s.form} app-form`}
layout="vertical"
onFinish={onFormFinish}
requiredMark="optional"
form={form}
>
<Form.Item
name="username"
rules={[{ required: true }]}
className={s.formItem}
>
<Input placeholder="Username, e.g., John Doe" />
</Form.Item>
<Form.Item
name="email"
rules={[{ required: true, type: 'email' }]}
className={s.formItem}
>
<Input placeholder="Email" />
</Form.Item>
<Form.Item
name="token"
rules={[{ required: true }]}
className={s.formItem}
extra={
<>
Guide to create a personal access token:{' '}
<a
href="https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens"
target="_blank"
rel="noopener noreferrer"
>
GitHub Documentation
</a>
</>
}
>
<Input.Password placeholder="Git Personal Access Token" />
</Form.Item>
<Button
type="primary"
className={`item-center-align w-100`}
htmlType="submit"
loading={isLoading}
>
<AppIcon name="Save" /> Save
</Button>
</Form>
</div>
);
};

export default GitSetting;
1 change: 1 addition & 0 deletions src/components/git/GitSetting/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './GitSetting';
8 changes: 8 additions & 0 deletions src/components/git/GitSync/GitSync.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.root {
.actions {
display: flex;
align-items: center;
justify-content: center;
gap: 0.5rem;
}
}
Loading

0 comments on commit 755c089

Please sign in to comment.