Browse Source

SONAR-21480 - Github Permission Mapping modal adopts new UI

tags/10.4.0.87286
Kevin Silva 4 months ago
parent
commit
1b91488b22

+ 1
- 0
server/sonar-web/src/main/js/app/components/GlobalContainer.tsx View File

@@ -82,6 +82,7 @@ const TEMP_PAGELIST_WITH_NEW_BACKGROUND_WHITE = [
'/admin/marketplace',
'/admin/system',
'/admin/users',
'/admin/settings',
'/admin/settings/encryption',
'/admin/extension/license/support',
'/admin/audit',

+ 1
- 1
server/sonar-web/src/main/js/apps/permission-templates/components/Template.tsx View File

@@ -351,7 +351,7 @@ export default class Template extends React.PureComponent<Props, State> {
<UseQuery query={useGithubProvisioningEnabledQuery}>
{({ data: githubProvisioningStatus }) =>
githubProvisioningStatus ? (
<FlagMessage variant="warning" className="sw-w-fit">
<FlagMessage variant="warning" className="sw-w-fit sw-mb-4">
{translate('permission_templates.github_warning')}
</FlagMessage>
) : null

+ 116
- 114
server/sonar-web/src/main/js/apps/settings/components/authentication/GitHubMappingModal.tsx View File

@@ -17,13 +17,23 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import {
ButtonSecondary,
Checkbox,
ContentCell,
DestructiveIcon,
FlagMessage,
FormField,
InputField,
Modal,
Spinner,
Table,
TableRow,
TableRowInteractive,
TrashIcon,
} from 'design-system';
import * as React from 'react';
import Checkbox from '../../../../components/controls/Checkbox';
import Modal from '../../../../components/controls/Modal';
import { DeleteButton, SubmitButton } from '../../../../components/controls/buttons';
import PermissionHeader from '../../../../components/permissions/PermissionHeader';
import { Alert } from '../../../../components/ui/Alert';
import Spinner from '../../../../components/ui/Spinner';
import { translate, translateWithParameters } from '../../../../helpers/l10n';
import {
PERMISSIONS_ORDER_FOR_PROJECT_TEMPLATE,
@@ -58,8 +68,8 @@ function PermissionRow(props: Readonly<PermissionCellProps>) {
const { mapping, list } = props;

return (
<tr>
<th scope="row" className="nowrap text-middle sw-pl-[10px]">
<TableRowInteractive>
<ContentCell scope="row" className="sw-whitespace-nowrap">
<div className="sw-flex sw-max-w-[150px] sw-items-center">
<b
className={mapping.isBaseRole ? 'sw-capitalize' : 'sw-truncate'}
@@ -68,7 +78,7 @@ function PermissionRow(props: Readonly<PermissionCellProps>) {
{mapping.githubRole}
</b>
{!mapping.isBaseRole && (
<DeleteButton
<DestructiveIcon
className="sw-ml-1"
aria-label={translateWithParameters(
'settings.authentication.github.configuration.roles_mapping.dialog.delete_custom_role',
@@ -77,12 +87,14 @@ function PermissionRow(props: Readonly<PermissionCellProps>) {
onClick={() => {
props.setMapping(list?.filter((r) => r.githubRole !== mapping.githubRole) ?? null);
}}
Icon={TrashIcon}
size="small"
/>
)}
</div>
</th>
</ContentCell>
{Object.entries(mapping.permissions).map(([key, value]) => (
<td key={key} className="permission-column text-center text-middle">
<ContentCell key={key} className="sw-justify-center">
<Checkbox
checked={value}
onCheck={(newValue) =>
@@ -95,9 +107,9 @@ function PermissionRow(props: Readonly<PermissionCellProps>) {
)
}
/>
</td>
</ContentCell>
))}
</tr>
</TableRowInteractive>
);
}

@@ -144,65 +156,46 @@ export default function GitHubMappingModal({ mapping, setMapping, onClose }: Rea
(el) => !el.isBaseRole && !Object.values(el.permissions).some(Boolean),
);

return (
<Modal
contentLabel={header}
onRequestClose={onClose}
shouldCloseOnOverlayClick={false}
shouldCloseOnEsc={false}
size="medium"
>
<div className="modal-head">
<h2>{header}</h2>
</div>
<div className="modal-body modal-container sw-p-0">
<table className="data zebra permissions-table">
<thead>
<tr className="sw-sticky sw-top-0 sw-bg-white sw-z-filterbar">
<th
scope="col"
className="nowrap bordered-bottom sw-pl-[10px] sw-align-middle sw-w-[150px]"
>
<b>
{translate(
'settings.authentication.github.configuration.roles_mapping.dialog.roles_column',
const formBody = (
<div className="sw-p-0">
<Table
noHeaderTopBorder
columnCount={permissions.length + 1}
columnWidths={['auto', ...Array(permissions.length).fill('1%')]}
header={
<TableRow className="sw-sticky sw-top-0 sw-bg-white">
<ContentCell className="sw-whitespace-nowrap">
{translate(
'settings.authentication.github.configuration.roles_mapping.dialog.roles_column',
)}
</ContentCell>
{permissions.map((permission) => (
<PermissionHeader
key={isPermissionDefinitionGroup(permission) ? permission.category : permission.key}
permission={permission}
/>
))}
</TableRow>
}
>
{list
?.filter((r) => r.isBaseRole)
.map((mapping) => (
<PermissionRow key={mapping.id} mapping={mapping} setMapping={setMapping} list={list} />
))}

<TableRow>
<ContentCell colSpan={7}>
<div className="sw-flex sw-items-end">
<form className="sw-flex sw-items-end" onSubmit={validateAndAddCustomRole}>
<FormField
htmlFor="custom-role-input"
label={translate(
'settings.authentication.github.configuration.roles_mapping.dialog.add_custom_role',
)}
</b>
</th>
{permissions.map((permission) => (
<PermissionHeader
key={
isPermissionDefinitionGroup(permission) ? permission.category : permission.key
}
permission={permission}
/>
))}
</tr>
</thead>
<tbody>
{list
?.filter((r) => r.isBaseRole)
.map((mapping) => (
<PermissionRow
key={mapping.id}
mapping={mapping}
setMapping={setMapping}
list={list}
/>
))}
<tr>
<td colSpan={7} className="sw-pt-2 sw-border-t">
<form
className="sw-flex sw-h-9 sw-items-center"
onSubmit={validateAndAddCustomRole}
>
<label htmlFor="custom-role-input">
{translate(
'settings.authentication.github.configuration.roles_mapping.dialog.add_custom_role',
)}
</label>
<input
className="sw-w-[300px] sw-mx-2"
<InputField
className="sw-w-[300px]"
id="custom-role-input"
maxLength={4000}
value={customRoleInput}
@@ -212,52 +205,61 @@ export default function GitHubMappingModal({ mapping, setMapping, onClose }: Rea
}}
type="text"
/>
<SubmitButton disabled={!customRoleInput.trim() || customRoleError}>
{translate('add_verb')}
</SubmitButton>
<Alert variant="error" className="sw-inline-block sw-ml-2 sw-mb-0">
{customRoleError &&
translate(
'settings.authentication.github.configuration.roles_mapping.role_exists',
)}
</Alert>
</form>
</td>
</tr>
{list
?.filter((r) => !r.isBaseRole)
.map((mapping) => (
<PermissionRow
key={mapping.id}
mapping={mapping}
setMapping={setMapping}
list={list}
/>
))}
</tbody>
</table>
<Spinner loading={isLoading} />
<div className="sw-bg-white sw-bottom-0 sw-sticky">
<Alert variant="info" className="sw-m-2">
{translate(
'settings.authentication.github.configuration.roles_mapping.dialog.custom_roles_description',
)}
</Alert>
</div>
</div>
<div className="modal-foot">
<div className="sw-flex sw-items-center sw-justify-end sw-h-8">
<Alert variant="error" className="sw-inline-block sw-mb-0 sw-mr-2">
{haveEmptyCustomRoles &&
translate(
'settings.authentication.github.configuration.roles_mapping.empty_custom_role',
</FormField>
<ButtonSecondary
type="submit"
className="sw-ml-2 sw-mr-4"
disabled={!customRoleInput.trim() || customRoleError}
>
{translate('add_verb')}
</ButtonSecondary>
</form>
{customRoleError && (
<FlagMessage variant="error">
{translate(
'settings.authentication.github.configuration.roles_mapping.role_exists',
)}
</FlagMessage>
)}
</Alert>
<SubmitButton disabled={haveEmptyCustomRoles} onClick={onClose}>
{translate('close')}
</SubmitButton>
</div>
</div>
</div>
</ContentCell>
</TableRow>

{list
?.filter((r) => !r.isBaseRole)
.map((mapping) => (
<PermissionRow key={mapping.id} mapping={mapping} setMapping={setMapping} list={list} />
))}
</Table>
<FlagMessage variant="info">
{translate(
'settings.authentication.github.configuration.roles_mapping.dialog.custom_roles_description',
)}
</FlagMessage>
<Spinner loading={isLoading} />
</div>
);

return (
<Modal onClose={onClose} isLarge>
<Modal.Header title={header} />
<Modal.Body>{formBody}</Modal.Body>
<Modal.Footer
secondaryButton={
<div className="sw-flex sw-items-center sw-justify-end sw-mt-2">
{haveEmptyCustomRoles && (
<FlagMessage variant="error" className="sw-inline-block sw-mb-0 sw-mr-2">
{translate(
'settings.authentication.github.configuration.roles_mapping.empty_custom_role',
)}
</FlagMessage>
)}
<ButtonSecondary disabled={haveEmptyCustomRoles} onClick={onClose}>
{translate('close')}
</ButtonSecondary>
</div>
}
/>
</Modal>
);
}

+ 1
- 1
server/sonar-web/src/main/js/apps/users/Header.tsx View File

@@ -50,7 +50,7 @@ export default function Header(props: Props) {
{manageProvider === undefined ? (
<span>{translate('users.page.description')}</span>
) : (
<FlagMessage className="sw-max-w-3/4" variant="info">
<FlagMessage className="sw-max-w-3/4 sw-mb-4" variant="info">
<span>
<FormattedMessage
defaultMessage={translate('users.page.managed_description')}

Loading…
Cancel
Save