feature: add suport for project scoped app connections

This commit is contained in:
Scott Wilson
2025-09-12 17:26:01 -07:00
parent 666ae3bc54
commit 93e5cf4b2b
135 changed files with 2823 additions and 742 deletions
@@ -1,10 +1,11 @@
import { useEffect } from "react";
import { useEffect, useState } from "react";
import { faArrowUpRightFromSquare, faBookOpen, faPlus } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { useNavigate, useSearch } from "@tanstack/react-router";
import { ProjectPermissionCan } from "@app/components/permissions";
import { CreateSecretSyncModal } from "@app/components/secret-syncs";
import { TSecretSyncForm } from "@app/components/secret-syncs/forms/schemas";
import { Button, Spinner } from "@app/components/v2";
import { ROUTE_PATHS } from "@app/const/routes";
import { ProjectPermissionSub, useWorkspace } from "@app/context";
@@ -16,8 +17,9 @@ import { SecretSyncsTable } from "./SecretSyncTable";
export const SecretSyncsTab = () => {
const { popUp, handlePopUpOpen, handlePopUpToggle } = usePopUp(["addSync"] as const);
const [initialSyncFormData, setInitialSyncFormData] = useState<Partial<TSecretSyncForm>>();
const { addSync, ...search } = useSearch({
const { addSync, connectionId, connectionName, ...search } = useSearch({
from: ROUTE_PATHS.SecretManager.IntegrationsListPage.id
});
@@ -38,6 +40,38 @@ export const SecretSyncsTab = () => {
});
}, [addSync]);
useEffect(() => {
if (connectionId && connectionName) {
const storedFormData = localStorage.getItem("secretSyncFormData");
if (!storedFormData) return;
let form: Partial<TSecretSyncForm> = {};
try {
form = JSON.parse(storedFormData) as TSecretSyncForm;
} catch {
return;
} finally {
localStorage.removeItem("secretSyncFormData");
}
handlePopUpOpen("addSync", form.destination);
setInitialSyncFormData({
...form,
connection: { id: connectionId, name: connectionName }
});
navigate({
to: ROUTE_PATHS.SecretManager.IntegrationsListPage.path,
params: {
projectId: currentWorkspace.id
},
search
});
}
}, [connectionId, connectionName]);
const { data: secretSyncs = [], isPending: isSecretSyncsPending } = useListSecretSyncs(
currentWorkspace.id,
{
@@ -100,7 +134,11 @@ export const SecretSyncsTab = () => {
<CreateSecretSyncModal
selectSync={popUp.addSync.data}
isOpen={popUp.addSync.isOpen}
onOpenChange={(isOpen) => handlePopUpToggle("addSync", isOpen)}
initialFormData={initialSyncFormData}
onOpenChange={(isOpen) => {
if (!isOpen) setInitialSyncFormData(undefined);
handlePopUpToggle("addSync", isOpen);
}}
/>
</>
);
@@ -17,7 +17,9 @@ import { IntegrationsListPage } from "./IntegrationsListPage";
const IntegrationsListPageQuerySchema = z.object({
selectedTab: z.nativeEnum(IntegrationsListPageTabs).optional(),
addSync: z.nativeEnum(SecretSync).optional()
addSync: z.nativeEnum(SecretSync).optional(),
connectionId: z.string().optional(),
connectionName: z.string().optional()
});
export const Route = createFileRoute(
@@ -6,7 +6,9 @@ import { OverviewPage } from "./OverviewPage";
const SecretOverviewPageQuerySchema = z.object({
search: z.string().catch(""),
secretPath: z.string().catch("/")
secretPath: z.string().catch("/"),
connectionId: z.string().optional(),
connectionName: z.string().optional()
});
export const Route = createFileRoute(
@@ -10,7 +10,9 @@ import { SecretDashboardPage } from "./SecretDashboardPage";
const SecretDashboardPageQueryParamsSchema = z.object({
secretPath: z.string().catch("/"),
search: z.string().catch(""),
tags: z.string().catch("")
tags: z.string().catch(""),
connectionId: z.string().optional(),
connectionName: z.string().optional()
});
export const Route = createFileRoute(
"/_authenticate/_inject-org-details/_org-layout/projects/secret-management/$projectId/_secret-manager-layout/secrets/$envSlug"