misc: applied ui/ux changes

This commit is contained in:
Sheen Capadngan
2024-05-22 00:06:06 +08:00
parent 9b404c215b
commit b9a9b6b4d9
3 changed files with 65 additions and 94 deletions
@@ -1,10 +1,10 @@
import { MutableRefObject } from "react";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { createNotification } from "@app/components/notifications";
import { apiRequest } from "@app/config/request"; import { apiRequest } from "@app/config/request";
import { workspaceKeys } from "../workspace/queries"; import { workspaceKeys } from "../workspace/queries";
import { TCloudIntegration, TIntegration } from "./types"; import { TCloudIntegration } from "./types";
export const integrationQueryKeys = { export const integrationQueryKeys = {
getIntegrations: () => ["integrations"] as const getIntegrations: () => ["integrations"] as const
@@ -112,27 +112,14 @@ export const useDeleteIntegration = () => {
}); });
}; };
export const useSyncIntegration = (pollingRef: MutableRefObject<NodeJS.Timeout | null>) => { export const useSyncIntegration = () => {
const queryClient = useQueryClient();
return useMutation<{}, {}, { id: string; workspaceId: string; lastUsed: string }>({ return useMutation<{}, {}, { id: string; workspaceId: string; lastUsed: string }>({
mutationFn: ({ id }) => apiRequest.post(`/api/v1/integration/${id}/sync`), mutationFn: ({ id }) => apiRequest.post(`/api/v1/integration/${id}/sync`),
onSuccess: (_, { id, workspaceId, lastUsed }) => { onSuccess: () => {
// eslint-disable-next-line no-param-reassign createNotification({
pollingRef.current = setInterval(() => { text: "Successfully triggered manual sync",
const integrations: TIntegration[] | undefined = queryClient.getQueryData( type: "success"
workspaceKeys.getWorkspaceIntegrations(workspaceId) });
);
const integration = integrations?.find((entry) => entry.id === id);
if (!integration || integration.lastUsed !== lastUsed) {
clearInterval(pollingRef.current as NodeJS.Timeout);
// eslint-disable-next-line no-param-reassign
pollingRef.current = null;
return;
}
queryClient.invalidateQueries(workspaceKeys.getWorkspaceIntegrations(workspaceId));
}, 3500);
} }
}); });
}; };
+2 -1
View File
@@ -198,7 +198,8 @@ export const useGetWorkspaceIntegrations = (workspaceId: string) =>
useQuery({ useQuery({
queryKey: workspaceKeys.getWorkspaceIntegrations(workspaceId), queryKey: workspaceKeys.getWorkspaceIntegrations(workspaceId),
queryFn: () => fetchWorkspaceIntegrations(workspaceId), queryFn: () => fetchWorkspaceIntegrations(workspaceId),
enabled: Boolean(workspaceId) enabled: Boolean(workspaceId),
refetchInterval: 4000
}); });
export const createWorkspace = ({ export const createWorkspace = ({
@@ -1,7 +1,6 @@
import { useEffect, useRef } from "react";
import Link from "next/link"; import Link from "next/link";
import { faCalendarCheck } from "@fortawesome/free-regular-svg-icons"; import { faCalendarCheck } from "@fortawesome/free-regular-svg-icons";
import { faArrowRight, faRefresh, faXmark } from "@fortawesome/free-solid-svg-icons"; import { faArrowRight, faRefresh, faWarning, faXmark } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { format } from "date-fns"; import { format } from "date-fns";
import { integrationSlugNameMapping } from "public/data/frequentConstants"; import { integrationSlugNameMapping } from "public/data/frequentConstants";
@@ -45,16 +44,7 @@ export const IntegrationsSection = ({
"deleteConfirmation" "deleteConfirmation"
] as const); ] as const);
const syncPollingRef = useRef<NodeJS.Timeout | null>(null); const { mutate: syncIntegration } = useSyncIntegration();
const { mutate: syncIntegration } = useSyncIntegration(syncPollingRef);
useEffect(() => {
return () => {
if (syncPollingRef.current) {
clearInterval(syncPollingRef.current);
}
};
}, []);
return ( return (
<div className="mb-8"> <div className="mb-8">
@@ -207,69 +197,62 @@ export const IntegrationsSection = ({
</div> </div>
<div className="mt-[1.5rem] flex cursor-default"> <div className="mt-[1.5rem] flex cursor-default">
{integration.isSynced != null && integration.lastUsed != null && ( {integration.isSynced != null && integration.lastUsed != null && (
<> <Tag
<Tag key={integration.id}
key={integration.id} className={integration.isSynced ? "bg-green-800" : "bg-red/80"}
className={integration.isSynced ? "bg-green/50" : "bg-red/80"} >
> <Tooltip
<Tooltip center
center className="max-w-xs whitespace-normal break-words"
className="max-w-xs whitespace-normal break-words" content={
content={ <div className="flex max-h-[10rem] flex-col overflow-auto ">
<div className="flex max-h-[10rem] flex-col overflow-auto "> <div className="flex self-start">
<div className="flex self-start"> <FontAwesomeIcon
<FontAwesomeIcon icon={faCalendarCheck}
icon={faCalendarCheck} className="pt-0.5 pr-2 text-sm"
className="pt-0.5 pr-2 text-sm" />
/> <div className="text-sm">Last sync</div>
<div className="text-sm">Last sync</div>
</div>
<div className="pl-5 text-left text-xs">
{format(new Date(integration.lastUsed), "yyyy-MM-dd, hh:mm aaa")}
</div>
{!integration.isSynced && (
<>
<div className="mt-2 flex self-start">
<FontAwesomeIcon icon={faXmark} className="pt-1 pr-2 text-sm" />
<div className="text-sm">Fail reason</div>
</div>
<div className="pl-5 text-left text-xs">
{integration.syncMessage}
</div>
</>
)}
</div> </div>
} <div className="pl-5 text-left text-xs">
> {format(new Date(integration.lastUsed), "yyyy-MM-dd, hh:mm aaa")}
<div className="px-2 text-white">Sync Status</div> </div>
</Tooltip> {!integration.isSynced && (
</Tag> <>
{!integration.isSynced && integration.lastUsed != null && ( <div className="mt-2 flex self-start">
<div className="mr-1 flex items-end opacity-80 duration-200 hover:opacity-100"> <FontAwesomeIcon icon={faXmark} className="pt-1 pr-2 text-sm" />
<Tooltip <div className="text-sm">Fail reason</div>
className="text-center" </div>
content="Manually sync integration secrets" <div className="pl-5 text-left text-xs">
> {integration.syncMessage}
<Button </div>
onClick={() => </>
syncIntegration({ )}
workspaceId, </div>
id: integration.id, }
lastUsed: integration.lastUsed as string >
}) <div className="flex items-center space-x-2 text-white">
} <div>Sync Status</div>
isLoading={!!syncPollingRef.current} {!integration.isSynced && <FontAwesomeIcon icon={faWarning} />}
className="max-w-[2.5rem] bg-mineshaft-500"
colorSchema="primary"
variant="outline"
>
<FontAwesomeIcon icon={faRefresh} className="px-1 text-bunker-200" />
</Button>
</Tooltip>
</div> </div>
)} </Tooltip>
</> </Tag>
)} )}
<div className="mr-1 flex items-end opacity-80 duration-200 hover:opacity-100">
<Tooltip className="text-center" content="Manually sync integration secrets">
<Button
onClick={() =>
syncIntegration({
workspaceId,
id: integration.id,
lastUsed: integration.lastUsed as string
})
}
className="max-w-[2.5rem] border-none bg-mineshaft-500"
>
<FontAwesomeIcon icon={faRefresh} className="px-1 text-bunker-200" />
</Button>
</Tooltip>
</div>
<ProjectPermissionCan <ProjectPermissionCan
I={ProjectPermissionActions.Delete} I={ProjectPermissionActions.Delete}
a={ProjectPermissionSub.Integrations} a={ProjectPermissionSub.Integrations}