|
|
@@ -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> |
|
|
|
); |
|
|
|
} |