Skip to content

Commit b85fc23

Browse files
committed
feat(web): Implement download argocd template functionality
1 parent 64afb62 commit b85fc23

10 files changed

Lines changed: 150 additions & 16 deletions

File tree

web/src/components/navbar/navbar.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,13 @@ const navbar = [
2626

2727
const Navbar: FC = () => {
2828
return (
29-
<nav className="flex items-center p-4 border-b border-gray-500 h-14">
30-
<div className="flex items-center justify-between w-full gap-4">
29+
<nav className="flex h-14 items-center border-b border-gray-500 p-4">
30+
<div className="flex w-full items-center justify-between gap-4">
3131
<img src="/images/logo-svg.svg" className="mr-8" width={60} />
3232
<div className="flex items-center gap-5">
3333
{navbar.map((link) => (
3434
<NavLink
35+
key={link.url}
3536
to={link.url}
3637
className={({ isActive }) => (isActive ? 'text-orange-base' : '')}
3738
>

web/src/config/global.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
export const BASE_API = import.meta.env.VITE_API_CLIENT_BASE_URL;
2+
console.log(BASE_API);

web/src/core/react-query.ts

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
1-
import { AxiosError, AxiosHeaders, AxiosInstance, AxiosResponse } from 'axios';
1+
import {
2+
AxiosError,
3+
AxiosHeaders,
4+
AxiosInstance,
5+
AxiosRequestConfig,
6+
AxiosResponse,
7+
} from 'axios';
28
import { useMutation } from '@tanstack/react-query';
39
import { apiClient } from '@/lib/axios';
410

@@ -8,15 +14,15 @@ async function request<R, B, E = unknown>(
814
url: string,
915
body?: B,
1016
headers?: AxiosHeaders,
17+
config?: AxiosRequestConfig,
1118
): Promise<AxiosResponse<R>> {
1219
try {
1320
return await axiosInstance({
1421
method,
1522
url,
1623
...(method !== 'get' && { data: body }),
17-
headers: {
18-
...headers,
19-
},
24+
headers,
25+
...config,
2026
});
2127
} catch (error) {
2228
throw error as AxiosError<E>;
@@ -28,11 +34,12 @@ function mutationHook(method: 'get' | 'post' | 'put' | 'patch') {
2834
url: string,
2935
key: string,
3036
headers?: AxiosHeaders,
37+
configs?: AxiosRequestConfig,
3138
) {
3239
return useMutation<AxiosResponse<R>, AxiosError<E>, B>({
3340
mutationKey: [key],
3441
mutationFn: (body: B) =>
35-
request<R, B, E>(apiClient, method, url, body, headers),
42+
request<R, B, E>(apiClient, method, url, body, headers, configs),
3643
});
3744
};
3845
}

web/src/enums/api.enums.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
export enum TerraformTemplateAPI {
2+
Argocd = '/IaC-template/argocd',
3+
Iam = '/IaC-template/aws/iam',
4+
S3 = '/IaC-template/aws/s3',
5+
EC2 = '/IaC-template/aws/ec2',
6+
Docker = '/IaC-template/docker',
7+
}

web/src/hooks/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import useDownload from './useDownload';
2+
3+
export { useDownload };

web/src/hooks/useDownload.ts

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import { useGet } from '@/core/react-query';
2+
import { useEffect } from 'react';
3+
4+
type UseDownloadProps = {
5+
folderName: string;
6+
source: string;
7+
downloadFileName: string;
8+
};
9+
10+
const useDownload = ({
11+
folderName,
12+
source,
13+
downloadFileName,
14+
}: UseDownloadProps) => {
15+
const { mutateAsync, isSuccess, data, isPending } = useGet<string, undefined>(
16+
`/download-folder${folderName}/${source}`,
17+
'download',
18+
undefined,
19+
{ responseType: 'blob' },
20+
);
21+
22+
useEffect(() => {
23+
if (isSuccess) {
24+
const blob = new Blob([data.data], {
25+
type: data.headers['content-type'],
26+
});
27+
const link = document.createElement('a');
28+
link.href = URL.createObjectURL(blob);
29+
link.download = `${downloadFileName}.zip`;
30+
document.body.appendChild(link);
31+
link.click();
32+
document.body.removeChild(link);
33+
}
34+
}, [isSuccess, data]);
35+
36+
const download = async () => {
37+
return await mutateAsync(undefined);
38+
};
39+
40+
return { download, isSuccess, isPending };
41+
};
42+
43+
export default useDownload;

web/src/main.tsx

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,15 @@ createRoot(document.getElementById('root')!).render(
1414
<App />
1515
</QueryProvider>
1616
</BrowserRouter>
17-
<Toaster />
17+
<Toaster
18+
position="bottom-right"
19+
toastOptions={{
20+
closeButton: true,
21+
className: 'bg-orange-base text-white',
22+
classNames: {
23+
closeButton: 'text-black',
24+
},
25+
}}
26+
/>
1827
</StrictMode>,
1928
);

web/src/pages/terraform-template/ARGOCD/argocd.tsx

Lines changed: 53 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,23 @@
11
import { cn } from '@/lib/utils';
2-
import { FC, useState } from 'react';
2+
import { FC, FormEvent, useState } from 'react';
33
import { ChevronDown } from 'lucide-react';
4+
import { TerraformTemplateAPI } from '@/enums/api.enums';
5+
import { usePost } from '@/core/react-query';
6+
import { ArgocdBody, ArgocdResponse } from './argocd.types';
7+
import { toast } from 'sonner';
8+
import { useDownload } from '@/hooks';
49

510
const Argocd: FC = () => {
11+
const { mutateAsync: argocdMutate, isPending: argocdPending } = usePost<
12+
ArgocdResponse,
13+
ArgocdBody
14+
>(TerraformTemplateAPI.Argocd, 'argocd');
15+
const { download, isPending: downloadPending } = useDownload({
16+
folderName: 'MyTerraform',
17+
source: 'argocd',
18+
downloadFileName: 'Argocd',
19+
});
20+
621
const [dropdown, setDropdown] = useState({
722
argo_application: false,
823
sync_policy: false,
@@ -28,8 +43,33 @@ const Argocd: FC = () => {
2843
}));
2944
};
3045

46+
const handleForm = async (e: FormEvent) => {
47+
e.preventDefault();
48+
49+
try {
50+
const argocdBody: ArgocdBody = {
51+
argocd_application: dropdown.argo_application
52+
? {
53+
sync_policy: {
54+
auto_prune: services.auto_prune,
55+
self_heal: services.self_heal,
56+
},
57+
}
58+
: null,
59+
argocd_repository: services.argocd_repository,
60+
application_depends_repository: services.application_depends_repository,
61+
};
62+
63+
await argocdMutate(argocdBody);
64+
await download();
65+
} catch (error) {
66+
console.log(error);
67+
toast.error('Something went wrong');
68+
}
69+
};
70+
3171
return (
32-
<div className="w-full max-w-96">
72+
<form onSubmit={handleForm} className="w-full max-w-96">
3373
<div className="rounded-md border border-gray-500">
3474
<div className="divide-y divide-gray-500">
3575
<div className="flex w-full items-center justify-between px-3 py-3">
@@ -118,10 +158,18 @@ const Argocd: FC = () => {
118158
</div>
119159
</div>
120160
</div>
121-
<button className="btn mt-3 w-full bg-orange-base text-white hover:bg-orange-base/70">
122-
Submit
161+
<button
162+
type="submit"
163+
disabled={argocdPending || downloadPending}
164+
className="btn mt-3 w-full bg-orange-base text-white hover:bg-orange-base/70 disabled:bg-orange-base/50 disabled:text-white/70"
165+
>
166+
{argocdPending
167+
? 'GPT Answer...'
168+
: downloadPending
169+
? 'Generate Terraform...'
170+
: 'Generate Terraform'}
123171
</button>
124-
</div>
172+
</form>
125173
);
126174
};
127175

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
export interface ArgocdBody {
2+
argocd_application: {
3+
sync_policy: {
4+
auto_prune: boolean;
5+
self_heal: boolean;
6+
};
7+
} | null;
8+
argocd_repository: boolean;
9+
application_depends_repository: boolean;
10+
}
11+
12+
export interface ArgocdResponse {
13+
output: 'string';
14+
}

web/src/pages/terraform-template/components/layout.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,11 @@ const menu = [
2626

2727
const TerraformTemplate: FC = () => {
2828
return (
29-
<div className="flex items-center h-dvh">
30-
<div className="flex flex-col items-center justify-center w-full h-full border-r border-gray-500 divide-y divide-gray-500 max-w-96">
29+
<div className="flex h-dvh items-center">
30+
<div className="flex h-full w-full max-w-96 flex-col items-center justify-center divide-y divide-gray-500 border-r border-gray-500">
3131
{menu.map((link) => (
3232
<NavLink
33+
key={link.url}
3334
to={link.url}
3435
className={({ isActive }) =>
3536
`block w-full p-4 text-center outline-none transition-all ${isActive ? 'bg-orange-base' : ''}`
@@ -39,7 +40,7 @@ const TerraformTemplate: FC = () => {
3940
</NavLink>
4041
))}
4142
</div>
42-
<div className="flex items-center justify-center w-2/3 h-full">
43+
<div className="flex h-full w-2/3 items-center justify-center">
4344
<Outlet />
4445
</div>
4546
</div>

0 commit comments

Comments
 (0)