diff --git a/frontend/src/pages/integrations/details/[integrationId].tsx b/frontend/src/pages/integrations/details/[integrationId].tsx
index d437dabd4..f0db57472 100644
--- a/frontend/src/pages/integrations/details/[integrationId].tsx
+++ b/frontend/src/pages/integrations/details/[integrationId].tsx
@@ -1,7 +1,7 @@
import { useTranslation } from "react-i18next";
import Head from "next/head";
-import { IntegrationDetails } from "@app/views/IntegrationsPage/DetailsPage/DetailsPage";
+import { IntegrationDetailsPage } from "@app/views/IntegrationsPage/IntegrationDetailsPage";
export default function IntegrationsDetailsPage() {
const { t } = useTranslation();
@@ -15,7 +15,7 @@ export default function IntegrationsDetailsPage() {
-
+
>
);
}
diff --git a/frontend/src/views/IntegrationsPage/DetailsPage/index.tsx b/frontend/src/views/IntegrationsPage/DetailsPage/index.tsx
deleted file mode 100644
index e69de29bb..000000000
diff --git a/frontend/src/views/IntegrationsPage/DetailsPage/DetailsPage.tsx b/frontend/src/views/IntegrationsPage/IntegrationDetailsPage/IntegrationDetailsPage.tsx
similarity index 80%
rename from frontend/src/views/IntegrationsPage/DetailsPage/DetailsPage.tsx
rename to frontend/src/views/IntegrationsPage/IntegrationDetailsPage/IntegrationDetailsPage.tsx
index c645f0f39..6fe2a1562 100644
--- a/frontend/src/views/IntegrationsPage/DetailsPage/DetailsPage.tsx
+++ b/frontend/src/views/IntegrationsPage/IntegrationDetailsPage/IntegrationDetailsPage.tsx
@@ -5,7 +5,6 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { integrationSlugNameMapping } from "public/data/frequentConstants";
import { twMerge } from "tailwind-merge";
-import { createNotification } from "@app/components/notifications";
import { OrgPermissionCan } from "@app/components/permissions";
import {
Button,
@@ -15,32 +14,32 @@ import {
DropdownMenuTrigger,
Tooltip
} from "@app/components/v2";
-import { OrgPermissionActions, OrgPermissionSubjects, useUser, useWorkspace } from "@app/context";
+import {
+ OrgPermissionActions,
+ OrgPermissionSubjects,
+ useOrganization,
+ useUser,
+ useWorkspace
+} from "@app/context";
import { useGetIntegration } from "@app/hooks/api";
import { useSyncIntegration } from "@app/hooks/api/integrations/queries";
-import { usePopUp } from "@app/hooks/usePopUp";
+import { IntegrationAuditLogsSection } from "./components/IntegrationAuditLogsSection";
+import { IntegrationConnectionSection } from "./components/IntegrationConnectionSection";
import { IntegrationDetailsSection } from "./components/IntegrationDetailsSection";
+import { IntegrationSettingsSection } from "./components/IntegrationSettingsSection";
-// import { UserDetailsSection, UserOrgMembershipModal, UserProjectsSection } from "./components";
-
-export const IntegrationDetails = () => {
+export const IntegrationDetailsPage = () => {
const router = useRouter();
const integrationId = router.query.integrationId as string;
- const { data: integration } = useGetIntegration(integrationId);
+ const { data: integration } = useGetIntegration(integrationId, {
+ refetchInterval: 4000
+ });
const projectId = useWorkspace().currentWorkspace?.id;
const { mutateAsync: syncIntegration } = useSyncIntegration();
-
- const { user } = useUser();
-
- const { popUp, handlePopUpOpen, handlePopUpClose, handlePopUpToggle } = usePopUp([
- "removeMember",
- "orgMembership",
- "deactivateMember",
- "upgradePlan"
- ] as const);
+ const { currentOrg } = useOrganization();
return integration ? (
@@ -104,9 +103,15 @@ export const IntegrationDetails = () => {
-
diff --git a/frontend/src/views/IntegrationsPage/IntegrationDetailsPage/components/IntegrationAuditLogsSection.tsx b/frontend/src/views/IntegrationsPage/IntegrationDetailsPage/components/IntegrationAuditLogsSection.tsx
new file mode 100644
index 000000000..2d1c64db5
--- /dev/null
+++ b/frontend/src/views/IntegrationsPage/IntegrationDetailsPage/components/IntegrationAuditLogsSection.tsx
@@ -0,0 +1,78 @@
+import Link from "next/link";
+
+import { EmptyState } from "@app/components/v2";
+import { useSubscription } from "@app/context";
+import { EventType } from "@app/hooks/api/auditLogs/enums";
+import { TIntegrationWithEnv } from "@app/hooks/api/integrations/types";
+import { LogsSection } from "@app/views/Project/AuditLogsPage/components";
+
+// Add more events if needed
+const INTEGRATION_EVENTS = [EventType.INTEGRATION_SYNCED];
+
+type Props = {
+ integration: TIntegrationWithEnv;
+ orgId: string;
+};
+
+export const IntegrationAuditLogsSection = ({ integration, orgId }: Props) => {
+ const { subscription, isLoading } = useSubscription();
+
+ const auditLogsRetentionDays = subscription?.auditLogsRetentionDays ?? 30;
+
+ // eslint-disable-next-line no-nested-ternary
+ return subscription?.auditLogs ? (
+
+
+
Integration Logs
+
+ View integration logs from the past {auditLogsRetentionDays} days
+
+
+
+
+ ) : !isLoading ? (
+
+ }
+ />
+
+ ) : null;
+};
diff --git a/frontend/src/views/IntegrationsPage/DetailsPage/components/IntegrationDetailsSection.tsx b/frontend/src/views/IntegrationsPage/IntegrationDetailsPage/components/IntegrationConnectionSection.tsx
similarity index 59%
rename from frontend/src/views/IntegrationsPage/DetailsPage/components/IntegrationDetailsSection.tsx
rename to frontend/src/views/IntegrationsPage/IntegrationDetailsPage/components/IntegrationConnectionSection.tsx
index c7ab28e0c..7aa862593 100644
--- a/frontend/src/views/IntegrationsPage/DetailsPage/components/IntegrationDetailsSection.tsx
+++ b/frontend/src/views/IntegrationsPage/IntegrationDetailsPage/components/IntegrationConnectionSection.tsx
@@ -1,7 +1,4 @@
-import { faCheckCircle, faCircleXmark } from "@fortawesome/free-solid-svg-icons";
-import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { integrationSlugNameMapping } from "public/data/frequentConstants";
-import { twMerge } from "tailwind-merge";
import { FormLabel } from "@app/components/v2";
import { IntegrationMappingBehavior, TIntegrationWithEnv } from "@app/hooks/api/integrations/types";
@@ -10,7 +7,7 @@ type Props = {
integration: TIntegrationWithEnv;
};
-export const IntegrationDetailsSection = ({ integration }: Props) => {
+export const IntegrationConnectionSection = ({ integration }: Props) => {
const specifcQoveryDetails = () => {
if (integration.integration !== "qovery") return null;
@@ -79,7 +76,7 @@ export const IntegrationDetailsSection = ({ integration }: Props) => {
case "aws-parameter-store":
case "rundeck":
- return `${integration.path}aaaaa`;
+ return `${integration.path}`;
default:
return `${integration.app}`;
@@ -160,80 +157,36 @@ export const IntegrationDetailsSection = ({ integration }: Props) => {
};
return (
-
-
-
-
Integration Details
-
-
-
-
-
Name
-
- {integrationSlugNameMapping[integration.integration]}
-
-
-
-
Sync Status
-
-
- {integration.isSynced ? "Synced" : "Not Synced"}
-
-
-
-
-
- {!integration.isSynced && integration.syncMessage && (
- <>
-
Latest sync error
-
{integration.syncMessage}
- >
- )}
-
-
-
+
+
+
Connection
-
-
-
Connection
+
+
+
+
+
+
+
{integration.environment.name}
+
+
+
+
{integration.secretPath}
+
-
-
-
-
-
-
-
{integration.environment.name}
-
-
-
-
{integration.secretPath}
-
+
+
+
+
+ {integrationSlugNameMapping[integration.integration]}
-
-
-
-
- {integrationSlugNameMapping[integration.integration]}
-
-
- {specifcQoveryDetails()}
- {isNotAwsManagerOneToOneDetails()}
- {targetEnvironmentDetails()}
- {generalIntegrationSpecificDetails()}
-
+ {specifcQoveryDetails()}
+ {isNotAwsManagerOneToOneDetails()}
+ {targetEnvironmentDetails()}
+ {generalIntegrationSpecificDetails()}
diff --git a/frontend/src/views/IntegrationsPage/IntegrationDetailsPage/components/IntegrationDetailsSection.tsx b/frontend/src/views/IntegrationsPage/IntegrationDetailsPage/components/IntegrationDetailsSection.tsx
new file mode 100644
index 000000000..d2ffeb906
--- /dev/null
+++ b/frontend/src/views/IntegrationsPage/IntegrationDetailsPage/components/IntegrationDetailsSection.tsx
@@ -0,0 +1,69 @@
+import { faCalendarCheck, faCheckCircle, faCircleXmark } from "@fortawesome/free-solid-svg-icons";
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import { format } from "date-fns";
+import { integrationSlugNameMapping } from "public/data/frequentConstants";
+import { twMerge } from "tailwind-merge";
+
+import { TIntegrationWithEnv } from "@app/hooks/api/integrations/types";
+
+type Props = {
+ integration: TIntegrationWithEnv;
+};
+
+export const IntegrationDetailsSection = ({ integration }: Props) => {
+ return (
+
+
+
+
Integration Details
+
+
+
+
+
Name
+
+ {integrationSlugNameMapping[integration.integration]}
+
+
+
+
Sync Status
+
+
+ {integration.isSynced ? "Synced" : "Not Synced"}
+
+
+
+
+ {integration.lastUsed && (
+
+
Latest Successful Sync
+
+ {format(new Date(integration.lastUsed), "yyyy-MM-dd, hh:mm aaa")}
+
+
+
+ )}
+
+
+ {!integration.isSynced && integration.syncMessage && (
+ <>
+
Latest Sync Error
+
{integration.syncMessage}
+ >
+ )}
+
+
+
+
+
+ );
+};
diff --git a/frontend/src/views/IntegrationsPage/IntegrationDetailsPage/components/IntegrationSettingsSection.tsx b/frontend/src/views/IntegrationsPage/IntegrationDetailsPage/components/IntegrationSettingsSection.tsx
new file mode 100644
index 000000000..50c638b66
--- /dev/null
+++ b/frontend/src/views/IntegrationsPage/IntegrationDetailsPage/components/IntegrationSettingsSection.tsx
@@ -0,0 +1,89 @@
+import { TIntegrationWithEnv } from "@app/hooks/api/integrations/types";
+
+type Props = {
+ integration: TIntegrationWithEnv;
+};
+
+type Metadata = NonNullable
;
+type MetadataKey = keyof Metadata;
+type MetadataValue = Metadata[K];
+
+const metadataMappings: Record, string> = {
+ githubVisibility: "Github Visibility",
+ githubVisibilityRepoIds: "Github Visibility Repo Ids",
+ shouldAutoRedeploy: "Auto Redeploy Target Application When Secrets Change",
+ secretAWSTag: "Tags For Secrets Stored In AWS",
+ kmsKeyId: "AWS KMS Key ID",
+ secretSuffix: "Secret Suffix",
+ secretPrefix: "Secret Prefix",
+ syncBehavior: "Secrets Sync behavior",
+ mappingBehavior: "Secrets Mapping Behavior",
+ scope: "Scope",
+ org: "Organization",
+ project: "Project",
+ environment: "Environment",
+ shouldDisableDelete: "AWS Secret Deletion Disabled",
+ shouldMaskSecrets: "GitLab Secrets Masking Enabled",
+ shouldProtectSecrets: "GitLab Secret Protection Enabled",
+ shouldEnableDelete: "GitHub Secret Deletion Enabled"
+} as const;
+
+export const IntegrationSettingsSection = ({ integration }: Props) => {
+ const renderValue = (key: K, value: MetadataValue) => {
+ if (!value) return null;
+
+ // If it's a boolean, we render a generic "Yes" or "No" response.
+ if (typeof value === "boolean") {
+ return value ? "Yes" : "No";
+ }
+
+ // When the value is an object or array, or array of objects, we need to handle some special cases.
+ if (typeof value === "object") {
+ if (key === "secretAWSTag") {
+ return (value as MetadataValue<"secretAWSTag">)!.map(({ key: tagKey, value: tagValue }) => (
+
+ {tagKey}={tagValue}
+
+ ));
+ }
+
+ if (key === "githubVisibilityRepoIds") {
+ return value.join(", ");
+ }
+ }
+
+ if (typeof value === "string") {
+ return value.length ? value : "N/A";
+ }
+
+ if (typeof value === "number") {
+ return value;
+ }
+
+ return null;
+ };
+
+ if (!integration.metadata || Object.keys(integration.metadata).length === 0) {
+ return null;
+ }
+
+ // eslint-disable-next-line no-nested-ternary
+ return (
+
+
+
+ {integration.metadata &&
+ Object.entries(integration.metadata).map(([key, value]) => (
+
+
+ {metadataMappings[key as keyof typeof metadataMappings]}
+
+
{renderValue(key as MetadataKey, value)}
+
+ ))}
+
+
+ );
+};
diff --git a/frontend/src/views/IntegrationsPage/IntegrationDetailsPage/index.tsx b/frontend/src/views/IntegrationsPage/IntegrationDetailsPage/index.tsx
new file mode 100644
index 000000000..145a6e2e0
--- /dev/null
+++ b/frontend/src/views/IntegrationsPage/IntegrationDetailsPage/index.tsx
@@ -0,0 +1 @@
+export { IntegrationDetailsPage } from "./IntegrationDetailsPage";