mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-07 13:27:46 +00:00
misc: applied ui/ux changes
This commit is contained in:
@@ -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);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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 = ({
|
||||||
|
|||||||
+55
-72
@@ -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}
|
||||||
|
|||||||
Reference in New Issue
Block a user