mirror of
https://github.com/dbeaver/cloudbeaver.git
synced 2026-09-24 16:04:36 +08:00
feat: CB-638 connection form readonly mode
This commit is contained in:
@@ -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 {
|
||||
|
||||
+1
-1
@@ -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 +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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user