Fix permissions table checkbox disabled state when no permissions are selected

[DSF-86]: https://hasurahq.atlassian.net/browse/DSF-86?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ

PR-URL: https://github.com/hasura/graphql-engine-mono/pull/10029
Co-authored-by: Luca Restagno <59067245+lucarestagno@users.noreply.github.com>
GitOrigin-RevId: 46c5a583a43ee93b51d50145c1b1156811f3eb86
This commit is contained in:
Nicolas Inchauspe 2023-08-29 17:10:46 +02:00 committed by hasura-bot
parent 0694723fd5
commit 530db8b313
6 changed files with 59 additions and 16 deletions

View File

@ -10,6 +10,7 @@ import { useDriverCapabilities } from '../../Data/hooks/useDriverCapabilities';
import { Capabilities } from '@hasura/dc-api-types';
import { getDriversSupportedQueryTypes } from './utils/getDriversSupportedQueryTypes';
import { useIsTableView } from '../../Data/hooks/useIsTableView';
import { isPermissionCheckboxDisabled } from './utils/isPermissionCheckboxDisabled';
const queryType = ['insert', 'select', 'update', 'delete'] as const;
type QueryType = (typeof queryType)[number];
@ -142,6 +143,7 @@ export const PermissionsTable: React.FC<PermissionsTableProps> = ({
isSelectable={bulkSelect.isSelectable}
isSelected={state.context.bulkSelections.includes(roleName)}
machine={machine}
disabled={isPermissionCheckboxDisabled(permissionTypes)}
/>
{permissionTypes.map(({ permissionType, access }) => {

View File

@ -1,12 +1,14 @@
import React from 'react';
import { TableMachine } from '../hooks';
import { PermissionsIcon } from './PermissionsIcons';
import { Checkbox } from '../../../../new-components/Form';
export interface InputCellProps extends React.ComponentProps<'input'> {
roleName: string;
isNewRole: boolean;
isSelectable: boolean;
isSelected: boolean;
disabled?: boolean;
machine: ReturnType<TableMachine>;
}
@ -15,6 +17,7 @@ export const InputCell: React.FC<InputCellProps> = ({
isNewRole,
isSelectable,
isSelected,
disabled,
machine,
}) => {
const [state, send] = machine;
@ -44,24 +47,20 @@ export const InputCell: React.FC<InputCellProps> = ({
}
return (
<td className="w-0 bg-gray-50 p-md font-semibold text-muted">
<td className="w-0 bg-gray-50 p-md">
<div className="flex items-center">
<input
<Checkbox
id={roleName}
type="checkbox"
value={roleName}
checked={isSelected}
className={`rounded shadow-sm border border-gray-300 hover:border-gray-400 focus:ring-yellow-400 m-0 ${
!isSelectable && 'cursor-not-allowed'
}`}
disabled={!isSelectable}
onChange={() => {
onCheckedChange={() => {
send({ type: 'BULK_OPEN', roleName });
}}
/>
<label className="flex items-center ml-sm" htmlFor={roleName}>
{roleName}
</label>
disabled={!isSelectable || !!disabled}
>
<label className="font-semibold text-muted" htmlFor={roleName}>
{roleName}
</label>
</Checkbox>
</div>
</td>
);

View File

@ -8,7 +8,7 @@ import { Metadata, Table } from '../../../hasura-metadata-types';
import { keyToPermission, metadataPermissionKeys } from '../../utils';
import { MetadataSelectors } from '../../../hasura-metadata-api';
interface RolePermission {
export interface RolePermission {
roleName: string;
isNewRole: boolean;
permissionTypes: {

View File

@ -0,0 +1,32 @@
import { RolePermission } from '../hooks';
import { isPermissionCheckboxDisabled } from './isPermissionCheckboxDisabled';
describe('isPermissionCheckboxDisabled', () => {
it('returns false', () => {
const permissionTypes: RolePermission['permissionTypes'] = [
{
permissionType: 'insert',
access: 'fullAccess',
},
{
permissionType: 'select',
access: 'noAccess',
},
];
expect(isPermissionCheckboxDisabled(permissionTypes)).toBeFalsy();
});
it('returns true', () => {
const permissionTypes: RolePermission['permissionTypes'] = [
{
permissionType: 'insert',
access: 'noAccess',
},
{
permissionType: 'select',
access: 'noAccess',
},
];
expect(isPermissionCheckboxDisabled(permissionTypes)).toBeTruthy();
});
});

View File

@ -0,0 +1,5 @@
import { RolePermission } from '../hooks';
export const isPermissionCheckboxDisabled = (
permissionTypes: RolePermission['permissionTypes']
) => !permissionTypes.some(({ access }) => access !== 'noAccess');

View File

@ -6,6 +6,10 @@ import * as RadixCheckbox from '@radix-ui/react-checkbox';
import clsx from 'clsx';
type CheckboxProps = PropsWithChildren<{
/**
* The checkbox id
*/
id?: string;
/**
* The checkbox name
*/
@ -45,6 +49,7 @@ type CheckboxProps = PropsWithChildren<{
export const Checkbox: React.FC<CheckboxProps> = props => {
const {
id,
children,
name,
disabled,
@ -55,7 +60,7 @@ export const Checkbox: React.FC<CheckboxProps> = props => {
onCheckedChange,
options,
} = props;
const componentId = `${name}-${uuid()}`;
const componentId = id ? id : `${name}-${uuid()}`;
const [internalCheckedState, setChecked] = React.useState<
RadixCheckbox.CheckedState | undefined
>(undefined);
@ -100,7 +105,7 @@ export const Checkbox: React.FC<CheckboxProps> = props => {
className={clsx(
(internalCheckedState === true ||
internalCheckedState === 'indeterminate') &&
'absolute inset-[-1px] bg-blue-600 border border-blue-600 rounded',
'absolute top-[-1px] right-[-1px] bottom-[-1px] left-[-1px] bg-blue-600 border border-blue-600 rounded',
invalid && '!border-red-600 !hover:border-red-700',
invalid && !disabled && '!bg-red-600',
disabled && '!cursor-not-allowed !bg-gray-300 !border-gray-300'