mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-10-05 11:26:33 +00:00
Merge pull request #2186 from LemmyMwaura/persist-tab-state
feat: persist tab state on route change.
This commit is contained in:
@@ -24,6 +24,7 @@ import {
|
|||||||
useRevokeIdentityTokenAuthToken,
|
useRevokeIdentityTokenAuthToken,
|
||||||
useRevokeIdentityUniversalAuthClientSecret} from "@app/hooks/api";
|
useRevokeIdentityUniversalAuthClientSecret} from "@app/hooks/api";
|
||||||
import { usePopUp } from "@app/hooks/usePopUp";
|
import { usePopUp } from "@app/hooks/usePopUp";
|
||||||
|
import { TabSections } from"@app/views/Org/Types";
|
||||||
|
|
||||||
import { IdentityAuthMethodModal } from "../MembersPage/components/OrgIdentityTab/components/IdentitySection/IdentityAuthMethodModal";
|
import { IdentityAuthMethodModal } from "../MembersPage/components/OrgIdentityTab/components/IdentitySection/IdentityAuthMethodModal";
|
||||||
import { IdentityModal } from "../MembersPage/components/OrgIdentityTab/components/IdentitySection/IdentityModal";
|
import { IdentityModal } from "../MembersPage/components/OrgIdentityTab/components/IdentitySection/IdentityModal";
|
||||||
@@ -75,7 +76,7 @@ export const IdentityPage = withPermission(
|
|||||||
});
|
});
|
||||||
|
|
||||||
handlePopUpClose("deleteIdentity");
|
handlePopUpClose("deleteIdentity");
|
||||||
router.push(`/org/${orgId}/members`);
|
router.push(`/org/${orgId}/members?selectedTab=${TabSections.Identities}`);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
const error = err as any;
|
const error = err as any;
|
||||||
@@ -154,7 +155,7 @@ export const IdentityPage = withPermission(
|
|||||||
type="submit"
|
type="submit"
|
||||||
leftIcon={<FontAwesomeIcon icon={faChevronLeft} />}
|
leftIcon={<FontAwesomeIcon icon={faChevronLeft} />}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
router.push(`/org/${orgId}/members`);
|
router.push(`/org/${orgId}/members?selectedTab=${TabSections.Identities}`);
|
||||||
}}
|
}}
|
||||||
className="mb-4"
|
className="mb-4"
|
||||||
>
|
>
|
||||||
|
|||||||
+2
-1
@@ -10,6 +10,7 @@ import { useWorkspace } from "@app/context";
|
|||||||
import { IdentityMembership } from "@app/hooks/api/identities/types";
|
import { IdentityMembership } from "@app/hooks/api/identities/types";
|
||||||
import { ProjectMembershipRole } from "@app/hooks/api/roles/types";
|
import { ProjectMembershipRole } from "@app/hooks/api/roles/types";
|
||||||
import { UsePopUpState } from "@app/hooks/usePopUp";
|
import { UsePopUpState } from "@app/hooks/usePopUp";
|
||||||
|
import { TabSections } from "@app/views/Org/Types";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
membership: IdentityMembership;
|
membership: IdentityMembership;
|
||||||
@@ -51,7 +52,7 @@ export const IdentityProjectRow = ({
|
|||||||
key={`identity-project-membership-${id}`}
|
key={`identity-project-membership-${id}`}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (isAccessible) {
|
if (isAccessible) {
|
||||||
router.push(`/project/${project.id}/members`);
|
router.push(`/project/${project.id}/members?selectedTab=${TabSections.Identities}`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,23 +1,39 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||||
|
import { useRouter } from 'next/router';
|
||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
|
||||||
import { Tab, TabList, TabPanel, Tabs } from "@app/components/v2";
|
import { Tab, TabList, TabPanel, Tabs } from "@app/components/v2";
|
||||||
import { OrgPermissionActions, OrgPermissionSubjects } from "@app/context";
|
import { OrgPermissionActions, OrgPermissionSubjects } from "@app/context";
|
||||||
import { withPermission } from "@app/hoc";
|
import { withPermission } from "@app/hoc";
|
||||||
|
import { isTabSection, TabSections } from "@app/views/Org/Types";;
|
||||||
|
|
||||||
import { OrgIdentityTab, OrgMembersTab, OrgRoleTabSection } from "./components";
|
import { OrgIdentityTab, OrgMembersTab, OrgRoleTabSection } from "./components";
|
||||||
|
|
||||||
enum TabSections {
|
|
||||||
Member = "members",
|
|
||||||
Roles = "roles",
|
|
||||||
Identities = "identities"
|
|
||||||
}
|
|
||||||
|
|
||||||
export const MembersPage = withPermission(
|
export const MembersPage = withPermission(
|
||||||
() => {
|
() => {
|
||||||
|
const router = useRouter();
|
||||||
|
const { query } = router;
|
||||||
|
const selectedTab = query.selectedTab as string;
|
||||||
|
const [activeTab, setActiveTab] = useState<TabSections>(TabSections.Member);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (selectedTab && isTabSection(selectedTab)) {
|
||||||
|
setActiveTab(selectedTab);
|
||||||
|
}
|
||||||
|
}, [isTabSection, selectedTab]);
|
||||||
|
|
||||||
|
const updateSelectedTab = (tab: string) => {
|
||||||
|
router.push({
|
||||||
|
pathname: router.pathname,
|
||||||
|
query: { ...router.query, selectedTab: tab },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="container mx-auto flex flex-col justify-between bg-bunker-800 text-white">
|
<div className="container mx-auto flex flex-col justify-between bg-bunker-800 text-white">
|
||||||
<div className="mx-auto mb-6 w-full max-w-7xl py-6 px-6">
|
<div className="mx-auto mb-6 w-full max-w-7xl py-6 px-6">
|
||||||
<p className="mr-4 mb-4 text-3xl font-semibold text-white">Organization Access Control</p>
|
<p className="mr-4 mb-4 text-3xl font-semibold text-white">Organization Access Control</p>
|
||||||
<Tabs defaultValue={TabSections.Member}>
|
<Tabs value={activeTab} onValueChange={updateSelectedTab}>
|
||||||
<TabList>
|
<TabList>
|
||||||
<Tab value={TabSections.Member}>Users</Tab>
|
<Tab value={TabSections.Member}>Users</Tab>
|
||||||
<Tab value={TabSections.Identities}>
|
<Tab value={TabSections.Identities}>
|
||||||
@@ -25,7 +41,7 @@ export const MembersPage = withPermission(
|
|||||||
<p>Machine Identities</p>
|
<p>Machine Identities</p>
|
||||||
</div>
|
</div>
|
||||||
</Tab>
|
</Tab>
|
||||||
<Tab value={TabSections.Roles}>Organization Roles</Tab>
|
<Tab value={TabSections.Roles}>Organization Roles</Tab>
|
||||||
</TabList>
|
</TabList>
|
||||||
<TabPanel value={TabSections.Member}>
|
<TabPanel value={TabSections.Member}>
|
||||||
<OrgMembersTab />
|
<OrgMembersTab />
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import { OrgPermissionActions, OrgPermissionSubjects, useOrganization } from "@a
|
|||||||
import { withPermission } from "@app/hoc";
|
import { withPermission } from "@app/hoc";
|
||||||
import { useDeleteOrgRole, useGetOrgRole } from "@app/hooks/api";
|
import { useDeleteOrgRole, useGetOrgRole } from "@app/hooks/api";
|
||||||
import { usePopUp } from "@app/hooks/usePopUp";
|
import { usePopUp } from "@app/hooks/usePopUp";
|
||||||
|
import { TabSections } from "@app/views/Org/Types";
|
||||||
|
|
||||||
import { RoleDetailsSection, RoleModal, RolePermissionsSection } from "./components";
|
import { RoleDetailsSection, RoleModal, RolePermissionsSection } from "./components";
|
||||||
|
|
||||||
@@ -51,7 +52,7 @@ export const RolePage = withPermission(
|
|||||||
});
|
});
|
||||||
|
|
||||||
handlePopUpClose("deleteOrgRole");
|
handlePopUpClose("deleteOrgRole");
|
||||||
router.push(`/org/${orgId}/members`);
|
router.push(`/org/${orgId}/members?selectedTab=${TabSections.Roles}`);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
const error = err as any;
|
const error = err as any;
|
||||||
@@ -75,7 +76,7 @@ export const RolePage = withPermission(
|
|||||||
type="submit"
|
type="submit"
|
||||||
leftIcon={<FontAwesomeIcon icon={faChevronLeft} />}
|
leftIcon={<FontAwesomeIcon icon={faChevronLeft} />}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
router.push(`/org/${orgId}/members`);
|
router.push(`/org/${orgId}/members?selectedTab=${TabSections.Roles}`);
|
||||||
}}
|
}}
|
||||||
className="mb-4"
|
className="mb-4"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
export enum TabSections {
|
||||||
|
Member = "members",
|
||||||
|
Roles = "roles",
|
||||||
|
Identities = "identities"
|
||||||
|
}
|
||||||
|
|
||||||
|
export const isTabSection = (value: string): value is TabSections => {
|
||||||
|
return (Object.values(TabSections) as string[]).includes(value);
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
import { TabSections, isTabSection } from "./TabSections";
|
||||||
|
|
||||||
|
export { TabSections, isTabSection };
|
||||||
@@ -29,6 +29,7 @@ import {
|
|||||||
useUpdateOrgMembership
|
useUpdateOrgMembership
|
||||||
} from "@app/hooks/api";
|
} from "@app/hooks/api";
|
||||||
import { usePopUp } from "@app/hooks/usePopUp";
|
import { usePopUp } from "@app/hooks/usePopUp";
|
||||||
|
import { TabSections } from "@app/views/Org/Types";
|
||||||
|
|
||||||
import { UserDetailsSection, UserOrgMembershipModal, UserProjectsSection } from "./components";
|
import { UserDetailsSection, UserOrgMembershipModal, UserProjectsSection } from "./components";
|
||||||
|
|
||||||
@@ -90,7 +91,7 @@ export const UserPage = withPermission(
|
|||||||
});
|
});
|
||||||
|
|
||||||
handlePopUpClose("removeMember");
|
handlePopUpClose("removeMember");
|
||||||
router.push(`/org/${orgId}/members`);
|
router.push(`/org/${orgId}/members?selectedTab=${TabSections.Member}`);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
createNotification({
|
createNotification({
|
||||||
@@ -111,7 +112,7 @@ export const UserPage = withPermission(
|
|||||||
type="submit"
|
type="submit"
|
||||||
leftIcon={<FontAwesomeIcon icon={faChevronLeft} />}
|
leftIcon={<FontAwesomeIcon icon={faChevronLeft} />}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
router.push(`/org/${orgId}/members`);
|
router.push(`/org/${orgId}/members?selectedTab=${TabSections.Member}`);
|
||||||
}}
|
}}
|
||||||
className="mb-4"
|
className="mb-4"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import { useWorkspace } from "@app/context";
|
|||||||
import { ProjectMembershipRole } from "@app/hooks/api/roles/types";
|
import { ProjectMembershipRole } from "@app/hooks/api/roles/types";
|
||||||
import { TWorkspaceUser } from "@app/hooks/api/types";
|
import { TWorkspaceUser } from "@app/hooks/api/types";
|
||||||
import { UsePopUpState } from "@app/hooks/usePopUp";
|
import { UsePopUpState } from "@app/hooks/usePopUp";
|
||||||
|
import { TabSections } from "@app/views/Org/Types";;
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
membership: TWorkspaceUser;
|
membership: TWorkspaceUser;
|
||||||
@@ -47,7 +48,7 @@ export const UserProjectRow = ({
|
|||||||
key={`user-project-membership-${id}`}
|
key={`user-project-membership-${id}`}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (isAccessible) {
|
if (isAccessible) {
|
||||||
router.push(`/project/${project.id}/members`);
|
router.push(`/project/${project.id}/members?selectedTab=${TabSections.Member}`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,25 +1,40 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||||
|
import { useRouter } from 'next/router';
|
||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
|
||||||
import { Tab, TabList, TabPanel, Tabs } from "@app/components/v2";
|
import { Tab, TabList, TabPanel, Tabs } from "@app/components/v2";
|
||||||
import { ProjectPermissionActions, ProjectPermissionSub } from "@app/context";
|
import { ProjectPermissionActions, ProjectPermissionSub } from "@app/context";
|
||||||
import { withProjectPermission } from "@app/hoc";
|
import { withProjectPermission } from "@app/hoc";
|
||||||
|
|
||||||
import { IdentityTab, MembersTab,ProjectRoleListTab, ServiceTokenTab } from "./components";
|
import { IdentityTab, MembersTab,ProjectRoleListTab, ServiceTokenTab } from "./components";
|
||||||
|
import { TabSections, isTabSection } from '../Types';
|
||||||
|
|
||||||
enum TabSections {
|
|
||||||
Member = "members",
|
|
||||||
Roles = "roles",
|
|
||||||
Groups = "groups",
|
|
||||||
Identities = "identities",
|
|
||||||
ServiceTokens = "service-tokens"
|
|
||||||
}
|
|
||||||
|
|
||||||
export const MembersPage = withProjectPermission(
|
export const MembersPage = withProjectPermission(
|
||||||
() => {
|
() => {
|
||||||
|
const router = useRouter();
|
||||||
|
const { query } = router;
|
||||||
|
const selectedTab = query.selectedTab as string;
|
||||||
|
const [activeTab, setActiveTab] = useState<TabSections>(TabSections.Member);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (selectedTab && isTabSection(selectedTab)) {
|
||||||
|
setActiveTab(selectedTab);
|
||||||
|
}
|
||||||
|
}, [isTabSection, selectedTab]);
|
||||||
|
|
||||||
|
const updateSelectedTab = (tab: string) => {
|
||||||
|
router.push({
|
||||||
|
pathname: router.pathname,
|
||||||
|
query: { ...router.query, selectedTab: tab },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="container mx-auto flex flex-col justify-between bg-bunker-800 text-white">
|
<div className="container mx-auto flex flex-col justify-between bg-bunker-800 text-white">
|
||||||
<div className="mx-auto mb-6 w-full max-w-7xl py-6 px-6">
|
<div className="mx-auto mb-6 w-full max-w-7xl py-6 px-6">
|
||||||
<p className="mr-4 mb-4 text-3xl font-semibold text-white">Project Access Control</p>
|
<p className="mr-4 mb-4 text-3xl font-semibold text-white">Project Access Control</p>
|
||||||
<Tabs defaultValue={TabSections.Member}>
|
<Tabs value={activeTab} onValueChange={updateSelectedTab}>
|
||||||
<TabList>
|
<TabList>
|
||||||
<Tab value={TabSections.Member}>Users</Tab>
|
<Tab value={TabSections.Member}>Users</Tab>
|
||||||
<Tab value={TabSections.Identities}>
|
<Tab value={TabSections.Identities}>
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import { useDeleteProjectRole,useGetProjectRoleBySlug } from "@app/hooks/api";
|
|||||||
import { usePopUp } from "@app/hooks/usePopUp";
|
import { usePopUp } from "@app/hooks/usePopUp";
|
||||||
|
|
||||||
import { RoleDetailsSection, RoleModal, RolePermissionsSection } from "./components";
|
import { RoleDetailsSection, RoleModal, RolePermissionsSection } from "./components";
|
||||||
|
import { TabSections } from '../Types';
|
||||||
|
|
||||||
export const RolePage = withProjectPermission(
|
export const RolePage = withProjectPermission(
|
||||||
() => {
|
() => {
|
||||||
@@ -52,7 +53,7 @@ export const RolePage = withProjectPermission(
|
|||||||
type: "success"
|
type: "success"
|
||||||
});
|
});
|
||||||
handlePopUpClose("deleteRole");
|
handlePopUpClose("deleteRole");
|
||||||
router.push(`/project/${projectId}/members`);
|
router.push(`/project/${projectId}/members?selectedTab=${TabSections.Roles}`);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
const error = err as any;
|
const error = err as any;
|
||||||
@@ -75,7 +76,7 @@ export const RolePage = withProjectPermission(
|
|||||||
variant="link"
|
variant="link"
|
||||||
type="submit"
|
type="submit"
|
||||||
leftIcon={<FontAwesomeIcon icon={faChevronLeft} />}
|
leftIcon={<FontAwesomeIcon icon={faChevronLeft} />}
|
||||||
onClick={() => router.push(`/project/${projectId}/members`)}
|
onClick={() => router.push(`/project/${projectId}/members?selectedTab=${TabSections.Roles}`)}
|
||||||
className="mb-4"
|
className="mb-4"
|
||||||
>
|
>
|
||||||
Roles
|
Roles
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
export enum TabSections {
|
||||||
|
Member = "members",
|
||||||
|
Roles = "roles",
|
||||||
|
Groups = "groups",
|
||||||
|
Identities = "identities",
|
||||||
|
ServiceTokens = "service-tokens"
|
||||||
|
}
|
||||||
|
|
||||||
|
export const isTabSection = (value: string): value is TabSections => {
|
||||||
|
return (Object.values(TabSections) as string[]).includes(value);
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
import { TabSections, isTabSection } from "./TabSections";
|
||||||
|
|
||||||
|
export { TabSections, isTabSection };
|
||||||
Reference in New Issue
Block a user