mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-14 18:41:21 +00:00
feat: re-arranged org project pages
This commit is contained in:
@@ -7,7 +7,7 @@ export const Route = createFileRoute("/_authenticate/_inject-org-details/admin/_
|
||||
beforeLoad: ({ context }) => {
|
||||
if (!context.user.superAdmin) {
|
||||
throw redirect({
|
||||
to: "/organization/secret-manager/overview"
|
||||
to: "/organization/projects"
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ import { useServerConfig } from "@app/context";
|
||||
import { fetchOrganizations } from "@app/hooks/api/organization/queries";
|
||||
import { queryClient } from "@app/hooks/api/reactQuery";
|
||||
import { userKeys } from "@app/hooks/api/users";
|
||||
import { ProjectType } from "@app/hooks/api/workspace/types";
|
||||
|
||||
export const navigateUserToOrg = async (navigate: NavigateFn, organizationId?: string) => {
|
||||
const userOrgs = await fetchOrganizations();
|
||||
@@ -13,7 +12,7 @@ export const navigateUserToOrg = async (navigate: NavigateFn, organizationId?: s
|
||||
|
||||
if (organizationId) {
|
||||
localStorage.setItem("orgData.id", organizationId);
|
||||
navigate({ to: "/organization/secret-manager/overview" });
|
||||
navigate({ to: "/organization/projects" });
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -21,7 +20,7 @@ export const navigateUserToOrg = async (navigate: NavigateFn, organizationId?: s
|
||||
// user is part of at least 1 non-auth enforced org
|
||||
const userOrg = nonAuthEnforcedOrgs[0] && nonAuthEnforcedOrgs[0].id;
|
||||
localStorage.setItem("orgData.id", userOrg);
|
||||
navigate({ to: `/organization/${ProjectType.SecretManager}/overview` as const });
|
||||
navigate({ to: "/organization/projects" });
|
||||
} else {
|
||||
// user is not part of any non-auth enforced orgs
|
||||
localStorage.removeItem("orgData.id");
|
||||
|
||||
@@ -28,7 +28,6 @@ import {
|
||||
import { MfaMethod } from "@app/hooks/api/auth/types";
|
||||
import { fetchOrganizations } from "@app/hooks/api/organization/queries";
|
||||
import { isLoggedIn } from "@app/hooks/api/reactQuery";
|
||||
import { ProjectType } from "@app/hooks/api/workspace/types";
|
||||
|
||||
// eslint-disable-next-line new-cap
|
||||
const client = new jsrp.client();
|
||||
@@ -204,7 +203,7 @@ export const SignupInvitePage = () => {
|
||||
localStorage.setItem("orgData.id", orgId);
|
||||
|
||||
navigate({
|
||||
to: `/organization/${ProjectType.SecretManager}/overview` as const
|
||||
to: "/organization/projects"
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
+1
-2
@@ -18,7 +18,6 @@ import { useToggle } from "@app/hooks";
|
||||
import { completeAccountSignup, useSelectOrganization } from "@app/hooks/api/auth/queries";
|
||||
import { MfaMethod } from "@app/hooks/api/auth/types";
|
||||
import { fetchOrganizations } from "@app/hooks/api/organization/queries";
|
||||
import { ProjectType } from "@app/hooks/api/workspace/types";
|
||||
|
||||
// eslint-disable-next-line new-cap
|
||||
const client = new jsrp.client();
|
||||
@@ -207,7 +206,7 @@ export const UserInfoSSOStep = ({
|
||||
|
||||
localStorage.setItem("orgData.id", orgId);
|
||||
navigate({
|
||||
to: `/organization/${ProjectType.SecretManager}/overview` as const
|
||||
to: "/organization/projects"
|
||||
});
|
||||
} catch (error) {
|
||||
setIsLoading(false);
|
||||
|
||||
+1
-1
@@ -64,7 +64,7 @@ export const DeleteProjectSection = () => {
|
||||
});
|
||||
|
||||
navigate({
|
||||
to: `/organization/${ProjectType.SecretManager}/overview` as const
|
||||
to: "/organization/projects"
|
||||
});
|
||||
handlePopUpClose("deleteWorkspace");
|
||||
} catch (err) {
|
||||
|
||||
@@ -112,7 +112,7 @@ export const Route = createFileRoute("/_restrict-login-signup")({
|
||||
throw redirect({ to: "/login/select-organization" });
|
||||
}
|
||||
throw redirect({
|
||||
to: `/organization/${ProjectType.SecretManager}/overview` as const
|
||||
to: "/organization/projects"
|
||||
});
|
||||
},
|
||||
component: AuthConsentWrapper
|
||||
|
||||
@@ -5,6 +5,7 @@ import { OrgPermissionCan } from "@app/components/permissions";
|
||||
import { OrgPermissionBillingActions, OrgPermissionSubjects } from "@app/context";
|
||||
|
||||
import { BillingTabGroup } from "./components";
|
||||
import { PageHeader } from "@app/components/v2";
|
||||
|
||||
export const BillingPage = () => {
|
||||
const { t } = useTranslation();
|
||||
@@ -18,10 +19,11 @@ export const BillingPage = () => {
|
||||
</Helmet>
|
||||
<div className="flex h-full w-full justify-center bg-bunker-800 text-white">
|
||||
<div className="w-full max-w-7xl px-6">
|
||||
<div className="my-6">
|
||||
<p className="text-3xl font-semibold text-gray-200">{t("billing.title")}</p>
|
||||
<div />
|
||||
</div>
|
||||
<PageHeader
|
||||
title={t("billing.title")}
|
||||
description="View your billing plan, next billing cycle."
|
||||
/>
|
||||
|
||||
<OrgPermissionCan
|
||||
passThrough={false}
|
||||
I={OrgPermissionBillingActions.Read}
|
||||
|
||||
@@ -5,5 +5,14 @@ import { BillingPage } from "./BillingPage";
|
||||
export const Route = createFileRoute(
|
||||
"/_authenticate/_inject-org-details/_org-layout/organization/billing"
|
||||
)({
|
||||
component: BillingPage
|
||||
component: BillingPage,
|
||||
beforeLoad: () => {
|
||||
return {
|
||||
breadcrumbs: [
|
||||
{
|
||||
label: "Billing"
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
import { ProjectType } from "@app/hooks/api/workspace/types";
|
||||
|
||||
import { ProductOverviewPage } from "../SecretManagerOverviewPage/SecretManagerOverviewPage";
|
||||
|
||||
export const CertManagerOverviewPage = () => (
|
||||
<ProductOverviewPage type={ProjectType.CertificateManager} />
|
||||
);
|
||||
@@ -1,17 +0,0 @@
|
||||
import { createFileRoute, linkOptions } from "@tanstack/react-router";
|
||||
|
||||
import { CertManagerOverviewPage } from "./CertManagerOverviewPage";
|
||||
|
||||
export const Route = createFileRoute(
|
||||
"/_authenticate/_inject-org-details/_org-layout/organization/cert-manager/overview"
|
||||
)({
|
||||
component: CertManagerOverviewPage,
|
||||
context: () => ({
|
||||
breadcrumbs: [
|
||||
{
|
||||
label: "Cert Management",
|
||||
link: linkOptions({ to: "/organization/cert-manager/overview" })
|
||||
}
|
||||
]
|
||||
})
|
||||
});
|
||||
+1
-1
@@ -44,7 +44,7 @@ type Props = {
|
||||
|
||||
const Content = ({ identityId, handlePopUpToggle }: Omit<Props, "popUp">) => {
|
||||
const { currentOrg } = useOrganization();
|
||||
const { data: workspaces = [] } = useGetUserWorkspaces({ type: "all" });
|
||||
const { data: workspaces = [] } = useGetUserWorkspaces();
|
||||
const { mutateAsync: addIdentityToWorkspace } = useAddIdentityToWorkspace();
|
||||
|
||||
const {
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
import { ProjectType } from "@app/hooks/api/workspace/types";
|
||||
|
||||
import { ProductOverviewPage } from "../SecretManagerOverviewPage/SecretManagerOverviewPage";
|
||||
|
||||
export const KmsOverviewPage = () => <ProductOverviewPage type={ProjectType.KMS} />;
|
||||
@@ -1,17 +0,0 @@
|
||||
import { createFileRoute, linkOptions } from "@tanstack/react-router";
|
||||
|
||||
import { KmsOverviewPage } from "./KmsOverviewPage";
|
||||
|
||||
export const Route = createFileRoute(
|
||||
"/_authenticate/_inject-org-details/_org-layout/organization/kms/overview"
|
||||
)({
|
||||
component: KmsOverviewPage,
|
||||
context: () => ({
|
||||
breadcrumbs: [
|
||||
{
|
||||
label: "KMS",
|
||||
link: linkOptions({ to: "/organization/kms/overview" })
|
||||
}
|
||||
]
|
||||
})
|
||||
});
|
||||
+13
-26
@@ -10,31 +10,25 @@ import { NewProjectModal } from "@app/components/projects";
|
||||
import { PageHeader } from "@app/components/v2";
|
||||
import { useSubscription } from "@app/context";
|
||||
import { useFetchServerStatus } from "@app/hooks/api/serverDetails";
|
||||
import { ProjectType } from "@app/hooks/api/workspace/types";
|
||||
import { usePopUp } from "@app/hooks/usePopUp";
|
||||
|
||||
import { AllProjectView } from "./components/AllProjectView";
|
||||
import { MyProjectView } from "./components/MyProjectView";
|
||||
import { ProjectListToggle, ProjectListView } from "./components/ProjectListToggle";
|
||||
|
||||
const formatDescription = (type: ProjectType) => {
|
||||
if (type === ProjectType.SecretManager)
|
||||
return "Securely store, manage, and rotate various application secrets, such as database credentials, API keys, etc.";
|
||||
if (type === ProjectType.CertificateManager)
|
||||
return "Manage your PKI infrastructure and issue digital certificates for services, applications, and devices.";
|
||||
if (type === ProjectType.KMS)
|
||||
return "Centralize the management of keys for cryptographic operations, such as encryption and decryption.";
|
||||
if (type === ProjectType.SecretScanning)
|
||||
return "Connect and monitor data sources to prevent secret leaks.";
|
||||
return "Infisical SSH lets you issue SSH credentials to users for short-lived, secure SSH access to infrastructure.";
|
||||
};
|
||||
// const formatDescription = (type: ProjectType) => {
|
||||
// if (type === ProjectType.SecretManager)
|
||||
// return "Securely store, manage, and rotate various application secrets, such as database credentials, API keys, etc.";
|
||||
// if (type === ProjectType.CertificateManager)
|
||||
// return "Manage your PKI infrastructure and issue digital certificates for services, applications, and devices.";
|
||||
// if (type === ProjectType.KMS)
|
||||
// return "Centralize the management of keys for cryptographic operations, such as encryption and decryption.";
|
||||
// if (type === ProjectType.SecretScanning)
|
||||
// return "Connect and monitor data sources to prevent secret leaks.";
|
||||
// return "Infisical SSH lets you issue SSH credentials to users for short-lived, secure SSH access to infrastructure.";
|
||||
// };
|
||||
|
||||
type Props = {
|
||||
type: ProjectType;
|
||||
};
|
||||
|
||||
// #TODO: Update all the workspaceIds
|
||||
export const ProductOverviewPage = ({ type }: Props) => {
|
||||
export const ProjectsPage = () => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
const [projectListView, setProjectListView] = useState(ProjectListView.MyProjects);
|
||||
@@ -87,19 +81,17 @@ export const ProductOverviewPage = ({ type }: Props) => {
|
||||
<ProjectListToggle value={projectListView} onChange={setProjectListView} />
|
||||
</div>
|
||||
}
|
||||
description={formatDescription(type)}
|
||||
description="Your team's complete security toolkit - organized and ready when you need them."
|
||||
/>
|
||||
</div>
|
||||
{projectListView === ProjectListView.MyProjects ? (
|
||||
<MyProjectView
|
||||
type={type}
|
||||
onAddNewProject={() => handlePopUpOpen("addNewWs")}
|
||||
onUpgradePlan={() => handlePopUpOpen("upgradePlan")}
|
||||
isAddingProjectsAllowed={isAddingProjectsAllowed}
|
||||
/>
|
||||
) : (
|
||||
<AllProjectView
|
||||
type={type}
|
||||
onAddNewProject={() => handlePopUpOpen("addNewWs")}
|
||||
onUpgradePlan={() => handlePopUpOpen("upgradePlan")}
|
||||
isAddingProjectsAllowed={isAddingProjectsAllowed}
|
||||
@@ -108,7 +100,6 @@ export const ProductOverviewPage = ({ type }: Props) => {
|
||||
<NewProjectModal
|
||||
isOpen={popUp.addNewWs.isOpen}
|
||||
onOpenChange={(isOpen) => handlePopUpToggle("addNewWs", isOpen)}
|
||||
projectType={type}
|
||||
/>
|
||||
<UpgradePlanModal
|
||||
isOpen={popUp.upgradePlan.isOpen}
|
||||
@@ -118,7 +109,3 @@ export const ProductOverviewPage = ({ type }: Props) => {
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const SecretManagerOverviewPage = () => (
|
||||
<ProductOverviewPage type={ProjectType.SecretManager} />
|
||||
);
|
||||
+1
-4
@@ -35,10 +35,9 @@ import {
|
||||
} from "@app/helpers/userTablePreferences";
|
||||
import { useDebounce, usePagination, usePopUp, useResetPageHelper } from "@app/hooks";
|
||||
import { useRequestProjectAccess, useSearchProjects } from "@app/hooks/api";
|
||||
import { ProjectType, Workspace } from "@app/hooks/api/workspace/types";
|
||||
import { Workspace } from "@app/hooks/api/workspace/types";
|
||||
|
||||
type Props = {
|
||||
type: ProjectType;
|
||||
onAddNewProject: () => void;
|
||||
onUpgradePlan: () => void;
|
||||
isAddingProjectsAllowed: boolean;
|
||||
@@ -92,7 +91,6 @@ const RequestAccessModal = ({ projectId, onPopUpToggle }: RequestAccessModalProp
|
||||
};
|
||||
|
||||
export const AllProjectView = ({
|
||||
type,
|
||||
onAddNewProject,
|
||||
onUpgradePlan,
|
||||
isAddingProjectsAllowed
|
||||
@@ -125,7 +123,6 @@ export const AllProjectView = ({
|
||||
const { data: searchedProjects, isPending: isProjectLoading } = useSearchProjects({
|
||||
limit,
|
||||
offset,
|
||||
type,
|
||||
name: debouncedSearch || undefined,
|
||||
orderDirection
|
||||
});
|
||||
+2
-16
@@ -29,10 +29,9 @@ import { useGetUserWorkspaces } from "@app/hooks/api";
|
||||
import { OrderByDirection } from "@app/hooks/api/generic/types";
|
||||
import { useUpdateUserProjectFavorites } from "@app/hooks/api/users/mutation";
|
||||
import { useGetUserProjectFavorites } from "@app/hooks/api/users/queries";
|
||||
import { ProjectType, Workspace } from "@app/hooks/api/workspace/types";
|
||||
import { Workspace } from "@app/hooks/api/workspace/types";
|
||||
|
||||
type Props = {
|
||||
type: ProjectType;
|
||||
onAddNewProject: () => void;
|
||||
onUpgradePlan: () => void;
|
||||
isAddingProjectsAllowed: boolean;
|
||||
@@ -48,7 +47,6 @@ enum ProjectsViewMode {
|
||||
}
|
||||
|
||||
export const MyProjectView = ({
|
||||
type,
|
||||
onAddNewProject,
|
||||
onUpgradePlan,
|
||||
isAddingProjectsAllowed
|
||||
@@ -56,9 +54,7 @@ export const MyProjectView = ({
|
||||
const navigate = useNavigate();
|
||||
const { currentOrg } = useOrganization();
|
||||
|
||||
const { data: workspaces = [], isPending: isWorkspaceLoading } = useGetUserWorkspaces({
|
||||
type
|
||||
});
|
||||
const { data: workspaces = [], isPending: isWorkspaceLoading } = useGetUserWorkspaces();
|
||||
const {
|
||||
setPage,
|
||||
perPage,
|
||||
@@ -202,11 +198,6 @@ export const MyProjectView = ({
|
||||
</div>
|
||||
|
||||
<div className="flex w-full flex-row items-end justify-between place-self-end">
|
||||
{type === ProjectType.SecretManager && (
|
||||
<div className="mt-0 text-xs text-mineshaft-400">
|
||||
{workspace.environments?.length || 0} environments
|
||||
</div>
|
||||
)}
|
||||
<button type="button">
|
||||
<div className="group ml-auto w-max cursor-pointer rounded-full border border-mineshaft-600 bg-mineshaft-900 px-4 py-2 text-sm text-mineshaft-300 transition-all hover:border-primary-500/80 hover:bg-primary-800/20 hover:text-mineshaft-200">
|
||||
Explore{" "}
|
||||
@@ -239,11 +230,6 @@ export const MyProjectView = ({
|
||||
<div className="truncate text-sm text-mineshaft-100">{workspace.name}</div>
|
||||
</div>
|
||||
<div className="flex items-center justify-end sm:col-span-3 lg:col-span-2">
|
||||
{type === ProjectType.SecretManager && (
|
||||
<div className="text-center text-sm text-mineshaft-300">
|
||||
{workspace.environments?.length || 0} environments
|
||||
</div>
|
||||
)}
|
||||
{isFavorite ? (
|
||||
<FontAwesomeIcon
|
||||
icon={faSolidStar}
|
||||
@@ -0,0 +1,16 @@
|
||||
import { createFileRoute } from "@tanstack/react-router";
|
||||
|
||||
import { ProjectsPage } from "./ProjectsPage";
|
||||
|
||||
export const Route = createFileRoute(
|
||||
"/_authenticate/_inject-org-details/_org-layout/organization/projects"
|
||||
)({
|
||||
component: ProjectsPage,
|
||||
context: () => ({
|
||||
breadcrumbs: [
|
||||
{
|
||||
label: "Projects"
|
||||
}
|
||||
]
|
||||
})
|
||||
});
|
||||
@@ -1,16 +0,0 @@
|
||||
import { createFileRoute } from "@tanstack/react-router";
|
||||
|
||||
import { SecretManagerOverviewPage } from "./SecretManagerOverviewPage";
|
||||
|
||||
export const Route = createFileRoute(
|
||||
"/_authenticate/_inject-org-details/_org-layout/organization/secret-manager/overview"
|
||||
)({
|
||||
component: SecretManagerOverviewPage,
|
||||
context: () => ({
|
||||
breadcrumbs: [
|
||||
{
|
||||
label: "Secret Management"
|
||||
}
|
||||
]
|
||||
})
|
||||
});
|
||||
-7
@@ -1,7 +0,0 @@
|
||||
import { ProjectType } from "@app/hooks/api/workspace/types";
|
||||
|
||||
import { ProductOverviewPage } from "../SecretManagerOverviewPage/SecretManagerOverviewPage";
|
||||
|
||||
export const SecretScanningOverviewPage = () => (
|
||||
<ProductOverviewPage type={ProjectType.SecretScanning} />
|
||||
);
|
||||
@@ -1,17 +0,0 @@
|
||||
import { createFileRoute, linkOptions } from "@tanstack/react-router";
|
||||
|
||||
import { SecretScanningOverviewPage } from "./SecretScanningOverviewPage";
|
||||
|
||||
export const Route = createFileRoute(
|
||||
"/_authenticate/_inject-org-details/_org-layout/organization/secret-scanning/overview"
|
||||
)({
|
||||
component: SecretScanningOverviewPage,
|
||||
context: () => ({
|
||||
breadcrumbs: [
|
||||
{
|
||||
label: "Secret Scanning",
|
||||
link: linkOptions({ to: "/organization/secret-scanning/overview" })
|
||||
}
|
||||
]
|
||||
})
|
||||
});
|
||||
@@ -1,5 +0,0 @@
|
||||
import { ProjectType } from "@app/hooks/api/workspace/types";
|
||||
|
||||
import { ProductOverviewPage } from "../SecretManagerOverviewPage/SecretManagerOverviewPage";
|
||||
|
||||
export const SshOverviewPage = () => <ProductOverviewPage type={ProjectType.SSH} />;
|
||||
@@ -1,17 +0,0 @@
|
||||
import { createFileRoute, linkOptions } from "@tanstack/react-router";
|
||||
|
||||
import { SshOverviewPage } from "./SshOverviewPage";
|
||||
|
||||
export const Route = createFileRoute(
|
||||
"/_authenticate/_inject-org-details/_org-layout/organization/ssh/overview"
|
||||
)({
|
||||
component: SshOverviewPage,
|
||||
context: () => ({
|
||||
breadcrumbs: [
|
||||
{
|
||||
label: "SSH",
|
||||
link: linkOptions({ to: "/organization/ssh/overview" })
|
||||
}
|
||||
]
|
||||
})
|
||||
});
|
||||
+2
-2
@@ -12,7 +12,7 @@ import { useProjectPermission, useWorkspace } from "@app/context";
|
||||
import { usePopUp } from "@app/hooks";
|
||||
import { useGetWorkspaceById, useMigrateProjectToV3, workspaceKeys } from "@app/hooks/api";
|
||||
import { ProjectMembershipRole } from "@app/hooks/api/roles/types";
|
||||
import { ProjectType, ProjectVersion } from "@app/hooks/api/workspace/types";
|
||||
import { ProjectVersion } from "@app/hooks/api/workspace/types";
|
||||
|
||||
enum ProjectUpgradeStatus {
|
||||
InProgress = "IN_PROGRESS",
|
||||
@@ -54,7 +54,7 @@ export const SecretV2MigrationSection = () => {
|
||||
createNotification({ type: "success", text: "Project upgrade completed successfully" });
|
||||
migrateProjectToV3.reset();
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: workspaceKeys.getAllUserWorkspace(ProjectType.SecretManager)
|
||||
queryKey: workspaceKeys.getAllUserWorkspace()
|
||||
});
|
||||
}
|
||||
}, [isProjectUpgraded, Boolean(migrateProjectToV3.data)]);
|
||||
|
||||
Reference in New Issue
Block a user