Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions frontend/public/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -2039,6 +2039,7 @@
"No risks found": "No risks found",
"No role assignments": "No role assignments",
"No role assignments have been created for this user yet. Create a role assignment to grant specific permissions.": "No role assignments have been created for this user yet. Create a role assignment to grant specific permissions.",
"No roles": "No roles",
"No status": "No status",
"No users": "No users",
"No users in group": "No users in group",
Expand Down Expand Up @@ -2197,6 +2198,7 @@
"Permanently destroy clusters?": "Permanently destroy clusters?",
"Permanently remove node pool {{name}}?": "Permanently remove node pool {{name}}?",
"Permission created": "Permission created",
"Permissions": "Permissions",
"Persistent volume": "Persistent volume",
"Persistent volume storage class for etcd data volumes": "Persistent volume storage class for etcd data volumes",
"Personalize this view": "Personalize this view",
Expand Down
8 changes: 4 additions & 4 deletions frontend/src/NavigationPath.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -209,10 +209,10 @@ export enum NavigationPath {

// RBAC Roles
roles = '/multicloud/user-management/roles',
rolesDetails = '/multicloud/user-management/roles/:id',
rolesPermissions = '/multicloud/user-management/roles/:id/permissions',
rolesRoleAssignments = '/multicloud/user-management/roles/:id/role-assignments',
rolesYaml = '/multicloud/user-management/roles/:id/yaml',
roleDetails = '/multicloud/user-management/roles/:id',
rolePermissions = '/multicloud/user-management/roles/:id/permissions',
roleRoleAssignments = '/multicloud/user-management/roles/:id/role-assignments',
roleYaml = '/multicloud/user-management/roles/:id/yaml',

emptyPath = '',
}
Expand Down
4 changes: 4 additions & 0 deletions frontend/src/resources/rbac.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,3 +152,7 @@ export function listRoles() {
export function listRoleBindings() {
return listResources<RoleBinding>(RoleBindingDefinition)
}

export function listVirtualizationClusterRoles() {
return listResources<ClusterRole>(ClusterRoleDefinition, ['rbac.open-cluster-management.io/filter=vm-clusterroles'])
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import { useLocation, useNavigate, Outlet, Link } from 'react-router-dom-v5-comp
import { Pages, usePageVisitMetricHandler } from '../../../hooks/console-metrics'
import { useTranslation } from '../../../lib/acm-i18next'
import { NavigationPath } from '../../../NavigationPath'
import { RoleAssignments } from '../../UserManagement/Roles/RoleAssignments'
import { RoleAssignments } from '../../UserManagement/Roles/Role/RoleAssignments'
import { OCP_DOC } from '../../../lib/doc-util'
import { PluginContext } from '../../../lib/PluginContext'
import { ConfigMap } from '../../../resources'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import { render, screen } from '@testing-library/react'
import { MemoryRouter } from 'react-router-dom-v5-compat'
import { RecoilRoot } from 'recoil'
import { nockIgnoreRBAC } from '../../../lib/nock-util'
import { nockIgnoreRBAC } from '../../../../lib/nock-util'
import { RoleAssignments } from './RoleAssignments'

function Component({ roleId = 'test-role' }: { roleId?: string }) {
Expand Down
13 changes: 13 additions & 0 deletions frontend/src/routes/UserManagement/Roles/Role/RoleAssignments.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/* Copyright Contributors to the Open Cluster Management project */
import { PageSection } from '@patternfly/react-core'
//import { useTranslation } from '../../../lib/acm-i18next'
import { useCurrentRole } from '../RolesPage'

const RoleAssignments = () => {
//const { t } = useTranslation()
const role = useCurrentRole()

return <PageSection>Role assignments page for Role: {role?.metadata.name}</PageSection>
}

export { RoleAssignments }
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
import { render, screen } from '@testing-library/react'
import { MemoryRouter } from 'react-router-dom-v5-compat'
import { RecoilRoot } from 'recoil'
import { nockIgnoreRBAC } from '../../../lib/nock-util'
import { RoleDetail } from './RoleDetail'
import { nockIgnoreRBAC } from '../../../../lib/nock-util'
import { RoleDetail } from './RoleDetails'

function Component({ roleId = 'test-role' }: { roleId?: string }) {
return (
Expand Down
13 changes: 13 additions & 0 deletions frontend/src/routes/UserManagement/Roles/Role/RoleDetails.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/* Copyright Contributors to the Open Cluster Management project */
import { PageSection } from '@patternfly/react-core'
//import { useTranslation } from '../../../lib/acm-i18next'
import { useCurrentRole } from '../RolesPage'

const RoleDetail = () => {
//const { t } = useTranslation()
const role = useCurrentRole()

return <PageSection>Role detail page for Role: {role?.metadata.name}</PageSection>
}

export { RoleDetail }
92 changes: 92 additions & 0 deletions frontend/src/routes/UserManagement/Roles/Role/RolePage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/* Copyright Contributors to the Open Cluster Management project */
import { useParams, useLocation, Link, Outlet, useNavigate } from 'react-router-dom-v5-compat'
import { useTranslation } from '../../../../lib/acm-i18next'
import { useRolesContext, useCurrentRole } from '../RolesPage'
import {
AcmPage,
AcmPageHeader,
AcmSecondaryNav,
AcmSecondaryNavItem,
AcmLoadingPage,
AcmButton,
} from '../../../../ui-components'
import { NavigationPath } from '../../../../NavigationPath'
import { generatePath } from 'react-router-dom-v5-compat'
import { Page, PageSection } from '@patternfly/react-core'
import { ErrorPage } from '../../../../components/ErrorPage'
import { ResourceError, ResourceErrorCode } from '../../../../resources/utils'

const RolePage = () => {
const { t } = useTranslation()
const { id = undefined } = useParams()
const location = useLocation()
const navigate = useNavigate()
const { loading } = useRolesContext()
const role = useCurrentRole()

const isDetailsActive = location.pathname === generatePath(NavigationPath.roleDetails, { id: id ?? '' })
const isPermissionsActive = location.pathname.includes('/permissions')
const isRoleAssignmentsActive = location.pathname.includes('/role-assignments')
const isYamlActive = location.pathname.includes('/yaml')

switch (true) {
case loading:
return (
<PageSection>
<AcmLoadingPage />
</PageSection>
)
case !role:
return (
<Page>
<ErrorPage
error={new ResourceError(ResourceErrorCode.NotFound)}
actions={
<AcmButton role="link" onClick={() => navigate(NavigationPath.roles)} style={{ marginRight: '10px' }}>
{t('button.backToRoles')}
</AcmButton>
}
/>
</Page>
)
default:
return (
<AcmPage
hasDrawer
header={
<AcmPageHeader
title={role.metadata.name}
description={`ClusterRole`}
breadcrumb={[
{ text: t('User Management'), to: NavigationPath.roles },
{ text: t('Roles'), to: NavigationPath.roles },
{ text: role.metadata.name ?? t('Unknown Role') },
]}
navigation={
<AcmSecondaryNav>
<AcmSecondaryNavItem isActive={isDetailsActive}>
<Link to={generatePath(NavigationPath.roleDetails, { id: id ?? '' })}>{t('Details')}</Link>
</AcmSecondaryNavItem>
<AcmSecondaryNavItem isActive={isPermissionsActive}>
<Link to={generatePath(NavigationPath.rolePermissions, { id: id ?? '' })}>{t('Permissions')}</Link>
</AcmSecondaryNavItem>
<AcmSecondaryNavItem isActive={isRoleAssignmentsActive}>
<Link to={generatePath(NavigationPath.roleRoleAssignments, { id: id ?? '' })}>
{t('Role assignments')}
</Link>
</AcmSecondaryNavItem>
<AcmSecondaryNavItem isActive={isYamlActive}>
<Link to={generatePath(NavigationPath.roleYaml, { id: id ?? '' })}>{t('YAML')}</Link>
</AcmSecondaryNavItem>
</AcmSecondaryNav>
}
/>
}
>
<Outlet />
</AcmPage>
)
}
}

export { RolePage }
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import { render, screen } from '@testing-library/react'
import { MemoryRouter } from 'react-router-dom-v5-compat'
import { RecoilRoot } from 'recoil'
import { nockIgnoreRBAC } from '../../../lib/nock-util'
import { nockIgnoreRBAC } from '../../../../lib/nock-util'
import { RolePermissions } from './RolePermissions'

function Component({ roleId = 'test-role' }: { roleId?: string }) {
Expand Down
13 changes: 13 additions & 0 deletions frontend/src/routes/UserManagement/Roles/Role/RolePermissions.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/* Copyright Contributors to the Open Cluster Management project */
import { PageSection } from '@patternfly/react-core'
//import { useTranslation } from '../../../lib/acm-i18next'
import { useCurrentRole } from '../RolesPage'

const RolePermissions = () => {
//const { t } = useTranslation()
const role = useCurrentRole()

return <PageSection>Role permissions page for Role: {role?.metadata.name}</PageSection>
}

export { RolePermissions }
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import { render, screen } from '@testing-library/react'
import { MemoryRouter } from 'react-router-dom-v5-compat'
import { RecoilRoot } from 'recoil'
import { nockIgnoreRBAC } from '../../../lib/nock-util'
import { nockIgnoreRBAC } from '../../../../lib/nock-util'
import { RoleYaml } from './RoleYaml'

function Component({ roleId = 'test-role' }: { roleId?: string }) {
Expand Down
13 changes: 13 additions & 0 deletions frontend/src/routes/UserManagement/Roles/Role/RoleYaml.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/* Copyright Contributors to the Open Cluster Management project */
import { PageSection } from '@patternfly/react-core'
//import { useTranslation } from '../../../lib/acm-i18next'
import { useCurrentRole } from '../RolesPage'

const RoleYaml = () => {
//const { t } = useTranslation()
const role = useCurrentRole()

return <PageSection>Role YAML page for Role: {role?.metadata.name}</PageSection>
}

export { RoleYaml }
20 changes: 0 additions & 20 deletions frontend/src/routes/UserManagement/Roles/RoleAssignments.tsx

This file was deleted.

20 changes: 0 additions & 20 deletions frontend/src/routes/UserManagement/Roles/RoleDetail.tsx

This file was deleted.

20 changes: 0 additions & 20 deletions frontend/src/routes/UserManagement/Roles/RolePermissions.tsx

This file was deleted.

20 changes: 0 additions & 20 deletions frontend/src/routes/UserManagement/Roles/RoleYaml.tsx

This file was deleted.

18 changes: 0 additions & 18 deletions frontend/src/routes/UserManagement/Roles/Roles.tsx

This file was deleted.

42 changes: 27 additions & 15 deletions frontend/src/routes/UserManagement/Roles/RolesManagement.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,39 @@
/* Copyright Contributors to the Open Cluster Management project */
import { Navigate, Route, Routes } from 'react-router-dom-v5-compat'
import { NavigationPath, createRoutePathFunction } from '../../../NavigationPath'
import { Roles } from './Roles'
import { RoleDetail } from './RoleDetail'
import { RoleYaml } from './RoleYaml'
import { RolePermissions } from './RolePermissions'
import { RoleAssignments } from './RoleAssignments'
import { RolesPage, RolesContextProvider } from './RolesPage'
import { RolePage } from './Role/RolePage'
import { RoleDetail } from './Role/RoleDetails'
import { RoleYaml } from './Role/RoleYaml'
import { RolePermissions } from './Role/RolePermissions'
import { RoleAssignments } from './Role/RoleAssignments'

const rolesChildPath = createRoutePathFunction(NavigationPath.roles)

export default function RolesManagement() {
return (
<Routes>
{/* Role detail routes */}
<Route path={rolesChildPath(NavigationPath.rolesYaml)} element={<RoleYaml />} />
<Route path={rolesChildPath(NavigationPath.rolesPermissions)} element={<RolePermissions />} />
<Route path={rolesChildPath(NavigationPath.rolesRoleAssignments)} element={<RoleAssignments />} />
<Route path={rolesChildPath(NavigationPath.rolesDetails)} element={<RoleDetail />} />
<RolesContextProvider>
<Routes>
{/* Individual role page tabs */}
<Route path={rolesChildPath(NavigationPath.roleDetails)} element={<RolePage />}>
<Route index element={<RoleDetail />} />
</Route>
<Route path={rolesChildPath(NavigationPath.rolePermissions)} element={<RolePage />}>
<Route index element={<RolePermissions />} />
</Route>
<Route path={rolesChildPath(NavigationPath.roleRoleAssignments)} element={<RolePage />}>
<Route index element={<RoleAssignments />} />
</Route>
<Route path={rolesChildPath(NavigationPath.roleYaml)} element={<RolePage />}>
<Route index element={<RoleYaml />} />
</Route>

{/* Main roles page */}
<Route path={rolesChildPath(NavigationPath.roles)} element={<Roles />} />
{/* Main roles page with list of roles */}
<Route path={rolesChildPath(NavigationPath.roles)} element={<RolesPage />} />

<Route path="*" element={<Navigate to={NavigationPath.roles} replace />} />
</Routes>
{/* Default redirect to roles */}
<Route path="*" element={<Navigate to={NavigationPath.roles} replace />} />
</Routes>
</RolesContextProvider>
)
}
Loading