diff --git a/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/ActionBar.tsx b/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/ActionBar.tsx
index 81c936bc7..e4de76198 100644
--- a/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/ActionBar.tsx
+++ b/frontend/src/pages/secret-manager/SecretDashboardPage/components/ActionBar/ActionBar.tsx
@@ -15,6 +15,7 @@ import {
faFolder,
faFolderPlus,
faKey,
+ faLock,
faMinusSquare,
faPlus,
faTrash
@@ -80,6 +81,7 @@ type Props = {
isVisible?: boolean;
snapshotCount: number;
isSnapshotCountLoading?: boolean;
+ protectedBranchPolicyName?: string;
onSearchChange: (term: string) => void;
onToggleTagFilter: (tagId: string) => void;
onVisibilityToggle: () => void;
@@ -101,7 +103,8 @@ export const ActionBar = ({
onToggleTagFilter,
onVisibilityToggle,
onClickRollbackMode,
- onToggleRowType
+ onToggleRowType,
+ protectedBranchPolicyName
}: Props) => {
const { handlePopUpOpen, handlePopUpToggle, handlePopUpClose, popUp } = usePopUp([
"addFolder",
@@ -112,9 +115,9 @@ export const ActionBar = ({
"misc",
"upgradePlan"
] as const);
+ const isProtectedBranch = Boolean(protectedBranchPolicyName);
const { subscription } = useSubscription();
const { openPopUp } = usePopUpAction();
-
const { mutateAsync: createFolder } = useCreateFolder();
const { mutateAsync: deleteBatchSecretV3 } = useDeleteSecretBatch();
const { mutateAsync: moveSecrets } = useMoveSecrets();
@@ -387,6 +390,15 @@ export const ActionBar = ({
+
+ {isProtectedBranch && (
+
+
+
+
+
+ )}
+
diff --git a/frontend/src/pages/secret-manager/SecretDashboardPage/route.tsx b/frontend/src/pages/secret-manager/SecretDashboardPage/route.tsx
index 9a5821124..ed6ffadb3 100644
--- a/frontend/src/pages/secret-manager/SecretDashboardPage/route.tsx
+++ b/frontend/src/pages/secret-manager/SecretDashboardPage/route.tsx
@@ -1,7 +1,10 @@
-import { createFileRoute, stripSearchParams } from "@tanstack/react-router";
+import { createFileRoute, linkOptions, stripSearchParams } from "@tanstack/react-router";
import { zodValidator } from "@tanstack/zod-adapter";
import { z } from "zod";
+import { SecretDashboardPathBreadcrumb } from "@app/components/navigation/SecretDashboardPathBreadcrumb";
+import { BreadcrumbTypes } from "@app/components/v2";
+
import { SecretDashboardPage } from "./SecretDashboardPage";
const SecretDashboardPageQueryParamsSchema = z.object({
@@ -9,7 +12,6 @@ const SecretDashboardPageQueryParamsSchema = z.object({
search: z.string().catch(""),
tags: z.string().catch("")
});
-
export const Route = createFileRoute(
"/_authenticate/_inject-org-details/secret-manager/$projectId/_secret-manager-layout/secrets/$envSlug"
)({
@@ -17,5 +19,39 @@ export const Route = createFileRoute(
validateSearch: zodValidator(SecretDashboardPageQueryParamsSchema),
search: {
middlewares: [stripSearchParams({ secretPath: "/", search: "", tags: "" })]
+ },
+ beforeLoad: ({ context, params, search }) => {
+ const secretPathSegments = search.secretPath.split("/").filter(Boolean);
+ return {
+ breadcrumbs: [
+ ...context.breadcrumbs,
+ {
+ type: BreadcrumbTypes.Dropdown,
+ label: context.project.environments.find((el) => el.slug === params.envSlug)?.name || "",
+ dropdownTitle: "Environments",
+ links: context.project.environments.map((el) => ({
+ label: el.name,
+ link: linkOptions({
+ to: "/secret-manager/$projectId/secrets/$envSlug",
+ params: {
+ projectId: params.projectId,
+ envSlug: el.slug
+ }
+ })
+ }))
+ },
+ ...secretPathSegments.map((_, index) => ({
+ type: BreadcrumbTypes.Component,
+ component: () => (
+
+ )
+ }))
+ ]
+ };
}
});
diff --git a/frontend/src/pages/secret-manager/SecretRotationPage/SecretRotationPage.tsx b/frontend/src/pages/secret-manager/SecretRotationPage/SecretRotationPage.tsx
index ef66cd069..c27d34cc4 100644
--- a/frontend/src/pages/secret-manager/SecretRotationPage/SecretRotationPage.tsx
+++ b/frontend/src/pages/secret-manager/SecretRotationPage/SecretRotationPage.tsx
@@ -20,6 +20,7 @@ import {
DeleteActionModal,
EmptyState,
IconButton,
+ PageHeader,
Skeleton,
Spinner,
Table,
@@ -137,30 +138,25 @@ const Page = () => {
};
return (
-
-
-
-
Secret Rotation
-
- Stop manually rotating secrets and automate credential rotation.
-
-
-
-
+
+
+
+
+ Documentation
+
+
+
+
Rotated Secrets
@@ -374,7 +370,7 @@ export const SecretRotationPage = () => {
const { t } = useTranslation();
return (
-
+
{t("common.head-title", { title: t("settings.project.title") })}
diff --git a/frontend/src/pages/secret-manager/SecretRotationPage/route.tsx b/frontend/src/pages/secret-manager/SecretRotationPage/route.tsx
index ad0c79c79..9cf72c6a8 100644
--- a/frontend/src/pages/secret-manager/SecretRotationPage/route.tsx
+++ b/frontend/src/pages/secret-manager/SecretRotationPage/route.tsx
@@ -5,5 +5,15 @@ import { SecretRotationPage } from "./SecretRotationPage";
export const Route = createFileRoute(
"/_authenticate/_inject-org-details/secret-manager/$projectId/_secret-manager-layout/secret-rotation"
)({
- component: SecretRotationPage
+ component: SecretRotationPage,
+ beforeLoad: ({ context }) => {
+ return {
+ breadcrumbs: [
+ ...context.breadcrumbs,
+ {
+ label: "Secret Rotation"
+ }
+ ]
+ };
+ }
});
diff --git a/frontend/src/pages/secret-manager/integrations/AzureKeyVaultAuthorizePage/AzureKeyVaultAuthorizePage.tsx b/frontend/src/pages/secret-manager/integrations/AzureKeyVaultAuthorizePage/AzureKeyVaultAuthorizePage.tsx
index 419aa30bf..cbaa54eda 100644
--- a/frontend/src/pages/secret-manager/integrations/AzureKeyVaultAuthorizePage/AzureKeyVaultAuthorizePage.tsx
+++ b/frontend/src/pages/secret-manager/integrations/AzureKeyVaultAuthorizePage/AzureKeyVaultAuthorizePage.tsx
@@ -1,13 +1,12 @@
+import { Helmet } from "react-helmet";
import { Controller, useForm } from "react-hook-form";
-
import { faArrowUpRightFromSquare, faBookOpen } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { zodResolver } from "@hookform/resolvers/zod";
+import { useSearch } from "@tanstack/react-router";
import z from "zod";
import { Button, Card, CardTitle, FormControl, Input } from "@app/components/v2";
-import { Helmet } from "react-helmet";
-import { useSearch } from "@tanstack/react-router";
import { ROUTE_PATHS } from "@app/const/routes";
const schema = z.object({
@@ -18,7 +17,7 @@ type FormData = z.infer;
export function AzureKeyVaultAuthorizePage() {
const { state, clientId } = useSearch({
- from: ROUTE_PATHS.SecretManager.Integratons.AzureKeyVaultAuthorizePage.id,
+ from: ROUTE_PATHS.SecretManager.Integratons.AzureKeyVaultAuthorizePage.id
});
const { control, handleSubmit } = useForm({
@@ -38,7 +37,7 @@ export function AzureKeyVaultAuthorizePage() {
return (
- Authorize Azure Key Vault Integration
+ Authorize Azure Key Vault Integration
@@ -56,12 +55,12 @@ export function AzureKeyVaultAuthorizePage() {
target="_blank"
rel="noopener noreferrer"
>
-
+
Docs
diff --git a/frontend/src/pages/secret-manager/integrations/AzureKeyVaultAuthorizePage/route.tsx b/frontend/src/pages/secret-manager/integrations/AzureKeyVaultAuthorizePage/route.tsx
index cb8c47764..a06dbd091 100644
--- a/frontend/src/pages/secret-manager/integrations/AzureKeyVaultAuthorizePage/route.tsx
+++ b/frontend/src/pages/secret-manager/integrations/AzureKeyVaultAuthorizePage/route.tsx
@@ -1,12 +1,11 @@
import { createFileRoute } from "@tanstack/react-router";
-import z from 'zod'
+import z from "zod";
import { AzureKeyVaultAuthorizePage } from "./AzureKeyVaultAuthorizePage";
-
const PageQueryParamsSchema = z.object({
state: z.string(),
- clientId: z.string().optional(),
+ clientId: z.string().optional()
});
export const Route = createFileRoute(
diff --git a/frontend/src/pages/secret-manager/integrations/CircleCIConfigurePage/CircleCIConfigurePage.tsx b/frontend/src/pages/secret-manager/integrations/CircleCIConfigurePage/CircleCIConfigurePage.tsx
index 36a3b9964..e91a3ca89 100644
--- a/frontend/src/pages/secret-manager/integrations/CircleCIConfigurePage/CircleCIConfigurePage.tsx
+++ b/frontend/src/pages/secret-manager/integrations/CircleCIConfigurePage/CircleCIConfigurePage.tsx
@@ -187,7 +187,7 @@ export const CircleCIConfigurePage = () => {
name="secretPath"
render={({ field, fieldState: { error } }) => (
-
+
)}
/>
diff --git a/frontend/src/pages/secret-manager/layout.tsx b/frontend/src/pages/secret-manager/layout.tsx
index 0ad0c2954..e513d2102 100644
--- a/frontend/src/pages/secret-manager/layout.tsx
+++ b/frontend/src/pages/secret-manager/layout.tsx
@@ -1,3 +1,5 @@
+import { faHome } from "@fortawesome/free-solid-svg-icons";
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { createFileRoute, linkOptions } from "@tanstack/react-router";
import { workspaceKeys } from "@app/hooks/api";
@@ -23,9 +25,11 @@ export const Route = createFileRoute(
});
return {
+ project,
breadcrumbs: [
{
label: "Secret Managers",
+ icon: () =>
,
link: linkOptions({ to: "/organization/secret-manager/overview" })
},
{