feat: CB-638 connection form readonly mode

This commit is contained in:
Wroud
2021-02-26 14:27:19 +03:00
parent c96090fff2
commit 1f22499273
11 changed files with 60 additions and 12 deletions
@@ -96,7 +96,7 @@ export const Loader: React.FC<Props> = observer(function Loader({
return () => clearTimeout(id);
}, [loading]);
if (!isVisible) {
if (!isVisible && !loading) {
return children?.() || null;
}
@@ -6,13 +6,13 @@
* you may not use this file except in compliance with the License.
*/
import { observable } from 'mobx';
import { AnnotationsMap, observable } from 'mobx';
import { useState } from 'react';
export function useObjectRef<T>(init: T, update?: Partial<T>, observed?: boolean): T {
export function useObjectRef<T>(init: T, update?: Partial<T>, observed?: boolean | AnnotationsMap<T, never>): T {
const [ref] = useState(() => {
if (observed) {
return observable.object(init, undefined, { deep: false });
return observable.object(init, typeof observed === 'object' ? observed : undefined, { deep: false });
}
return init;
});
@@ -128,7 +128,7 @@ export const ConnectionForm = observer(function ConnectionForm({
</Button>
<Button
type="button"
disabled={formState.form.disabled}
disabled={formState.form.disabled || formState.form.readonly}
mod={['unelevated']}
onClick={formState.save}
>
@@ -19,6 +19,7 @@ export interface IConnectionForm {
originLocal: boolean; // connection specific, maybe should be in another place
disabled: boolean;
loading: boolean;
readonly: boolean;
}
export interface IConnectionFormData {
@@ -107,7 +107,7 @@ export const DriverProperties: TabContainerPanelComponent<IConnectionFormTabProp
<PropertiesTable
properties={joinedProperties.get()}
propertiesState={data.config.properties}
readOnly={!form.form.originLocal}
readOnly={form.form.readonly || !form.form.originLocal}
onAdd={state.add}
/>
)}
@@ -155,7 +155,7 @@ export const Options: TabContainerPanelComponent<IConnectionFormTabProps> = obse
items={drivers}
keySelector={driver => driver.id}
valueSelector={driver => driver?.name ?? ''}
readOnly={edit || drivers.length < 2}
readOnly={form.form.readonly || edit || drivers.length < 2}
mod="surface"
disabled={form.form.disabled}
>
@@ -170,6 +170,7 @@ export const Options: TabContainerPanelComponent<IConnectionFormTabProps> = obse
minLength={1}
state={data.config}
disabled={form.form.disabled}
readOnly={form.form.readonly}
mod='surface'
required
>
@@ -182,6 +183,7 @@ export const Options: TabContainerPanelComponent<IConnectionFormTabProps> = obse
rows={3}
state={data.config}
disabled={form.form.disabled}
readOnly={form.form.readonly}
mod='surface'
>
{translate('connections_connection_description')}
@@ -195,6 +197,7 @@ export const Options: TabContainerPanelComponent<IConnectionFormTabProps> = obse
state={data.config}
checkboxLabel={translate('connections_connection_template')}
disabled={edit || form.form.disabled}
readOnly={form.form.readonly}
// autoHide={} // maybe better to use autoHide
mod='surface'
/>
@@ -210,6 +213,7 @@ export const Options: TabContainerPanelComponent<IConnectionFormTabProps> = obse
name="url"
state={data.config}
disabled={form.form.disabled}
readOnly={form.form.readonly}
autoComplete={`section-${data.config.driverId || 'driver'} section-jdbc`}
mod='surface'
>
@@ -221,7 +225,7 @@ export const Options: TabContainerPanelComponent<IConnectionFormTabProps> = obse
config={data.config}
embedded={driver.data?.embedded}
disabled={form.form.disabled}
readOnly={!form.form.originLocal}
readOnly={form.form.readonly || !form.form.originLocal}
/>
)}
</parameters-type-container>
@@ -236,6 +240,7 @@ export const Options: TabContainerPanelComponent<IConnectionFormTabProps> = obse
properties={properties}
state={data.config.credentials}
disabled={form.form.disabled}
readOnly={form.form.readonly}
showRememberTip
/>
{credentialsSavingEnabled && (
@@ -246,6 +251,7 @@ export const Options: TabContainerPanelComponent<IConnectionFormTabProps> = obse
state={data.config}
checkboxLabel={translate('connections_connection_edit_save_credentials')}
disabled={form.form.disabled}
readOnly={form.form.readonly}
mod='surface'
/>
</FormGroup>
@@ -263,6 +269,7 @@ export const Options: TabContainerPanelComponent<IConnectionFormTabProps> = obse
properties={driver.data.providerProperties}
state={data.config.providerProperties}
disabled={form.form.disabled}
readOnly={form.form.readonly}
/>
</>
)}
@@ -90,6 +90,7 @@ export const SSH: TabContainerPanelComponent<IConnectionFormTabProps> = observer
state={state}
mod={['primary']}
disabled={disabled}
readOnly={form.form.readonly}
>
{translate('connections_network_handler_ssh_tunnel_enable')}
</Switch>
@@ -102,6 +103,7 @@ export const SSH: TabContainerPanelComponent<IConnectionFormTabProps> = observer
name="host"
state={state.properties}
disabled={disabled || !enabled}
readOnly={form.form.readonly}
mod='surface'
>
{translate('connections_network_handler_ssh_tunnel_host')}
@@ -113,6 +115,7 @@ export const SSH: TabContainerPanelComponent<IConnectionFormTabProps> = observer
name="port"
state={state.properties}
disabled={disabled || !enabled}
readOnly={form.form.readonly}
mod='surface'
>
{translate('connections_network_handler_ssh_tunnel_port')}
@@ -126,6 +129,7 @@ export const SSH: TabContainerPanelComponent<IConnectionFormTabProps> = observer
name="userName"
state={state}
disabled={disabled || !enabled}
readOnly={form.form.readonly}
mod='surface'
>
{translate('connections_network_handler_ssh_tunnel_user')}
@@ -138,6 +142,7 @@ export const SSH: TabContainerPanelComponent<IConnectionFormTabProps> = observer
placeholder={passwordHint}
state={state}
disabled={disabled || !enabled}
readOnly={form.form.readonly}
mod='surface'
>
{translate('connections_network_handler_ssh_tunnel_password')}
@@ -151,6 +156,7 @@ export const SSH: TabContainerPanelComponent<IConnectionFormTabProps> = observer
state={state}
checkboxLabel={translate('connections_network_handler_ssh_tunnel_save_password')}
disabled={disabled || !enabled}
readOnly={form.form.readonly}
mod='surface'
/>
</FormGroup>
@@ -10,11 +10,26 @@ import { useRef } from 'react';
import type { IConnectionFormData } from './ConnectionFormService';
export function useConnectionData(data: IConnectionFormData, fill: (data: IConnectionFormData) => void): void {
const firstRenderRef = useRef(true);
interface IState {
connectionId: string | undefined;
driverId: string | undefined;
}
if (firstRenderRef.current) {
export function useConnectionData(data: IConnectionFormData, fill: (data: IConnectionFormData) => void): void {
const connectionId = data.info?.id || data.config.connectionId;
const driverId = data.info?.driverId || data.config.driverId;
const firstRenderRef = useRef<IState>({
connectionId: undefined,
driverId: undefined,
});
if (
firstRenderRef.current.connectionId !== connectionId
|| firstRenderRef.current.driverId !== driverId
) {
fill(data);
firstRenderRef.current = false;
firstRenderRef.current.connectionId = connectionId;
firstRenderRef.current.driverId = driverId;
}
}
@@ -14,6 +14,7 @@ import { useService } from '@cloudbeaver/core-di';
import { ExecutorHandlersCollection } from '@cloudbeaver/core-executor';
import { isLocalConnection } from '../Administration/ConnectionsResource';
import { EConnectionFeature } from '../EConnectionFeature';
import { IConnectionForm, IConnectionFormData, IConnectionFormOptions, IConnectionFormState, IConnectionFormSubmitData, ConnectionFormService } from './ConnectionFormService';
export function useConnectionFormState(
@@ -27,6 +28,17 @@ export function useConnectionFormState(
const [form] = useState<IConnectionForm>(() => observable({
disabled: false,
loading: false,
get readonly() {
if (options.type === 'admin') {
return false;
}
if (props.data.info?.features && !props.data.info.features.includes(EConnectionFeature.manageable)) {
return true;
}
return false;
},
get originLocal() {
return !props.data.info || isLocalConnection(props.data.info);
},
@@ -52,6 +52,7 @@ export const PublicConnectionForm: React.FC = observer(function PublicConnection
<Loader state={connection}>
{() => (
<ConnectionForm
key={service.connectionId}
data={data}
options={options}
onCancel={close}
@@ -6,6 +6,8 @@
* you may not use this file except in compliance with the License.
*/
import { makeObservable, observable } from 'mobx';
import { injectable } from '@cloudbeaver/core-di';
import { OptionsPanelService } from '@cloudbeaver/core-ui';
@@ -20,6 +22,10 @@ export class PublicConnectionFormService {
constructor(
private readonly optionsPanelService: OptionsPanelService
) {
makeObservable(this, {
connectionId: observable,
});
this.connectionId = null;
}