diff --git a/lib/dl_api_connector/dl_api_connector/form_config/models/base.py b/lib/dl_api_connector/dl_api_connector/form_config/models/base.py index 6eeb30796..f6d628c61 100644 --- a/lib/dl_api_connector/dl_api_connector/form_config/models/base.py +++ b/lib/dl_api_connector/dl_api_connector/form_config/models/base.py @@ -18,6 +18,7 @@ SerializableConfig, TFieldName, TopLevelFieldName, + inner, remap_skip_if_null, ) from dl_api_connector.form_config.models.rows import CustomizableRow @@ -63,6 +64,8 @@ class ConnectionForm(SerializableConfig): template_name: Optional[str] = attr.ib(default=None, metadata=remap_skip_if_null("templateName")) form_ui_override: Optional[FormUIOverride] = attr.ib(default=None, metadata=remap_skip_if_null("uiSchema")) + implicit_form_fields: set[TFieldName] = attr.ib(factory=set, metadata=inner()) + def validate_conditional_fields(self) -> None: form_field_names = self._get_form_field_names() fields_in_conditions = self._get_conditional_fields() @@ -98,6 +101,8 @@ def _get_form_field_names(self) -> set[TFieldName]: if isinstance(row, FormFieldMixin): form_field_names.add(row.name) + form_field_names |= self.implicit_form_fields + return form_field_names def _get_conditional_fields(self) -> set[TFieldName]: diff --git a/lib/dl_api_connector/dl_api_connector/form_config/models/rows/customizable/components.py b/lib/dl_api_connector/dl_api_connector/form_config/models/rows/customizable/components.py index 21bf13179..8f90b38d3 100644 --- a/lib/dl_api_connector/dl_api_connector/form_config/models/rows/customizable/components.py +++ b/lib/dl_api_connector/dl_api_connector/form_config/models/rows/customizable/components.py @@ -56,7 +56,8 @@ class InputRowItem(ControlRowItem, PlaceholderMixin): @attr.s(kw_only=True, frozen=True) class Props(SerializableConfig): multiline: Optional[bool] = attr.ib(default=None, metadata=skip_if_null()) # false if undefined - type: Literal["text", "password", "number"] = attr.ib(default="text") + type: Optional[Literal["text", "password", "number"]] = attr.ib(default="text", metadata=skip_if_null()) + disabled: Optional[bool] = attr.ib(default=None, metadata=skip_if_null()) component_id = "input" diff --git a/lib/dl_api_connector/dl_api_connector/form_config/models/shortcuts/rows.py b/lib/dl_api_connector/dl_api_connector/form_config/models/shortcuts/rows.py index 2687d509c..277c7189f 100644 --- a/lib/dl_api_connector/dl_api_connector/form_config/models/shortcuts/rows.py +++ b/lib/dl_api_connector/dl_api_connector/form_config/models/shortcuts/rows.py @@ -44,16 +44,22 @@ def port_row( self, label_text: BaseTranslatable = Translatable("field_port"), # noqa: B008 default_value: Optional[str] = None, + display_conditions: Optional[TDisplayConditions] = None, + disabled: Optional[bool] = None, ) -> C.CustomizableRow: text = self._localizer.translate(label_text) return C.CustomizableRow( items=[ - C.LabelRowItem(text=text), + C.LabelRowItem( + text=text, + display_conditions=display_conditions, + ), C.InputRowItem( name=CommonFieldName.port, width="s", - control_props=C.InputRowItem.Props(type="number"), + control_props=C.InputRowItem.Props(type="number", disabled=disabled), default_value=default_value, + display_conditions=display_conditions, ), ] ) @@ -82,30 +88,40 @@ def username_row( label_text: BaseTranslatable = Translatable("field_username"), # noqa: B008 default_value: Optional[str] = None, display_conditions: Optional[TDisplayConditions] = None, + control_props: Optional[C.InputRowItem.Props] = None, + inner: Optional[bool] = None, ) -> C.CustomizableRow: return C.CustomizableRow( items=[ C.LabelRowItem(text=self._localizer.translate(label_text), display_conditions=display_conditions), C.InputRowItem( name=CommonFieldName.username, - width="m", default_value=default_value, display_conditions=display_conditions, + control_props=control_props, + inner=inner, ), ] ) - def password_row(self, mode: ConnectionFormMode) -> C.CustomizableRow: - label_text = self._localizer.translate(Translatable("field_password")) + def password_row( + self, + mode: ConnectionFormMode, + display_conditions: Optional[TDisplayConditions] = None, + ) -> C.CustomizableRow: return C.CustomizableRow( items=[ - C.LabelRowItem(text=label_text), + C.LabelRowItem( + text=self._localizer.translate(Translatable("field_password")), + display_conditions=display_conditions, + ), C.InputRowItem( name=CommonFieldName.password, width="m", default_value="" if mode == ConnectionFormMode.create else None, fake_value="******" if mode == ConnectionFormMode.edit else None, control_props=C.InputRowItem.Props(type="password"), + display_conditions=display_conditions, ), ] ) diff --git a/lib/dl_connector_postgresql/dl_connector_postgresql/api/connection_form/form_config.py b/lib/dl_connector_postgresql/dl_connector_postgresql/api/connection_form/form_config.py index 207efb672..e950e6720 100644 --- a/lib/dl_connector_postgresql/dl_connector_postgresql/api/connection_form/form_config.py +++ b/lib/dl_connector_postgresql/dl_connector_postgresql/api/connection_form/form_config.py @@ -1,10 +1,7 @@ from __future__ import annotations from enum import unique -from typing import ( - Optional, - Sequence, -) +import typing import attr @@ -23,6 +20,7 @@ from dl_api_connector.form_config.models.common import ( CommonFieldName, FormFieldName, + TFieldName, ) from dl_api_connector.form_config.models.rows.base import FormRow from dl_api_connector.form_config.models.shortcuts.rows import RowConstructor @@ -74,6 +72,11 @@ def enforce_collate_row(self) -> C.CustomizableRow: class PostgreSQLConnectionFormFactory(ConnectionFormFactory): + DEFAULT_PORT = "6432" + + def _get_implicit_form_fields(self) -> set[TFieldName]: + return set() + def _get_base_edit_api_schema(self) -> FormActionApiSchema: return FormActionApiSchema( items=[ @@ -116,9 +119,11 @@ def _get_base_check_api_schema(self) -> FormActionApiSchema: def _get_base_form_config( self, - host_section: Sequence[FormRow], - username_section: Sequence[FormRow], - db_name_section: Sequence[FormRow], + host_section: typing.Sequence[FormRow], + port_section: typing.Sequence[FormRow], + db_name_section: typing.Sequence[FormRow], + username_section: typing.Sequence[FormRow], + password_section: typing.Sequence[FormRow], create_api_schema: FormActionApiSchema, edit_api_schema: FormActionApiSchema, check_api_schema: FormActionApiSchema, @@ -130,10 +135,10 @@ def _get_base_form_config( rows=self._filter_nulls( [ *host_section, - rc.port_row(default_value="6432"), + *port_section, *db_name_section, *username_section, - rc.password_row(mode=self.mode), + *password_section, C.CacheTTLRow(name=CommonFieldName.cache_ttl_sec), rc.raw_sql_level_row(), rc.collapse_advanced_settings_row(), @@ -151,28 +156,62 @@ def _get_base_form_config( edit=edit_api_schema if self.mode == ConnectionFormMode.edit else None, check=check_api_schema, ), + implicit_form_fields=self._get_implicit_form_fields(), ) + def _get_host_section( + self, + rc: RowConstructor, + connector_settings: typing.Optional[ConnectorSettingsBase], + ) -> typing.Sequence[FormRow]: + return [rc.host_row()] + + def _get_port_section( + self, + rc: RowConstructor, + connector_settings: typing.Optional[ConnectorSettingsBase], + ) -> typing.Sequence[FormRow]: + return [rc.port_row(default_value=self.DEFAULT_PORT)] + + def _get_username_section( + self, + rc: RowConstructor, + connector_settings: typing.Optional[ConnectorSettingsBase], + ) -> typing.Sequence[FormRow]: + return [rc.username_row()] + + def _get_db_name_section( + self, + rc: RowConstructor, + connector_settings: typing.Optional[ConnectorSettingsBase], + ) -> typing.Sequence[FormRow]: + return [rc.db_name_row()] + + def _get_password_section( + self, + rc: RowConstructor, + connector_settings: typing.Optional[ConnectorSettingsBase], + ) -> typing.Sequence[FormRow]: + return [rc.password_row(mode=self.mode)] + def get_form_config( self, - connector_settings: Optional[ConnectorSettingsBase], - tenant: Optional[TenantDef], + connector_settings: typing.Optional[ConnectorSettingsBase], + tenant: typing.Optional[TenantDef], ) -> ConnectionForm: rc = RowConstructor(localizer=self._localizer) postgres_rc = PostgresRowConstructor(localizer=self._localizer) - host_section = [rc.host_row()] - username_section = [rc.username_row()] - db_name_section = [rc.db_name_row()] - edit_api_schema = self._get_base_edit_api_schema() create_api_schema = self._get_base_create_api_schema(edit_api_schema) check_api_schema = self._get_base_check_api_schema() return self._get_base_form_config( - host_section=host_section, - username_section=username_section, - db_name_section=db_name_section, + host_section=self._get_host_section(rc, connector_settings), + port_section=self._get_port_section(rc, connector_settings), + db_name_section=self._get_db_name_section(rc, connector_settings), + username_section=self._get_username_section(rc, connector_settings), + password_section=self._get_password_section(rc, connector_settings), create_api_schema=create_api_schema, edit_api_schema=edit_api_schema, check_api_schema=check_api_schema,