diff --git a/frontend/src/views/Org/IdentityPage/IdentityPage.tsx b/frontend/src/views/Org/IdentityPage/IdentityPage.tsx index 1be789baa..3d863f2d3 100644 --- a/frontend/src/views/Org/IdentityPage/IdentityPage.tsx +++ b/frontend/src/views/Org/IdentityPage/IdentityPage.tsx @@ -24,6 +24,7 @@ import { useRevokeIdentityTokenAuthToken, useRevokeIdentityUniversalAuthClientSecret} from "@app/hooks/api"; import { usePopUp } from "@app/hooks/usePopUp"; +import { TabSections } from"@app/views/Org/Types"; import { IdentityAuthMethodModal } from "../MembersPage/components/OrgIdentityTab/components/IdentitySection/IdentityAuthMethodModal"; import { IdentityModal } from "../MembersPage/components/OrgIdentityTab/components/IdentitySection/IdentityModal"; @@ -75,7 +76,7 @@ export const IdentityPage = withPermission( }); handlePopUpClose("deleteIdentity"); - router.push(`/org/${orgId}/members`); + router.push(`/org/${orgId}/members?selectedTab=${TabSections.Identities}`); } catch (err) { console.error(err); const error = err as any; @@ -154,7 +155,7 @@ export const IdentityPage = withPermission( type="submit" leftIcon={} onClick={() => { - router.push(`/org/${orgId}/members`); + router.push(`/org/${orgId}/members?selectedTab=${TabSections.Identities}`); }} className="mb-4" > diff --git a/frontend/src/views/Org/IdentityPage/components/IdentityProjectsSection/IdentityProjectRow.tsx b/frontend/src/views/Org/IdentityPage/components/IdentityProjectsSection/IdentityProjectRow.tsx index e5ec47f6c..70a3c998b 100644 --- a/frontend/src/views/Org/IdentityPage/components/IdentityProjectsSection/IdentityProjectRow.tsx +++ b/frontend/src/views/Org/IdentityPage/components/IdentityProjectsSection/IdentityProjectRow.tsx @@ -10,6 +10,7 @@ import { useWorkspace } from "@app/context"; import { IdentityMembership } from "@app/hooks/api/identities/types"; import { ProjectMembershipRole } from "@app/hooks/api/roles/types"; import { UsePopUpState } from "@app/hooks/usePopUp"; +import { TabSections } from "@app/views/Org/Types"; type Props = { membership: IdentityMembership; @@ -51,7 +52,7 @@ export const IdentityProjectRow = ({ key={`identity-project-membership-${id}`} onClick={() => { if (isAccessible) { - router.push(`/project/${project.id}/members`); + router.push(`/project/${project.id}/members?selectedTab=${TabSections.Identities}`); return; } diff --git a/frontend/src/views/Org/MembersPage/MembersPage.tsx b/frontend/src/views/Org/MembersPage/MembersPage.tsx index 0a9363d09..303411ab0 100644 --- a/frontend/src/views/Org/MembersPage/MembersPage.tsx +++ b/frontend/src/views/Org/MembersPage/MembersPage.tsx @@ -1,23 +1,39 @@ /* 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 { OrgPermissionActions, OrgPermissionSubjects } from "@app/context"; import { withPermission } from "@app/hoc"; +import { isTabSection, TabSections } from "@app/views/Org/Types";; import { OrgIdentityTab, OrgMembersTab, OrgRoleTabSection } from "./components"; -enum TabSections { - Member = "members", - Roles = "roles", - Identities = "identities" -} - export const MembersPage = withPermission( () => { + const router = useRouter(); + const { query } = router; + const selectedTab = query.selectedTab as string; + const [activeTab, setActiveTab] = useState(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 ( Organization Access Control - + Users @@ -25,7 +41,7 @@ export const MembersPage = withPermission( Machine Identities - Organization Roles + Organization Roles diff --git a/frontend/src/views/Org/RolePage/RolePage.tsx b/frontend/src/views/Org/RolePage/RolePage.tsx index c8e78a54e..eb5dae788 100644 --- a/frontend/src/views/Org/RolePage/RolePage.tsx +++ b/frontend/src/views/Org/RolePage/RolePage.tsx @@ -19,6 +19,7 @@ import { OrgPermissionActions, OrgPermissionSubjects, useOrganization } from "@a import { withPermission } from "@app/hoc"; import { useDeleteOrgRole, useGetOrgRole } from "@app/hooks/api"; import { usePopUp } from "@app/hooks/usePopUp"; +import { TabSections } from "@app/views/Org/Types"; import { RoleDetailsSection, RoleModal, RolePermissionsSection } from "./components"; @@ -51,7 +52,7 @@ export const RolePage = withPermission( }); handlePopUpClose("deleteOrgRole"); - router.push(`/org/${orgId}/members`); + router.push(`/org/${orgId}/members?selectedTab=${TabSections.Roles}`); } catch (err) { console.error(err); const error = err as any; @@ -75,7 +76,7 @@ export const RolePage = withPermission( type="submit" leftIcon={} onClick={() => { - router.push(`/org/${orgId}/members`); + router.push(`/org/${orgId}/members?selectedTab=${TabSections.Roles}`); }} className="mb-4" > diff --git a/frontend/src/views/Org/Types/TabSections.ts b/frontend/src/views/Org/Types/TabSections.ts new file mode 100644 index 000000000..945370d45 --- /dev/null +++ b/frontend/src/views/Org/Types/TabSections.ts @@ -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); +} diff --git a/frontend/src/views/Org/Types/index.ts b/frontend/src/views/Org/Types/index.ts new file mode 100644 index 000000000..76f47c6f2 --- /dev/null +++ b/frontend/src/views/Org/Types/index.ts @@ -0,0 +1,3 @@ +import { TabSections, isTabSection } from "./TabSections"; + +export { TabSections, isTabSection }; diff --git a/frontend/src/views/Org/UserPage/UserPage.tsx b/frontend/src/views/Org/UserPage/UserPage.tsx index 2858d97df..f1ac3fae8 100644 --- a/frontend/src/views/Org/UserPage/UserPage.tsx +++ b/frontend/src/views/Org/UserPage/UserPage.tsx @@ -29,6 +29,7 @@ import { useUpdateOrgMembership } from "@app/hooks/api"; import { usePopUp } from "@app/hooks/usePopUp"; +import { TabSections } from "@app/views/Org/Types"; import { UserDetailsSection, UserOrgMembershipModal, UserProjectsSection } from "./components"; @@ -90,7 +91,7 @@ export const UserPage = withPermission( }); handlePopUpClose("removeMember"); - router.push(`/org/${orgId}/members`); + router.push(`/org/${orgId}/members?selectedTab=${TabSections.Member}`); } catch (err) { console.error(err); createNotification({ @@ -111,7 +112,7 @@ export const UserPage = withPermission( type="submit" leftIcon={} onClick={() => { - router.push(`/org/${orgId}/members`); + router.push(`/org/${orgId}/members?selectedTab=${TabSections.Member}`); }} className="mb-4" > diff --git a/frontend/src/views/Org/UserPage/components/UserProjectsSection/UserProjectRow.tsx b/frontend/src/views/Org/UserPage/components/UserProjectsSection/UserProjectRow.tsx index 31c3184af..0e13442a5 100644 --- a/frontend/src/views/Org/UserPage/components/UserProjectsSection/UserProjectRow.tsx +++ b/frontend/src/views/Org/UserPage/components/UserProjectsSection/UserProjectRow.tsx @@ -9,6 +9,7 @@ import { useWorkspace } from "@app/context"; import { ProjectMembershipRole } from "@app/hooks/api/roles/types"; import { TWorkspaceUser } from "@app/hooks/api/types"; import { UsePopUpState } from "@app/hooks/usePopUp"; +import { TabSections } from "@app/views/Org/Types";; type Props = { membership: TWorkspaceUser; @@ -47,7 +48,7 @@ export const UserProjectRow = ({ key={`user-project-membership-${id}`} onClick={() => { if (isAccessible) { - router.push(`/project/${project.id}/members`); + router.push(`/project/${project.id}/members?selectedTab=${TabSections.Member}`); return; } diff --git a/frontend/src/views/Project/MembersPage/MembersPage.tsx b/frontend/src/views/Project/MembersPage/MembersPage.tsx index 188d11ede..5b30b1d4e 100644 --- a/frontend/src/views/Project/MembersPage/MembersPage.tsx +++ b/frontend/src/views/Project/MembersPage/MembersPage.tsx @@ -1,25 +1,40 @@ /* 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 { ProjectPermissionActions, ProjectPermissionSub } from "@app/context"; import { withProjectPermission } from "@app/hoc"; 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( () => { + const router = useRouter(); + const { query } = router; + const selectedTab = query.selectedTab as string; + const [activeTab, setActiveTab] = useState(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 ( Project Access Control - + Users diff --git a/frontend/src/views/Project/RolePage/RolePage.tsx b/frontend/src/views/Project/RolePage/RolePage.tsx index 7e19b49f4..95ea64a90 100644 --- a/frontend/src/views/Project/RolePage/RolePage.tsx +++ b/frontend/src/views/Project/RolePage/RolePage.tsx @@ -21,6 +21,7 @@ import { useDeleteProjectRole,useGetProjectRoleBySlug } from "@app/hooks/api"; import { usePopUp } from "@app/hooks/usePopUp"; import { RoleDetailsSection, RoleModal, RolePermissionsSection } from "./components"; +import { TabSections } from '../Types'; export const RolePage = withProjectPermission( () => { @@ -52,7 +53,7 @@ export const RolePage = withProjectPermission( type: "success" }); handlePopUpClose("deleteRole"); - router.push(`/project/${projectId}/members`); + router.push(`/project/${projectId}/members?selectedTab=${TabSections.Roles}`); } catch (err) { console.error(err); const error = err as any; @@ -75,7 +76,7 @@ export const RolePage = withProjectPermission( variant="link" type="submit" leftIcon={} - onClick={() => router.push(`/project/${projectId}/members`)} + onClick={() => router.push(`/project/${projectId}/members?selectedTab=${TabSections.Roles}`)} className="mb-4" > Roles diff --git a/frontend/src/views/Project/Types/TabSections.ts b/frontend/src/views/Project/Types/TabSections.ts new file mode 100644 index 000000000..ffc93587e --- /dev/null +++ b/frontend/src/views/Project/Types/TabSections.ts @@ -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); +} diff --git a/frontend/src/views/Project/Types/index.ts b/frontend/src/views/Project/Types/index.ts new file mode 100644 index 000000000..76f47c6f2 --- /dev/null +++ b/frontend/src/views/Project/Types/index.ts @@ -0,0 +1,3 @@ +import { TabSections, isTabSection } from "./TabSections"; + +export { TabSections, isTabSection };
Organization Access Control
Machine Identities
Project Access Control