chore: rework administration styles & table selection behavior

CB-232
This commit is contained in:
Wroud
2020-08-13 19:23:17 +03:00
parent 46bb9bd613
commit 8207d53839
7 changed files with 165 additions and 194 deletions
@@ -24,13 +24,20 @@ type ExpandProps = {
type Props = React.PropsWithChildren<{
item: any;
expandElement?: React.FunctionComponent<ExpandProps>;
selectDisabled?: boolean;
className?: string;
onClick?: () => void;
onDoubleClick?: () => void;
}>
export const TableItem = observer(function TableItem({
item, expandElement, children, className, onClick, onDoubleClick,
item,
expandElement,
selectDisabled = false,
children,
className,
onClick,
onDoubleClick,
}: Props) {
const context = useContext(TableContext);
if (!context) {
@@ -39,24 +46,27 @@ export const TableItem = observer(function TableItem({
const itemContext = useMemo<ITableItemContext>(() => ({
item,
selectDisabled,
isSelected: () => !!context.selectedItems.get(item),
isExpanded: () => !!context.expandedItems.get(item),
}), [item]);
}), [item, selectDisabled]);
const handleClick = useCallback(
(e: React.MouseEvent<HTMLTableRowElement>) => {
const isSelected = context.selectedItems.get(item);
if (!e.ctrlKey) {
context.clearSelection();
}
if (!selectDisabled) {
const isSelected = context.selectedItems.get(item);
if (!e.ctrlKey) {
context.clearSelection();
}
context.setItemSelect(item, !isSelected);
context.setItemSelect(item, !isSelected);
}
if (onClick) {
onClick();
}
},
[context, item, onClick]
[context, item, selectDisabled, onClick]
);
const handleDoubleClick = useCallback((e: React.MouseEvent<HTMLTableRowElement>) => {
if (onDoubleClick) {
@@ -10,6 +10,7 @@ import { createContext } from 'react';
export interface ITableItemContext {
item: any;
selectDisabled: boolean;
isSelected(): boolean;
isExpanded(): boolean;
}
@@ -32,6 +32,6 @@ export const TableItemSelect = observer(function TableItemSelect({ disabled, cla
}, [tableContext, context]);
return styled(useStyles())(
<input type='checkbox' checked={context.isSelected()} onClick={handleClick} className={className} disabled={disabled}/>
<input type='checkbox' checked={context.isSelected()} onClick={handleClick} className={className} disabled={context.selectDisabled || disabled}/>
);
});
@@ -32,16 +32,12 @@ const styles = composes(
composes: theme-ripple theme-background-secondary theme-text-on-secondary from global;
}
TabList {
composes: theme-border-color-background from global;
}
ErrorMessage {
composes: theme-background-secondary from global;
}
SubmittingForm {
composes: theme-background-secondary from global;
content-box {
composes: theme-background-secondary theme-border-color-background from global;
}
GrantedSubjects {
@@ -49,18 +45,14 @@ const styles = composes(
}
`,
css`
custom-connection {
display: flex;
flex-direction: column;
box-sizing: border-box;
content-box {
margin: 0 24px;
margin-bottom: 16px;
border: solid 1px;
border-top: none;
}
CommonDialogWrapper {
max-height: 500px;
min-height: 500px;
}
SubmittingForm, BaseTabPanel {
SubmittingForm {
flex: 1;
display: flex;
flex-direction: column;
@@ -73,7 +65,6 @@ const styles = composes(
width: 100%;
padding-left: 24px;
outline: none;
border-bottom: solid 1px;
}
Tab {
@@ -96,21 +87,11 @@ const styles = composes(
flex: 1;
}
connection-form[|new] {
border-left: solid 3px;
}
SubmittingForm, Loader {
min-height: 320px;
max-height: 500px;
}
IconButton {
height: 32px;
width: 32px;
margin-right: 16px;
}
Button:not(:first-child) {
margin-right: 24px;
}
@@ -169,42 +150,44 @@ export const ConnectionEdit = observer(function ConnectionEdit({
{translate(controller.isNew ? 'ui_processing_create' : 'ui_processing_save')}
</Button>
</TabList>
{controller.isLoading
? <Loader />
: (
<SubmittingForm onSubmit={controller.onSaveConnection}>
<TabPanel tabId='options'>
<ConnectionForm controller={controller} />
</TabPanel>
{controller.driver && (
<TabPanel tabId='driver_properties'>
<DriverProperties
driver={controller.driver}
state={controller.config.properties!}
loadProperties={loadProperties}
<content-box as="div">
{controller.isLoading
? <Loader />
: (
<SubmittingForm onSubmit={controller.onSaveConnection}>
<TabPanel tabId='options'>
<ConnectionForm controller={controller} />
</TabPanel>
{controller.driver && (
<TabPanel tabId='driver_properties'>
<DriverProperties
driver={controller.driver}
state={controller.config.properties!}
loadProperties={loadProperties}
/>
</TabPanel>
)}
<TabPanel tabId='access'>
<GrantedSubjects
grantedSubjects={controller.grantedSubjects}
users={controller.users}
roles={controller.roles}
selectedSubjects={controller.selectedSubjects}
disabled={controller.isLoading || controller.isSaving}
onChange={controller.handleAccessChange}
/>
</TabPanel>
)}
<TabPanel tabId='access'>
<GrantedSubjects
grantedSubjects={controller.grantedSubjects}
users={controller.users}
roles={controller.roles}
selectedSubjects={controller.selectedSubjects}
disabled={controller.isLoading}
onChange={controller.handleAccessChange}
/>
</TabPanel>
</SubmittingForm>
)
}
{controller.error.responseMessage && (
<ErrorMessage
text={controller.error.responseMessage}
hasDetails={controller.error.hasDetails}
onShowDetails={controller.onShowDetails}
/>
)}
</SubmittingForm>
)
}
{controller.error.responseMessage && (
<ErrorMessage
text={controller.error.responseMessage}
hasDetails={controller.error.hasDetails}
onShowDetails={controller.onShowDetails}
/>
)}
</content-box>
</TabsState>
);
});
@@ -67,10 +67,8 @@ export const GrantedSubjects = observer(function GrantedSubjects({
</TableHeader>
<TableBody>
{roles.map(role => (
<TableItem key={role.roleId} item={role.roleId}>
<TableColumnValue centerContent flex>
<TableItemSelect disabled={disabled}/>
</TableColumnValue>
<TableItem key={role.roleId} item={role.roleId} selectDisabled={disabled}>
<TableColumnValue centerContent flex><TableItemSelect /></TableColumnValue>
<TableColumnValue>{role.roleName}</TableColumnValue>
<TableColumnValue></TableColumnValue>
<TableColumnValue></TableColumnValue>
@@ -81,10 +79,8 @@ export const GrantedSubjects = observer(function GrantedSubjects({
const isRoleProvided = connectionPermission?.subjectType === AdminSubjectType.Role;
return (
<TableItem key={user.userId} item={user.userId}>
<TableColumnValue centerContent flex>
<TableItemSelect disabled={disabled || isRoleProvided}/>
</TableColumnValue>
<TableItem key={user.userId} item={user.userId} selectDisabled={disabled || isRoleProvided}>
<TableColumnValue centerContent flex><TableItemSelect /></TableColumnValue>
<TableColumnValue>{user.userId}</TableColumnValue>
<TableColumnValue>{isRoleProvided && user.grantedRoles.join(',')}</TableColumnValue>
<TableColumnValue></TableColumnValue>
@@ -76,10 +76,8 @@ export const GrantedConnections = observer(function GrantedConnections({
const isRoleProvided = connectionPermission?.subjectType === AdminSubjectType.Role;
return (
<TableItem key={connection.id} item={connection.id}>
<TableColumnValue centerContent flex>
<TableItemSelect disabled={disabled || isRoleProvided}/>
</TableColumnValue>
<TableItem key={connection.id} item={connection.id} selectDisabled={disabled || isRoleProvided}>
<TableColumnValue centerContent flex><TableItemSelect /></TableColumnValue>
<TableColumnValue><StaticImage icon={driver?.icon} /></TableColumnValue>
<TableColumnValue>{connection.name}</TableColumnValue>
<TableColumnValue>{isRoleProvided && connectionPermission?.subjectId}</TableColumnValue>
@@ -34,35 +34,27 @@ const styles = composes(
composes: theme-ripple theme-background-secondary theme-text-on-secondary from global;
}
TabList {
composes: theme-border-color-background from global;
}
ErrorMessage {
composes: theme-background-secondary from global;
}
content-box {
composes: theme-background-secondary theme-border-color-background from global;
}
GrantedConnections {
composes: theme-background-surface from global;
}
SubmittingForm, Loader {
composes: theme-background-secondary from global;
}
`,
css`
custom-connection {
display: flex;
flex-direction: column;
box-sizing: border-box;
content-box {
margin: 0 24px;
margin-bottom: 16px;
border: solid 1px;
border-top: none;
}
CommonDialogWrapper {
max-height: 500px;
min-height: 500px;
}
SubmittingForm, BaseTabPanel {
SubmittingForm {
flex: 1;
display: flex;
flex-direction: column;
@@ -75,7 +67,6 @@ const styles = composes(
width: 100%;
padding-left: 24px;
outline: none;
border-bottom: solid 1px;
}
Tab {
@@ -98,21 +89,11 @@ const styles = composes(
flex: 1;
}
connection-form[|new] {
border-left: solid 3px;
}
SubmittingForm, Loader {
min-height: 320px;
max-height: 500px;
}
IconButton {
height: 32px;
width: 32px;
margin-right: 16px;
}
Button:not(:first-child) {
margin-right: 24px;
}
@@ -190,93 +171,95 @@ export const UserEdit = observer(function UserEdit({
{translate(controller.isNew ? 'ui_processing_create' : 'ui_processing_save')}
</Button>
</TabList>
{controller.isLoading
? <Loader />
: (
<SubmittingForm onSubmit={controller.save} ref={focusedRef as React.RefObject<HTMLFormElement>}>
<TabPanel tabId='info'>
<layout-grid as="div">
<layout-grid-inner as="div">
<layout-grid-cell as='div' {...use({ 'span-tablet': 12, 'span-desktop': 5 })}>
<group as="div">
<InputGroup>{translate('authentication_user_credentials')}</InputGroup>
</group>
<group as="div">
<InputField
type='text'
name='login'
value={controller.credentials.login}
onChange={handleLoginChange}
disabled={!controller.isNew || controller.isSaving}
mod='surface'
>
{translate('authentication_user_name')}
</InputField>
</group>
<group as="div">
<InputField
type='password'
name='password'
value={controller.credentials.password}
onChange={handlePasswordChange}
disabled={controller.isSaving}
mod='surface'
>
{translate('authentication_user_password')}
</InputField>
</group>
<group as="div">
<InputField
type='password'
name='password_repeat'
value={controller.credentials.passwordRepeat}
onChange={handlePasswordRepeatChange}
disabled={controller.isSaving}
mod='surface'
>
{translate('authentication_user_password_repeat')}
</InputField>
</group>
</layout-grid-cell>
<layout-grid-cell as='div' {...use({ 'span-tablet': 12, 'span-desktop': 5 })}>
<group as="div">
<InputGroup>{translate('authentication_user_role')}</InputGroup>
</group>
{controller.roles.map((role, i) => (
<group as="div" key={role.roleId}>
<Checkbox
value={role.roleId}
name='role'
checkboxLabel={role.roleName || role.roleId}
onChange={checked => handleRoleChange(role.roleId, checked)}
checked={controller.credentials.roles.get(role.roleId)}
<content-box as='div'>
{controller.isLoading
? <Loader />
: (
<SubmittingForm onSubmit={controller.save} ref={focusedRef as React.RefObject<HTMLFormElement>}>
<TabPanel tabId='info'>
<layout-grid as="div">
<layout-grid-inner as="div">
<layout-grid-cell as='div' {...use({ 'span-tablet': 12, 'span-desktop': 5 })}>
<group as="div">
<InputGroup>{translate('authentication_user_credentials')}</InputGroup>
</group>
<group as="div">
<InputField
type='text'
name='login'
value={controller.credentials.login}
onChange={handleLoginChange}
disabled={!controller.isNew || controller.isSaving}
mod='surface'
>
{translate('authentication_user_name')}
</InputField>
</group>
<group as="div">
<InputField
type='password'
name='password'
value={controller.credentials.password}
onChange={handlePasswordChange}
disabled={controller.isSaving}
mod='surface'
/>
>
{translate('authentication_user_password')}
</InputField>
</group>
))}
</layout-grid-cell>
</layout-grid-inner>
</layout-grid>
</TabPanel>
<TabPanel tabId='connections_access'>
<GrantedConnections
grantedConnections={controller.grantedConnections}
connections={controller.connections}
selectedConnection={controller.selectedConnections}
disabled={controller.isLoading}
onChange={controller.handleConnectionsAccessChange}
/>
</TabPanel>
</SubmittingForm>
<group as="div">
<InputField
type='password'
name='password_repeat'
value={controller.credentials.passwordRepeat}
onChange={handlePasswordRepeatChange}
disabled={controller.isSaving}
mod='surface'
>
{translate('authentication_user_password_repeat')}
</InputField>
</group>
</layout-grid-cell>
<layout-grid-cell as='div' {...use({ 'span-tablet': 12, 'span-desktop': 5 })}>
<group as="div">
<InputGroup>{translate('authentication_user_role')}</InputGroup>
</group>
{controller.roles.map((role, i) => (
<group as="div" key={role.roleId}>
<Checkbox
value={role.roleId}
name='role'
checkboxLabel={role.roleName || role.roleId}
onChange={checked => handleRoleChange(role.roleId, checked)}
checked={controller.credentials.roles.get(role.roleId)}
disabled={controller.isSaving}
mod='surface'
/>
</group>
))}
</layout-grid-cell>
</layout-grid-inner>
</layout-grid>
</TabPanel>
<TabPanel tabId='connections_access'>
<GrantedConnections
grantedConnections={controller.grantedConnections}
connections={controller.connections}
selectedConnection={controller.selectedConnections}
disabled={controller.isLoading}
onChange={controller.handleConnectionsAccessChange}
/>
</TabPanel>
</SubmittingForm>
)}
{controller.error.responseMessage && (
<ErrorMessage
text={controller.error.responseMessage}
hasDetails={controller.error.hasDetails}
onShowDetails={controller.showDetails}
/>
)}
{controller.error.responseMessage && (
<ErrorMessage
text={controller.error.responseMessage}
hasDetails={controller.error.hasDetails}
onShowDetails={controller.showDetails}
/>
)}
</content-box>
</TabsState>
);
});