From 675b2c7afa5f1fb06bb7fe2cafe54eb9643518ef Mon Sep 17 00:00:00 2001 From: OpenShift Cherrypick Robot Date: Thu, 6 Nov 2025 16:16:22 +0100 Subject: [PATCH] [redhat-3.16] fix(ui): add user status labels to organizations table (PROJQUAY-9656) (#4475) fix(ui): add user status labels to organizations table (PROJQUAY-9656) Signed-off-by: Brady Pratt Co-authored-by: Brady Pratt Co-authored-by: Claude --- web/cypress/e2e/org-list.cy.ts | 26 ++++++++ .../OrganizationsListTableData.tsx | 59 +++++++++++++------ 2 files changed, 68 insertions(+), 17 deletions(-) diff --git a/web/cypress/e2e/org-list.cy.ts b/web/cypress/e2e/org-list.cy.ts index 71f8f36df..838259b1e 100644 --- a/web/cypress/e2e/org-list.cy.ts +++ b/web/cypress/e2e/org-list.cy.ts @@ -242,4 +242,30 @@ describe('Org List Page', () => { // The quota should be displayed as "10.0 GiB / 50.0 GiB" format cy.get('td[data-label="Size"]').first().should('not.contain.text', '—'); }); + + it('Superuser displays user status labels', () => { + // Mock config with superuser features enabled + cy.fixture('config.json').then((config) => { + config.features.SUPER_USERS = true; + config.features.SUPERUSERS_FULL_ACCESS = true; + cy.intercept('GET', '/config', config).as('getConfig'); + }); + + // Mock superuser + cy.fixture('superuser.json').then((user) => { + cy.intercept('GET', '/api/v1/user/', user).as('getSuperUser'); + }); + + cy.visit('/organization'); + cy.wait('@getConfig'); + cy.wait('@getSuperUser'); + + cy.get('#orgslist-search-input').type('user1'); + + cy.contains('a', 'user1') + .parents('tr') + .within(() => { + cy.contains('Superuser').should('exist'); + }); + }); }); diff --git a/web/src/routes/OrganizationsList/OrganizationsListTableData.tsx b/web/src/routes/OrganizationsList/OrganizationsListTableData.tsx index db6eb548e..aa167fa3b 100644 --- a/web/src/routes/OrganizationsList/OrganizationsListTableData.tsx +++ b/web/src/routes/OrganizationsList/OrganizationsListTableData.tsx @@ -1,5 +1,5 @@ import {Td} from '@patternfly/react-table'; -import {Skeleton, Flex, FlexItem} from '@patternfly/react-core'; +import {Skeleton, Flex, FlexItem, Label} from '@patternfly/react-core'; import './css/Organizations.scss'; import {Link} from 'react-router-dom'; import {fetchOrg} from 'src/resources/OrganizationResource'; @@ -126,24 +126,49 @@ export default function OrgTableData(props: OrgTableDataProps) { return ( <> - - {/* Show avatar for organizations OR current user */} - {((props.isUser && - currentUser?.username === props.name && - currentUser?.avatar) || - (!props.isUser && organization?.avatar)) && ( - - + + + {/* Show avatar for organizations OR current user */} + {((props.isUser && + currentUser?.username === props.name && + currentUser?.avatar) || + (!props.isUser && organization?.avatar)) && ( + + + + )} + + {props.name} + + {/* Show status labels for users (right-aligned, superuser only) */} + {isSuperUser && props.isUser && ( + + {currentUser?.username === props.name && ( + + + + )} + {props.userSuperuser && ( + + + + )} + {props.userEnabled === false && ( + + + + )} + )} - - {props.name} - {isSuperUser && config?.features?.MAILING && (