Skip to content

Commit

Permalink
Merge pull request #99 from MiladSadeghi/master
Browse files Browse the repository at this point in the history
refactor(argocd): improve ArgoCD UI for better usability
  • Loading branch information
mohammadll authored Nov 27, 2024
2 parents bda80c4 + 31378f5 commit 6b07ce3
Show file tree
Hide file tree
Showing 7 changed files with 169 additions and 41 deletions.
2 changes: 2 additions & 0 deletions web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"@emotion/react": "^11.13.3",
"@tanstack/react-query": "^5.59.19",
"axios": "^1.7.7",
"clsx": "^2.1.1",
"i": "^0.3.7",
"next-themes": "^0.4.3",
"npm": "^10.9.0",
Expand All @@ -22,6 +23,7 @@
"react-hook-form": "^7.53.2",
"react-icons": "^5.3.0",
"react-router-dom": "^6.27.0",
"tailwind-merge": "^2.5.5",
"uuid": "^11.0.3",
"zustand": "^5.0.1"
},
Expand Down
17 changes: 17 additions & 0 deletions web/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions web/src/components/internal-ui/PlatformBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ interface PlatformProps<FormData, RequestData> {
mapperFunction: (data: FormData) => RequestData;
}

const PlatformBox = <FormData extends {}, RequestData extends {}>({
const PlatformBox = <FormData extends object, RequestData extends object>({
serviceName,
defaultValues,
endpoint,
Expand All @@ -36,7 +36,7 @@ const PlatformBox = <FormData extends {}, RequestData extends {}>({
<div className="flex flex-col ">
<FormProvider {...formMethods}>
<form onSubmit={handleFormSubmit}>
<div className="flex flex-col justify-between w-full border items-center gap-y-5 border-orange-300 p-8">
<div className="flex flex-col items-center justify-between w-full p-8 border border-orange-300 gap-y-5">
<HStack lg={{ gap: 5 }} md={{ gap: 3 }}>
<p className="font-bold">{serviceName}: </p>
{fieldProperties.map((field) => (
Expand Down
5 changes: 1 addition & 4 deletions web/src/features/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,8 @@ export enum TerraformIAMFields {
export enum TerraformArgocdFields {
AUTO_PRUNE = "autoPrune",
SELF_HEAL = "selfHeal",
APPLY_OUT_OF_SYNC_ONLY = "applyOutOfSyncOnly",
CREATE_NAMESPACE = "createNamespace",
FAIL_OR_SHARE_RESOURCE = "failOrShareResource",
ARGOCD_REPOSITORY = "argocdRepository",
ARGOCD_CLUSTER = "argocdCluster",
APPLICATION_DEPENDS_REPOSITORY = "applicationDependsRepository",
}

export enum UserType {
Expand Down
160 changes: 139 additions & 21 deletions web/src/features/terraform/components/Argocd.tsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,146 @@
import PlatformBox from "../../../components/internal-ui/PlatformBox";
import useFindPlatform from "../../../hooks/useFindPlatform";
import { TerraformServices } from "../../constants";
import {
ApiRequestTerraformArgocd,
TerraformArgocdFormData,
} from "../../models";
import { useEffect, useState } from "react";
import { cn } from "../../../utils/tailwind";
import { FaChevronDown } from "react-icons/fa";
import apiClient from "../../../utils/apiClient";
import { Endpoints } from "../../constants";
import { useMutation } from "@tanstack/react-query";
import { AxiosResponse } from "axios";

const Argocd = () => {
const { platform } = useFindPlatform(TerraformServices.ARGOCD);
const [buttons, setButtons] = useState({
auto_prune: false,
self_heal: false,
argocd_repository: false,
application_depends_repository: false
});

const [menus, setMenus] = useState({
argocd_application: true,
sync_policy: true
});

const [error, setError] = useState(false);

const {data, isPending, isError, isSuccess, mutate} = useMutation<AxiosResponse, Error, {body: {argocd_application: {sync_policy: {auto_prune: boolean, self_heal: boolean}} | null, argocd_repository: boolean, application_depends_repository: boolean}}>({
mutationKey: ["argocd"],
mutationFn: async ({body}) => {
await apiClient.post(Endpoints.POST_IAC_ARGOCD, {...body});
return await apiClient.get(`${Endpoints.GET_DOWNLOAD_TERRAFORM}MyTerraform/argocd`, {responseType: "blob"});
}
})

useEffect(() => {
if (isError) {
setError(true);
setTimeout(() => {
setError(false);
}, 3000);
}
}, [isError]);

useEffect(() => {
if (isSuccess && data) {
const blob = new Blob([data.data], { type: data.headers['content-type'] });
const link = document.createElement('a');
link.href = URL.createObjectURL(blob);
link.download = "Argocd.zip";
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
}, [isSuccess, data])

useEffect(() => {
if (!menus.argocd_application) {
setButtons({
...buttons,
auto_prune: false,
self_heal: false
})
}
}, [menus])

const handleButtons = (button: keyof typeof buttons) => {
setButtons({...buttons, [button]: !buttons[button]})
}

const handleMenus = (menu: keyof typeof menus) => {
setMenus({...menus, [menu]: !menus[menu]})
}

const handleSubmit = async () => {
const body = {
argocd_application: (
menus.argocd_application
? {
sync_policy: {
auto_prune: buttons.auto_prune,
self_heal: buttons.self_heal
}
}
: null
),
argocd_repository: buttons.argocd_repository,
application_depends_repository: buttons.application_depends_repository
};

mutate({body})
}

return (
<>
{platform && (
<PlatformBox
defaultValues={platform.defaultValues as TerraformArgocdFormData}
endpoint={platform.endpoint}
fieldProperties={platform.fieldProperties}
mapperFunction={
platform.mapperFunction as () => ApiRequestTerraformArgocd
}
serviceName={platform.serviceName}
/>
)}
</>
<div className="flex flex-col items-center justify-center">
<div className="w-full bg-orange-800 divide-y-2 divide-gray-300 rounded-md max-w-96">
<div className="divide-y-2 divide-gray-300">
<div className="flex items-center justify-between w-full px-4 py-2">
<p>Argocd Application</p>
<input type="checkbox" className={cn('border-orange-[#2e323a] toggle [--tglbg:#2e323a] bg-orange-300 hover:bg-orange-400', {
'bg-[#5b6372] hover:bg-[#5b6372]': !menus.argocd_application,
}) } checked={menus.argocd_application} onChange={() => {handleMenus("argocd_application")}} />
</div>
<div className={cn("divide-y-2 divide-gray-300 max-h-0 overflow-hidden transition-all ease-linear duration-300", {"max-h-96": menus.argocd_application})}>
<button className="flex items-center justify-between w-full py-2 pl-10 pr-4" onClick={() => handleMenus("sync_policy")}>
<p>Sync Policy</p>
<FaChevronDown className={cn('transition-all', {"rotate-180": menus.sync_policy})} />
</button>
<div className={cn("divide-y-2 divide-gray-300 max-h-0 overflow-hidden transition-all ease-linear duration-300", {"max-h-96": menus.sync_policy})}>
<div className="py-2 pl-16 pr-4">
<div className="flex items-center justify-between">
<p>Auto Prune</p>
<input type="checkbox" className={cn('border-orange-[#2e323a] toggle [--tglbg:#2e323a] bg-orange-300 hover:bg-orange-400', {
'bg-[#5b6372] hover:bg-[#5b6372]': !buttons.auto_prune,
}) } checked={buttons.auto_prune} onChange={() => handleButtons("auto_prune")} />
</div>
</div>
<div className="py-2 pl-16 pr-4">
<div className="flex items-center justify-between">
<p>Self Heal</p>
<input type="checkbox" className={cn('border-orange-[#2e323a] toggle [--tglbg:#2e323a] bg-orange-300 hover:bg-orange-400', {
'bg-[#5b6372] hover:bg-[#5b6372]': !buttons.self_heal,
}) } checked={buttons.self_heal} onChange={() => handleButtons("self_heal")} />
</div>
</div>
</div>
</div>
<div className="px-4 py-2">
<div className="flex items-center justify-between">
<p>Argocd Repository</p>
<input type="checkbox" className={cn('border-orange-[#2e323a] toggle [--tglbg:#2e323a] bg-orange-300 hover:bg-orange-400', {
'bg-[#5b6372] hover:bg-[#5b6372]': !buttons.argocd_repository,
}) } checked={buttons.argocd_repository} onChange={() => handleButtons("argocd_repository")} />
</div>
</div>
<div className="px-4 py-2">
<div className="flex items-center justify-between">
<p>Application Depends Repository</p>
<input type="checkbox" className={cn('border-orange-[#2e323a] toggle [--tglbg:#2e323a] bg-orange-300 hover:bg-orange-400', {
'bg-[#5b6372] hover:bg-[#5b6372]': !buttons.application_depends_repository,
}) } checked={buttons.application_depends_repository} onChange={() => handleButtons("application_depends_repository")} />
</div>
</div>
</div>
</div>
<button disabled={isPending} onClick={() => handleSubmit()} className="w-full py-2 mt-4 text-center transition-all bg-orange-800 rounded-md btn max-w-96 hover:bg-orange-900">{isPending ? <div className="flex items-center justify-center gap-4 disabled:opacity-80"><span className="loading loading-spinner"></span>Loading</div>: error ? "Error" : "Submit"}</button>
</div>
);
};

Expand Down
16 changes: 2 additions & 14 deletions web/src/features/terraform/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,25 +81,13 @@ const argocdFieldProperties: Checkboxprops[] = [
fieldName: TerraformArgocdFields.SELF_HEAL,
label: "Self heal",
},
{
fieldName: TerraformArgocdFields.APPLY_OUT_OF_SYNC_ONLY,
label: "Apply out of sync only",
},
{
fieldName: TerraformArgocdFields.CREATE_NAMESPACE,
label: "Create namespace",
},
{
fieldName: TerraformArgocdFields.FAIL_OR_SHARE_RESOURCE,
label: "Fail or share resource",
},
{
fieldName: TerraformArgocdFields.ARGOCD_REPOSITORY,
label: "ARGOCD repository",
},
{
fieldName: TerraformArgocdFields.ARGOCD_CLUSTER,
label: "ARGOCD cluster",
fieldName: TerraformArgocdFields.APPLICATION_DEPENDS_REPOSITORY ,
label: "Application depends repository",
},
];

Expand Down
6 changes: 6 additions & 0 deletions web/src/utils/tailwind.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import clsx, { ClassValue } from 'clsx';
import { twMerge } from 'tailwind-merge';

export const cn = (...inputs: ClassValue[]) => {
return twMerge(clsx(inputs));
};

0 comments on commit 6b07ce3

Please sign in to comment.