@finos/legend-application-studio
Version:
Legend Studio application core
397 lines • 48.1 kB
JavaScript
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
/**
* Copyright (c) 2020-present, Goldman Sachs
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { observer } from 'mobx-react-lite';
import { useState } from 'react';
import { RELATIONAL_DATABASE_TAB_TYPE, POST_PROCESSOR_TYPE, } from '../../../../stores/editor/editor-state/element-editor-state/connection/ConnectionEditorState.js';
import { ResizablePanelGroup, ResizablePanel, ResizablePanelSplitter, CustomSelectorInput, ErrorIcon, FilledWindowMaximizeIcon, PanelHeader, PlusIcon, PanelFormTextField, ContextMenu, MenuContent, MenuContentItem, PanelListSelectorItem, ControlledDropdownMenu, PanelTabs, BlankPanelContent, ResizablePanelSplitterLine, PanelContent, Panel, Badge, PanelListSelectorItemLabel, PanelFormBooleanField, PanelHeaderActions, PanelDivider, PanelFormSection, Dialog, Modal, ModalBody, ModalFooter, ModalFooterButton, ModalHeader, Button, } from '@finos/legend-art';
import { DatabaseType, DelegatedKerberosAuthenticationStrategy, OAuthAuthenticationStrategy, SnowflakePublicAuthenticationStrategy, ApiTokenAuthenticationStrategy, UsernamePasswordAuthenticationStrategy, GCPWorkloadIdentityFederationAuthenticationStrategy, MiddleTierUsernamePasswordAuthenticationStrategy, TrinoDelegatedKerberosAuthenticationStrategy, EmbeddedH2DatasourceSpecification, LocalH2DatasourceSpecification, SnowflakeDatasourceSpecification, DatabricksDatasourceSpecification, StaticDatasourceSpecification, BigQueryDatasourceSpecification, RedshiftDatasourceSpecification, PackageableElementExplicitReference, MapperPostProcessor, SpannerDatasourceSpecification, TrinoDatasourceSpecification, guaranteeRelationalDatabaseConnection, } from '@finos/legend-graph';
import { useEditorStore } from '../../EditorStoreProvider.js';
import { CODE_EDITOR_LANGUAGE } from '@finos/legend-code-editor';
import { CodeEditor } from '@finos/legend-lego/code-editor';
import { buildElementOption, } from '@finos/legend-lego/graph-editor';
import { connection_setStore } from '../../../../stores/graph-modifier/DSL_Mapping_GraphModifierHelper.js';
import { apiTokenAuthenticationStrategy_setApiToken, bigQueryDatasourceSpecification_setDefaultDataset, bigQueryDatasourceSpecification_setProjectId, bigQueryDatasourceSpecification_setProxyHost, bigQueryDatasourceSpecification_setProxyPort, databricksDatasourceSpecification_setHostName, databricksDatasourceSpecification_setHttpPath, databricksDatasourceSpecification_setPort, databricksDatasourceSpecification_setProtocol, dBConnection_setQuoteIdentifiers, dBConnection_setType, delegatedKerberosAuthenticationStrategy_setServerPrincipal, embeddedH2DatasourceSpecification_setAutoServerMode, embeddedH2DatasourceSpecification_setDatabaseName, embeddedH2DatasourceSpecification_setDirectory, localH2DatasourceSpecification_setTestDataSetupSqls, oAuthAuthenticationStrategy_setOauthKey, oAuthAuthenticationStrategy_setScopeName, redshiftDatasourceSpecification_setClusterID, redshiftDatasourceSpecification_setDatabaseName, redshiftDatasourceSpecification_setEndpointURL, redshiftDatasourceSpecification_setHost, redshiftDatasourceSpecification_setPort, redshiftDatasourceSpecification_setRegion, snowflakeDatasourceSpec_setAccountName, snowflakeDatasourceSpec_setAccountType, snowflakeDatasourceSpec_setCloudType, snowflakeDatasourceSpec_setDatabaseName, snowflakeDatasourceSpec_setNonProxyHosts, snowflakeDatasourceSpec_setOrganization, snowflakeDatasourceSpec_setProxyHost, snowflakeDatasourceSpec_setProxyPort, snowflakeDatasourceSpec_setQuotedIdentifiersIgnoreCase, snowflakeDatasourceSpec_setEnableQueryTags, snowflakeDatasourceSpec_setRegion, snowflakeDatasourceSpec_setRole, snowflakeDatasourceSpec_setWarehouseName, snowflakePublicAuthenticationStrategy_setPassPhraseVaultReference, snowflakePublicAuthenticationStrategy_setPrivateKeyVaultReference, snowflakePublicAuthenticationStrategy_setPublicUserName, spannerDatasourceSpecification_setDatabaseId, spannerDatasourceSpecification_setProxyHost, spannerDatasourceSpecification_setInstanceId, spannerDatasourceSpecification_setProxyPort, spannerDatasourceSpecification_setProjectId, staticDatasourceSpecification_setDatabaseName, staticDatasourceSpecification_setHost, staticDatasourceSpecification_setPort, trinoDatasourceSpecification_setHost, trinoDatasourceSpecification_setPort, trinoDatasourceSpecification_setCatalog, trinoDatasourceSpecification_setSchema, trinoDatasourceSpecification_setClientTags, trinoDatasourceSpecification_setSsl, trinoDatasourceSpecification_setTrustStorePathVaultReference, trinoDatasourceSpecification_setTrustStorePasswordVaultReference, trinoDelegatedKerberosAuthenticationStrategy_setKerberosRemoteServiceName, trinoDelegatedKerberosAuthenticationStrategy_setKerberosUseCanonicalHostname, usernamePasswordAuthenticationStrategy_setBaseVaultReference, usernamePasswordAuthenticationStrategy_setPasswordVaultReference, usernamePasswordAuthenticationStrategy_setUserNameVaultReference, gcpWorkloadIdentityFederationAuthenticationStrategy_setServiceAccountEmail, gcpWorkloadIdentityFederationAuthenticationStrategy_setAdditionalGcpScopes, middleTierUsernamePasswordAuthenticationStrategy_setVaultReference, relationalDatabaseConnection_addPostProcessor, relationalDatabaseConnection_deletePostProcessor, snowflakeDatasourceSpec_setTempTableDb, snowflakeDatasourceSpec_setTempTableSchema, dBConnection_setQueryTimeOut, } from '../../../../stores/graph-modifier/STO_Relational_GraphModifierHelper.js';
import { MapperPostProcessorEditor } from './post-processor-editor/MapperPostProcessorEditor.js';
import { UnsupportedEditorPanel } from '../UnsupportedElementEditor.js';
import { prettyCONSTName, uniq } from '@finos/legend-shared';
import { useApplicationStore } from '@finos/legend-application';
export const buildRelationalDatabaseConnectionOption = (connection) => {
const connectionValue = guaranteeRelationalDatabaseConnection(connection);
return {
value: connection,
label: (_jsxs("div", { className: "sql-playground__config__connection-selector__option", children: [_jsx("div", { className: "sql-playground__config__connection-selector__option__label", children: connection.name }), _jsx("div", { className: "sql-playground__config__connection-selector__option__type", children: connectionValue.type }), _jsx("div", { className: "sql-playground__config__connection-selector__option__path", children: connection.path })] })),
};
};
const LocalH2DatasourceSpecificationEditor = observer((props) => {
const applicationStore = useApplicationStore();
const { sourceSpec, isReadOnly } = props;
const [showPopUp, setShowPopUp] = useState(false);
const openInPopUp = () => setShowPopUp(true);
const closePopUp = () => setShowPopUp(false);
// TODO?: support CSV and toggler to go to CSV mode
const SQLValue = sourceSpec.testDataSetupSqls.join('\n');
return (_jsxs(_Fragment, { children: [showPopUp && (_jsx("div", { children: _jsx(Dialog, { open: showPopUp, onClose: closePopUp, children: _jsxs(Modal, { darkMode: !applicationStore.layoutService
.TEMPORARY__isLightColorThemeEnabled, className: "editor-modal", children: [_jsx(ModalHeader, { title: "test data setup SQL" }), _jsx(ModalBody, { className: "modal__body__large", children: _jsx(CodeEditor, { inputValue: SQLValue, updateInput: (value) => localH2DatasourceSpecification_setTestDataSetupSqls(sourceSpec, value ? [value] : []), isReadOnly: isReadOnly, language: CODE_EDITOR_LANGUAGE.SQL }) }), _jsx(ModalFooter, { children: _jsx(ModalFooterButton, { onClick: closePopUp, text: "Close", type: "secondary" }) })] }) }) })), _jsxs("div", { children: [_jsxs("div", { className: "panel__content__form__section__header__label", children: ["Test Data Setup SQL", _jsx(Button, { className: "btn--icon--small btn--icon--margin--left", onClick: openInPopUp, title: "Open...", children: _jsx(FilledWindowMaximizeIcon, {}) })] }), _jsx("div", { className: "panel__content__form__section__text-editor", children: _jsx(CodeEditor, { inputValue: SQLValue, updateInput: (value) => localH2DatasourceSpecification_setTestDataSetupSqls(sourceSpec, value ? [value] : []), isReadOnly: isReadOnly, language: CODE_EDITOR_LANGUAGE.SQL }) })] })] }));
});
const StaticDatasourceSpecificationEditor = observer((props) => {
const { sourceSpec, isReadOnly } = props;
const changePort = (event) => {
const val = event.target.value;
staticDatasourceSpecification_setPort(sourceSpec, parseInt(val, 10));
};
return (_jsxs(_Fragment, { children: [_jsx(PanelFormTextField, { isReadOnly: isReadOnly, value: sourceSpec.host, name: "host (required)", update: (value) => staticDatasourceSpecification_setHost(sourceSpec, value ?? '') }), _jsxs(PanelFormSection, { children: [_jsx("div", { className: "panel__content__form__section__header__label", children: "port" }), _jsx("input", { className: "panel__content__form__section__input panel__content__form__section__number-input", spellCheck: false, type: "number (required)", disabled: isReadOnly, value: sourceSpec.port, onChange: changePort })] }), _jsx(PanelFormTextField, { isReadOnly: isReadOnly, value: sourceSpec.databaseName, name: "database (required)", update: (value) => staticDatasourceSpecification_setDatabaseName(sourceSpec, value ?? '') })] }));
});
const EmbeddedH2DatasourceSpecificationEditor = observer((props) => {
const { sourceSpec, isReadOnly } = props;
return (_jsxs(_Fragment, { children: [_jsx(PanelFormTextField, { isReadOnly: isReadOnly, value: sourceSpec.databaseName, name: "database (required)", update: (value) => embeddedH2DatasourceSpecification_setDatabaseName(sourceSpec, value ?? '') }), _jsx(PanelFormTextField, { isReadOnly: isReadOnly, value: sourceSpec.directory, name: "directory (required)", update: (value) => embeddedH2DatasourceSpecification_setDirectory(sourceSpec, value ?? '') }), _jsx(PanelFormBooleanField, { isReadOnly: isReadOnly, value: sourceSpec.autoServerMode, name: "auto server mode (required)", update: (value) => embeddedH2DatasourceSpecification_setAutoServerMode(sourceSpec, Boolean(value)) })] }));
});
const DatabricksDatasourceSpecificationEditor = observer((props) => {
const { sourceSpec, isReadOnly } = props;
return (_jsxs(_Fragment, { children: [_jsx(PanelFormTextField, { isReadOnly: isReadOnly, value: sourceSpec.hostname, name: "hostname (required)", update: (value) => databricksDatasourceSpecification_setHostName(sourceSpec, value ?? '') }), _jsx(PanelFormTextField, { isReadOnly: isReadOnly, value: sourceSpec.port, name: "port (required)", update: (value) => databricksDatasourceSpecification_setPort(sourceSpec, value ?? '') }), _jsx(PanelFormTextField, { isReadOnly: isReadOnly, value: sourceSpec.protocol, name: "protocol (required)", update: (value) => databricksDatasourceSpecification_setProtocol(sourceSpec, value ?? '') }), _jsx(PanelFormTextField, { isReadOnly: isReadOnly, value: sourceSpec.httpPath, name: "httpPath (required)", update: (value) => databricksDatasourceSpecification_setHttpPath(sourceSpec, value ?? '') })] }));
});
const TrinoDatasourceSpecificationEditor = observer((props) => {
const { sourceSpec, isReadOnly } = props;
const changePort = (event) => {
const val = event.target.value;
trinoDatasourceSpecification_setPort(sourceSpec, parseInt(val, 10));
};
return (_jsxs(_Fragment, { children: [_jsx(PanelFormTextField, { isReadOnly: isReadOnly, value: sourceSpec.host, name: "host (required)", update: (value) => trinoDatasourceSpecification_setHost(sourceSpec, value ?? '') }), _jsxs("div", { className: "panel__content__form__section", children: [_jsx("div", { className: "panel__content__form__section__header__label", children: "port (required)" }), _jsx("input", { className: "panel__content__form__section__input panel__content__form__section__number-input", spellCheck: false, type: "number", disabled: isReadOnly, value: sourceSpec.port, onChange: changePort })] }), _jsx(PanelFormTextField, { isReadOnly: isReadOnly, value: sourceSpec.catalog, name: "catalog", update: (value) => trinoDatasourceSpecification_setCatalog(sourceSpec, value) }), _jsx(PanelFormTextField, { isReadOnly: isReadOnly, value: sourceSpec.schema, name: "schema", update: (value) => trinoDatasourceSpecification_setSchema(sourceSpec, value) }), _jsx(PanelFormTextField, { isReadOnly: isReadOnly, value: sourceSpec.clientTags, name: "clientTags", update: (value) => trinoDatasourceSpecification_setClientTags(sourceSpec, value) }), _jsx(PanelFormBooleanField, { isReadOnly: isReadOnly, value: sourceSpec.sslSpecification.ssl, name: "SSL", update: (value) => trinoDatasourceSpecification_setSsl(sourceSpec, Boolean(value)) }), _jsx(PanelFormTextField, { isReadOnly: isReadOnly, value: sourceSpec.sslSpecification.trustStorePathVaultReference, name: "TrustStorePathVaultReference", update: (value) => trinoDatasourceSpecification_setTrustStorePathVaultReference(sourceSpec, value) }), _jsx(PanelFormTextField, { isReadOnly: isReadOnly, value: sourceSpec.sslSpecification.trustStorePasswordVaultReference, name: "TrustStorePasswordVaultReference", update: (value) => trinoDatasourceSpecification_setTrustStorePasswordVaultReference(sourceSpec, value) })] }));
});
const SnowflakeDatasourceSpecificationEditor = observer((props) => {
const { sourceSpec, isReadOnly } = props;
return (_jsxs(_Fragment, { children: [_jsx(PanelFormTextField, { isReadOnly: isReadOnly, value: sourceSpec.accountName, name: "account (required)", update: (value) => snowflakeDatasourceSpec_setAccountName(sourceSpec, value ?? '') }), _jsx(PanelFormTextField, { isReadOnly: isReadOnly, value: sourceSpec.region, name: "region (required)", update: (value) => snowflakeDatasourceSpec_setRegion(sourceSpec, value ?? '') }), _jsx(PanelFormTextField, { isReadOnly: isReadOnly, value: sourceSpec.warehouseName, name: "warehouse (required)", update: (value) => snowflakeDatasourceSpec_setWarehouseName(sourceSpec, value ?? '') }), _jsx(PanelFormTextField, { isReadOnly: isReadOnly, value: sourceSpec.databaseName, name: "database (required)", update: (value) => snowflakeDatasourceSpec_setDatabaseName(sourceSpec, value ?? '') }), _jsx(PanelFormTextField, { isReadOnly: isReadOnly, value: sourceSpec.cloudType, name: "cloud type", update: (value) => snowflakeDatasourceSpec_setCloudType(sourceSpec, value) }), _jsx(PanelFormTextField, { isReadOnly: isReadOnly, value: sourceSpec.proxyHost, name: "proxy host", update: (value) => snowflakeDatasourceSpec_setProxyHost(sourceSpec, value) }), _jsx(PanelFormTextField, { isReadOnly: isReadOnly, value: sourceSpec.proxyPort, name: "proxy port", update: (value) => snowflakeDatasourceSpec_setProxyPort(sourceSpec, value) }), _jsx(PanelFormTextField, { isReadOnly: isReadOnly, value: sourceSpec.nonProxyHosts, name: "non proxy hosts", update: (value) => snowflakeDatasourceSpec_setNonProxyHosts(sourceSpec, value) }), _jsx(PanelFormTextField, { isReadOnly: isReadOnly, value: sourceSpec.organization, name: "organization", update: (value) => snowflakeDatasourceSpec_setOrganization(sourceSpec, value) }), _jsx(PanelFormTextField, { isReadOnly: isReadOnly, value: sourceSpec.accountType, name: "account type", update: (value) => snowflakeDatasourceSpec_setAccountType(sourceSpec, value) }), _jsx(PanelFormTextField, { isReadOnly: isReadOnly, value: sourceSpec.role, name: "role", update: (value) => snowflakeDatasourceSpec_setRole(sourceSpec, value) }), _jsx(PanelFormTextField, { isReadOnly: isReadOnly, value: sourceSpec.tempTableDb, name: "Temp Table DB", update: (value) => snowflakeDatasourceSpec_setTempTableDb(sourceSpec, value ?? undefined) }), _jsx(PanelFormTextField, { isReadOnly: isReadOnly, value: sourceSpec.tempTableSchema, name: "Temp Table Schema", update: (value) => snowflakeDatasourceSpec_setTempTableSchema(sourceSpec, value ?? undefined) }), _jsx(PanelFormBooleanField, { isReadOnly: isReadOnly, value: sourceSpec.quotedIdentifiersIgnoreCase, name: "quoted identifiers ignore case", prompt: "Controls whether Snowflake will treat alphabetic characters in double-quoted identifiers as uppercase", update: (value) => snowflakeDatasourceSpec_setQuotedIdentifiersIgnoreCase(sourceSpec, Boolean(value)) }), _jsx(PanelFormBooleanField, { isReadOnly: isReadOnly, value: sourceSpec.enableQueryTags, name: "Enable Query Tags", prompt: "Controls whether engine sets a tag on each query for identification", update: (value) => snowflakeDatasourceSpec_setEnableQueryTags(sourceSpec, Boolean(value)) })] }));
});
const RedshiftDatasourceSpecificationEditor = observer((props) => {
const { sourceSpec, isReadOnly } = props;
const changePort = (event) => {
const val = event.target.value;
redshiftDatasourceSpecification_setPort(sourceSpec, parseInt(val, 10));
};
return (_jsxs(_Fragment, { children: [_jsx(PanelFormTextField, { isReadOnly: isReadOnly, value: sourceSpec.host, name: "host (required)", update: (value) => redshiftDatasourceSpecification_setHost(sourceSpec, value ?? '') }), _jsxs("div", { className: "panel__content__form__section", children: [_jsx("div", { className: "panel__content__form__section__header__label", children: "port (required)" }), _jsx("input", { className: "panel__content__form__section__input panel__content__form__section__number-input", spellCheck: false, type: "number", disabled: isReadOnly, value: sourceSpec.port, onChange: changePort })] }), _jsx(PanelFormTextField, { isReadOnly: isReadOnly, value: sourceSpec.databaseName, name: "database (required)", update: (value) => redshiftDatasourceSpecification_setDatabaseName(sourceSpec, value ?? '') }), _jsx(PanelFormTextField, { isReadOnly: isReadOnly, value: sourceSpec.region, name: "region (required)", update: (value) => redshiftDatasourceSpecification_setRegion(sourceSpec, value ?? '') }), _jsx(PanelFormTextField, { isReadOnly: isReadOnly, value: sourceSpec.clusterID, name: "cluster (required)", update: (value) => redshiftDatasourceSpecification_setClusterID(sourceSpec, value ?? '') }), _jsx(PanelFormTextField, { isReadOnly: isReadOnly, value: sourceSpec.endpointURL, name: "endpointURL", update: (value) => redshiftDatasourceSpecification_setEndpointURL(sourceSpec, value ?? '') })] }));
});
const BigQueryDatasourceSpecificationEditor = observer((props) => {
const { sourceSpec, isReadOnly } = props;
return (_jsxs(_Fragment, { children: [_jsx(PanelFormTextField, { isReadOnly: isReadOnly, value: sourceSpec.projectId, name: "project id (required)", update: (value) => bigQueryDatasourceSpecification_setProjectId(sourceSpec, value ?? '') }), _jsx(PanelFormTextField, { isReadOnly: isReadOnly, value: sourceSpec.defaultDataset, name: "default dataset", update: (value) => bigQueryDatasourceSpecification_setDefaultDataset(sourceSpec, value ?? '') }), _jsx(PanelFormTextField, { isReadOnly: isReadOnly, value: sourceSpec.proxyHost, name: "proxy host", prompt: "Specifies proxy host for connection to GCP BigQuery", update: (value) => bigQueryDatasourceSpecification_setProxyHost(sourceSpec, value ?? '') }), _jsx(PanelFormTextField, { isReadOnly: isReadOnly, value: sourceSpec.proxyPort, name: "proxy port", prompt: "Specifies proxy port for connection to GCP BigQuery", update: (value) => bigQueryDatasourceSpecification_setProxyPort(sourceSpec, value ?? '') })] }));
});
const SpannerDatasourceSpecificationEditor = observer((props) => {
const { sourceSpec, isReadOnly } = props;
return (_jsxs(_Fragment, { children: [_jsx(PanelFormTextField, { isReadOnly: isReadOnly, value: sourceSpec.projectId, name: "project id (required)", prompt: "Your Google Cloud Platform (GCP) project identifier", update: (value) => spannerDatasourceSpecification_setProjectId(sourceSpec, value ?? '') }), _jsx(PanelFormTextField, { isReadOnly: isReadOnly, value: sourceSpec.instanceId, name: "instance id (required)", prompt: "Spanner instance identifier in Google Cloud Platform (GCP)", update: (value) => spannerDatasourceSpecification_setInstanceId(sourceSpec, value ?? '') }), _jsx(PanelFormTextField, { isReadOnly: isReadOnly, value: sourceSpec.databaseId, name: "database id (required)", prompt: "Spanner database identifier", update: (value) => spannerDatasourceSpecification_setDatabaseId(sourceSpec, value ?? '') }), _jsx(PanelFormTextField, { isReadOnly: isReadOnly, value: sourceSpec.proxyHost, name: "proxyHost", prompt: "Specifies the connection host. Leave blank to use GCP defaults", update: (value) => spannerDatasourceSpecification_setProxyHost(sourceSpec, value ?? '') }), _jsx(PanelFormTextField, { isReadOnly: isReadOnly, value: sourceSpec.proxyPort, name: "proxyPort", prompt: "Specifies the connection port. Leave blank to use GCP defaults", update: (value) => spannerDatasourceSpecification_setProxyPort(sourceSpec, value ?? '') })] }));
});
// auth strategy
const DelegatedKerberosAuthenticationStrategyEditor = observer((props) => {
const { authSpec, isReadOnly } = props;
return (_jsx(_Fragment, { children: _jsx(PanelFormTextField, { isReadOnly: isReadOnly, value: authSpec.serverPrincipal, name: "server principal", update: (value) => delegatedKerberosAuthenticationStrategy_setServerPrincipal(authSpec, value ?? '') }) }));
});
const ApiTokenAuthenticationStrategyEditor = observer((props) => {
const { authSpec, isReadOnly } = props;
return (_jsx(_Fragment, { children: _jsx(PanelFormTextField, { isReadOnly: isReadOnly, value: authSpec.apiToken, name: "apiTokenRef (required)", update: (value) => apiTokenAuthenticationStrategy_setApiToken(authSpec, value ?? '') }) }));
});
const SnowflakePublicAuthenticationStrategyEditor = observer((props) => {
const { authSpec, isReadOnly } = props;
return (_jsxs(_Fragment, { children: [_jsx(PanelFormTextField, { isReadOnly: isReadOnly, value: authSpec.privateKeyVaultReference, name: "private key vault reference (required)", update: (value) => snowflakePublicAuthenticationStrategy_setPrivateKeyVaultReference(authSpec, value ?? '') }), _jsx(PanelFormTextField, { isReadOnly: isReadOnly, value: authSpec.passPhraseVaultReference, name: "pass phrase vault reference (required)", update: (value) => snowflakePublicAuthenticationStrategy_setPassPhraseVaultReference(authSpec, value ?? '') }), _jsx(PanelFormTextField, { isReadOnly: isReadOnly, value: authSpec.publicUserName, name: "public user name (required)", update: (value) => snowflakePublicAuthenticationStrategy_setPublicUserName(authSpec, value ?? '') })] }));
});
const OAuthAuthenticationStrategyEditor = observer((props) => {
const { authSpec, isReadOnly } = props;
return (_jsxs(_Fragment, { children: [_jsx(PanelFormTextField, { isReadOnly: isReadOnly, value: authSpec.oauthKey, name: "oauth key (required)", update: (value) => oAuthAuthenticationStrategy_setOauthKey(authSpec, value ?? '') }), _jsx(PanelFormTextField, { isReadOnly: isReadOnly, value: authSpec.scopeName, name: "scope name (required)", update: (value) => oAuthAuthenticationStrategy_setScopeName(authSpec, value ?? '') })] }));
});
const UsernamePasswordAuthenticationStrategyEditor = observer((props) => {
const { authSpec, isReadOnly } = props;
return (_jsxs(_Fragment, { children: [_jsx(PanelFormTextField, { isReadOnly: isReadOnly, value: authSpec.baseVaultReference, name: "base vault reference", update: (value) => usernamePasswordAuthenticationStrategy_setBaseVaultReference(authSpec, value) }), _jsx(PanelFormTextField, { isReadOnly: isReadOnly, value: authSpec.userNameVaultReference, name: "user name vault reference (required)", update: (value) => usernamePasswordAuthenticationStrategy_setUserNameVaultReference(authSpec, value ?? '') }), _jsx(PanelFormTextField, { isReadOnly: isReadOnly, value: authSpec.passwordVaultReference, name: "password vault reference (required)", update: (value) => usernamePasswordAuthenticationStrategy_setPasswordVaultReference(authSpec, value ?? '') })] }));
});
// Middle Tier Username Password Authentication Strategy obtains credentials(username and password) from the provided vault reference
const MiddleTierUsernamePasswordAuthenticationStrategyEditor = observer((props) => {
const { authSpec, isReadOnly } = props;
return (_jsx(_Fragment, { children: _jsx(PanelFormTextField, { isReadOnly: isReadOnly, value: authSpec.vaultReference, name: "vault reference (required)", prompt: "Specifies the credential vault reference containing connection credentials", update: (value) => middleTierUsernamePasswordAuthenticationStrategy_setVaultReference(authSpec, value ?? '') }) }));
});
const TrinoDelegatedKerberosAuthenticationStrategyEditor = observer((props) => {
const { authSpec, isReadOnly } = props;
return (_jsxs(_Fragment, { children: [_jsx(PanelFormTextField, { isReadOnly: isReadOnly, value: authSpec.kerberosRemoteServiceName, name: "Kerberos Remote Service Name (required)", prompt: "Specifies the Kerberos Remote Service Name", update: (value) => trinoDelegatedKerberosAuthenticationStrategy_setKerberosRemoteServiceName(authSpec, value ?? '') }), _jsx(PanelFormBooleanField, { isReadOnly: isReadOnly, value: authSpec.kerberosUseCanonicalHostname, name: "kerberosUseCanonicalHostname", prompt: "Specifies KerberosUseCanonicalHostname", update: (value) => trinoDelegatedKerberosAuthenticationStrategy_setKerberosUseCanonicalHostname(authSpec, Boolean(value)) })] }));
});
const GCPWorkloadIdentityFederationAuthenticationStrategyEditor = observer((props) => {
const { authSpec, isReadOnly } = props;
const GCPScopes = authSpec.additionalGcpScopes.join('\n');
return (_jsxs(_Fragment, { children: [_jsx(PanelFormTextField, { isReadOnly: isReadOnly, value: authSpec.serviceAccountEmail, name: "Service Account Email (required)", update: (value) => gcpWorkloadIdentityFederationAuthenticationStrategy_setServiceAccountEmail(authSpec, value ?? '') }), _jsx(PanelFormTextField, { isReadOnly: isReadOnly, value: GCPScopes, name: "Additional GCP Scopes", update: (value) => gcpWorkloadIdentityFederationAuthenticationStrategy_setAdditionalGcpScopes(authSpec, value ? [value] : []) })] }));
});
const RelationalConnectionStoreEditor = observer((props) => {
const { connectionValueState, isReadOnly } = props;
const applicationStore = connectionValueState.editorStore.applicationStore;
const connection = connectionValueState.connection;
// store
const isStoreEmpty = connectionValueState.storeValidationResult;
const noStoreLabel = (_jsxs("div", { className: "relational-connection-editor__store-option--empty", title: isStoreEmpty?.messages.join('\n') ?? '', children: [_jsx("div", { className: "relational-connection-editor__store-option--empty__label", children: "(none)" }), _jsx(ErrorIcon, {})] }));
const stores = connectionValueState.editorStore.graphManagerState.graph.ownStores;
const options = stores.map(buildElementOption);
const store = connection.store?.value;
const selectedStore = {
value: store,
label: isStoreEmpty ? noStoreLabel : store?.path,
};
const onStoreChange = (val) => {
if (val) {
connection_setStore(connection, PackageableElementExplicitReference.create(val.value));
}
};
const openDatabaseBuilder = () => connectionValueState.editorStore.explorerTreeState.buildDatabase(connection, isReadOnly);
return (_jsx("div", { className: "relational-connection-editor", children: _jsx(PanelContent, { className: "relational-connection-editor__auth__content", children: _jsxs(PanelFormSection, { children: [_jsx("div", { className: "panel__content__form__section__header__label", children: "Store" }), _jsx(CustomSelectorInput, { options: options, onChange: onStoreChange, value: selectedStore, darkMode: !applicationStore.layoutService
.TEMPORARY__isLightColorThemeEnabled, disabled: isReadOnly, hasError: Boolean(isStoreEmpty) }), _jsx(PanelDivider, {}), _jsx("button", { className: "relational-connection-editor-btn btn--dark", onClick: openDatabaseBuilder, disabled: Boolean(isStoreEmpty), children: "Build Database" })] }) }) }));
});
const renderEditorPostProcessor = (connectionValueState, postProcessor, isReadOnly, plugins) => {
if (postProcessor instanceof MapperPostProcessor) {
return (_jsx(MapperPostProcessorEditor, { postProcessorState: connectionValueState.postProcessorState, isReadOnly: isReadOnly, postProcessor: postProcessor }));
}
else {
const extraPostProcessorEditorRenderers = plugins.flatMap((plugin) => plugin.getExtraPostProcessorEditorRenderers?.() ?? []);
for (const editorRenderer of extraPostProcessorEditorRenderers) {
const editor = editorRenderer(postProcessor, connectionValueState, false);
if (editor) {
return editor;
}
}
return (_jsx(UnsupportedEditorPanel, { isReadOnly: true, text: "Can't display post-processor in form mode" }));
}
};
const PostProcessorRelationalConnectionEditor = observer((props) => {
const { connectionValueState, isReadOnly } = props;
const connection = connectionValueState.connection;
const postProcessors = connection.postProcessors;
const editorStore = useEditorStore();
const observerContext = editorStore.changeDetectionState.observerContext;
const plugins = editorStore.pluginManager.getApplicationPlugins();
const postProcessorState = connectionValueState.postProcessorState;
const deletePostProcessor = (postProcessor) => () => {
relationalDatabaseConnection_deletePostProcessor(connectionValueState, postProcessor);
if (postProcessor ===
connectionValueState.postProcessorState?.postProcessor) {
connectionValueState.postProcessorState.setPostProcessorState(undefined);
}
};
const postProcessorOptions = Object.values(POST_PROCESSOR_TYPE)
.concat(plugins.flatMap((plugin) => plugin.getExtraPostProcessorClassifiers?.() ?? []))
.map((type) => ({
value: type,
label: type,
}));
const addPostProcessor = (postProcessorType) => () => {
switch (postProcessorType) {
case POST_PROCESSOR_TYPE.MAPPER: {
relationalDatabaseConnection_addPostProcessor(connectionValueState, new MapperPostProcessor(), observerContext);
break;
}
default: {
const extraPostProcessorCreators = plugins.flatMap((plugin) => plugin.getExtraPostProcessorCreators?.() ?? []);
for (const creator of extraPostProcessorCreators) {
creator(postProcessorType, connectionValueState, observerContext);
}
}
}
connectionValueState.postProcessorState?.setPostProcessorState(connectionValueState.connection.postProcessors[connectionValueState.connection.postProcessors.length - 1]);
};
const selectPostProcessor = (postProcessor) => {
connectionValueState.selectPostProcessor(postProcessor);
};
const getPostProcessorLabel = (postProcessor) => {
if (postProcessor instanceof MapperPostProcessor) {
return POST_PROCESSOR_TYPE.MAPPER;
}
else {
const extraPostProcessorEditorClassifier = plugins.flatMap((plugin) => plugin.getExtraPostProcessorClassifierGetters?.() ?? []);
for (const classify of extraPostProcessorEditorClassifier) {
const label = classify(postProcessor);
if (label) {
return label;
}
}
}
return 'unknown type';
};
return (_jsx("div", { className: "relational-connection-editor", children: _jsxs(ResizablePanelGroup, { orientation: "horizontal", children: [_jsx(ResizablePanelSplitter, { children: _jsx(ResizablePanelSplitterLine, { color: "var(--color-dark-grey-200)" }) }), _jsx(ResizablePanel, { children: _jsx("div", { className: "relational-connection-editor__content", children: _jsxs(ResizablePanelGroup, { orientation: "vertical", children: [_jsx(ResizablePanel, { size: 200, minSize: 100, children: _jsxs(Panel, { children: [_jsx(PanelHeader, { title: "post-processor", children: _jsx(PanelHeaderActions, { children: _jsx(ControlledDropdownMenu, { title: "Create post-processor", className: "panel__header__action", disabled: isReadOnly, content: postProcessorOptions.map((postProcessorType) => (_jsxs(MenuContentItem, { onClick: addPostProcessor(postProcessorType.value), children: ["New ", postProcessorType.label, " Post-Processor"] }, postProcessorType.value))), menuProps: {
anchorOrigin: {
vertical: 'bottom',
horizontal: 'right',
},
transformOrigin: {
vertical: 'top',
horizontal: 'right',
},
elevation: 7,
}, children: _jsx(PlusIcon, {}) }) }) }), _jsx(PanelContent, { children: postProcessors.map((postProcessor, idx) => (_jsx(ContextMenu, { disabled: isReadOnly, content: _jsx(MenuContent, { children: _jsx(MenuContentItem, { onClick: deletePostProcessor(postProcessor), children: "Delete" }) }), menuProps: { elevation: 7 }, children: _jsxs(PanelListSelectorItem, { onSelect: () => selectPostProcessor(postProcessor), isSelected: postProcessor ===
postProcessorState?.postProcessor, children: [_jsx(PanelListSelectorItemLabel, { title: `Post-Processor ${idx + 1}` }), _jsx(Badge, { className: "badge--right", title: getPostProcessorLabel(postProcessor) })] }) }, postProcessor._UUID))) })] }) }), _jsx(ResizablePanelSplitter, { children: _jsx(ResizablePanelSplitterLine, { color: "var(--color-dark-grey-200)" }) }), _jsxs(ResizablePanel, { children: [postProcessorState?.postProcessor &&
renderEditorPostProcessor(connectionValueState, postProcessorState.postProcessor, isReadOnly, plugins), !postProcessorState && (_jsx(BlankPanelContent, { children: !postProcessors.length
? 'Add a post-processor'
: 'Choose a post-processor to view' }))] })] }) }) })] }) }));
});
const renderDatasourceSpecificationEditor = (connection, isReadOnly, plugins) => {
const sourceSpec = connection.datasourceSpecification;
if (sourceSpec instanceof StaticDatasourceSpecification) {
return (_jsx(StaticDatasourceSpecificationEditor, { sourceSpec: sourceSpec, isReadOnly: isReadOnly }));
}
else if (sourceSpec instanceof EmbeddedH2DatasourceSpecification) {
return (_jsx(EmbeddedH2DatasourceSpecificationEditor, { sourceSpec: sourceSpec, isReadOnly: isReadOnly }));
}
else if (sourceSpec instanceof DatabricksDatasourceSpecification) {
return (_jsx(DatabricksDatasourceSpecificationEditor, { sourceSpec: sourceSpec, isReadOnly: isReadOnly }));
}
else if (sourceSpec instanceof SnowflakeDatasourceSpecification) {
return (_jsx(SnowflakeDatasourceSpecificationEditor, { sourceSpec: sourceSpec, isReadOnly: isReadOnly }));
}
else if (sourceSpec instanceof BigQueryDatasourceSpecification) {
return (_jsx(BigQueryDatasourceSpecificationEditor, { sourceSpec: sourceSpec, isReadOnly: isReadOnly }));
}
else if (sourceSpec instanceof RedshiftDatasourceSpecification) {
return (_jsx(RedshiftDatasourceSpecificationEditor, { sourceSpec: sourceSpec, isReadOnly: isReadOnly }));
}
else if (sourceSpec instanceof LocalH2DatasourceSpecification) {
return (_jsx(LocalH2DatasourceSpecificationEditor, { sourceSpec: sourceSpec, isReadOnly: isReadOnly }));
}
else if (sourceSpec instanceof SpannerDatasourceSpecification) {
return (_jsx(SpannerDatasourceSpecificationEditor, { sourceSpec: sourceSpec, isReadOnly: isReadOnly }));
}
else if (sourceSpec instanceof TrinoDatasourceSpecification) {
return (_jsx(TrinoDatasourceSpecificationEditor, { sourceSpec: sourceSpec, isReadOnly: isReadOnly }));
}
else {
const extraDatasourceSpecificationEditorRenderers = plugins.flatMap((plugin) => plugin.getExtraDatasourceSpecificationEditorRenderers?.() ?? []);
for (const editorRenderer of extraDatasourceSpecificationEditorRenderers) {
const editor = editorRenderer(sourceSpec, isReadOnly);
if (editor) {
return editor;
}
}
// TODO: create unsupported screen
return null;
}
};
const renderAuthenticationStrategyEditor = (connection, isReadOnly, plugins) => {
const authSpec = connection.authenticationStrategy;
if (authSpec instanceof DelegatedKerberosAuthenticationStrategy) {
return (_jsx(DelegatedKerberosAuthenticationStrategyEditor, { authSpec: authSpec, isReadOnly: isReadOnly }));
}
else if (authSpec instanceof SnowflakePublicAuthenticationStrategy) {
return (_jsx(SnowflakePublicAuthenticationStrategyEditor, { authSpec: authSpec, isReadOnly: isReadOnly }));
}
else if (authSpec instanceof ApiTokenAuthenticationStrategy) {
return (_jsx(ApiTokenAuthenticationStrategyEditor, { authSpec: authSpec, isReadOnly: isReadOnly }));
}
else if (authSpec instanceof OAuthAuthenticationStrategy) {
return (_jsx(OAuthAuthenticationStrategyEditor, { authSpec: authSpec, isReadOnly: isReadOnly }));
}
else if (authSpec instanceof UsernamePasswordAuthenticationStrategy) {
return (_jsx(UsernamePasswordAuthenticationStrategyEditor, { authSpec: authSpec, isReadOnly: isReadOnly }));
}
else if (authSpec instanceof MiddleTierUsernamePasswordAuthenticationStrategy) {
return (_jsx(MiddleTierUsernamePasswordAuthenticationStrategyEditor, { authSpec: authSpec, isReadOnly: isReadOnly }));
}
else if (authSpec instanceof GCPWorkloadIdentityFederationAuthenticationStrategy) {
return (_jsx(GCPWorkloadIdentityFederationAuthenticationStrategyEditor, { authSpec: authSpec, isReadOnly: isReadOnly }));
}
else if (authSpec instanceof TrinoDelegatedKerberosAuthenticationStrategy) {
return (_jsx(TrinoDelegatedKerberosAuthenticationStrategyEditor, { authSpec: authSpec, isReadOnly: isReadOnly }));
}
else {
const extraAuthenticationStrategyEditorRenderers = plugins.flatMap((plugin) => plugin.getExtraAuthenticationStrategyEditorRenderers?.() ?? []);
for (const editorRenderer of extraAuthenticationStrategyEditorRenderers) {
const editor = editorRenderer(authSpec, isReadOnly);
if (editor) {
return editor;
}
}
// TODO: create unsupported screen
return null;
}
};
export const RelationalConnectionGeneralEditor = observer((props) => {
const { connectionValueState, isReadOnly, hideHeader } = props;
const connection = connectionValueState.connection;
const editorStore = useEditorStore();
const applicationStore = editorStore.applicationStore;
const plugins = editorStore.pluginManager.getApplicationPlugins();
const databseTypeConfigs = connectionValueState.editorStore.graphState
.relationalDatabseTypeConfigurations;
const availableDbTypes = databseTypeConfigs?.length
? // Currently H2 Flow is not returned in relational configs. We will remove this once it is properly returned as a supported flow in engine
uniq([DatabaseType.H2, ...databseTypeConfigs.map((e) => e.type)])
: Object.values(DatabaseType);
const dbTypes = availableDbTypes.map((dbType) => ({
value: dbType,
label: dbType,
}));
const selectedDbType = {
value: connection.type,
label: connection.type,
};
const changeTimeOut = (event) => {
const val = event.target.value;
dBConnection_setQueryTimeOut(connection, val === '' ? undefined : parseInt(val, 10));
};
const onTypeChange = (val) => {
dBConnection_setType(connection, val?.value ?? DatabaseType.H2);
if (connectionValueState.selectedValidDatasources[0]) {
connectionValueState.changeDatasourceSpec(connectionValueState.selectedValidDatasources[0]);
}
if (connectionValueState.selectedValidAuthenticationStrategies[0]) {
connectionValueState.changeAuthenticationStrategy(connectionValueState.selectedValidAuthenticationStrategies[0]);
}
};
// source spec type
const sourceSpecOptions = connectionValueState.selectedValidDatasources.map((type) => ({
value: type,
label: prettyCONSTName(type),
}));
const selectedSourceSpec = (spec) => ({
label: prettyCONSTName(connectionValueState.selectedDatasourceSpecificationType(spec) ??
'Unknown'),
value: connectionValueState.selectedDatasourceSpecificationType(spec),
});
const onSourceSpecChange = (val) => {
if (val?.value) {
connectionValueState.changeDatasourceSpec(val.value);
}
};
// auth type
const authOptions = connectionValueState.selectedValidAuthenticationStrategies.map((type) => ({
value: type,
label: prettyCONSTName(type),
}));
const selectedAuth = (auth) => ({
label: prettyCONSTName(connectionValueState.selectedAuthenticationStrategyType(auth) ??
'Unknown'),
value: connectionValueState.selectedAuthenticationStrategyType(auth),
});
const onAuthStrategyChange = (val) => {
if (val?.value) {
connectionValueState.changeAuthenticationStrategy(val.value);
}
};
// HACKY:
if (connection.localMode) {
return (_jsx("div", { className: "relational-connection-editor", children: _jsxs(Panel, { children: [_jsx(PanelHeader, { title: "general" }), _jsx(PanelContent, { className: "relational-connection-editor__general", children: _jsxs(PanelFormSection, { children: [_jsx("div", { className: "panel__content__form__section__header__label", children: "Database Type" }), _jsx(CustomSelectorInput, { options: dbTypes, onChange: onTypeChange, value: selectedDbType, darkMode: !applicationStore.layoutService
.TEMPORARY__isLightColorThemeEnabled })] }) })] }) }));
}
return (_jsx("div", { className: "relational-connection-editor", children: _jsxs(ResizablePanelGroup, { orientation: "horizontal", children: [_jsx(ResizablePanel, { size: 200, minSize: 15, children: _jsxs(Panel, { children: [!hideHeader && _jsx(PanelHeader, { title: "general" }), _jsxs(PanelContent, { className: "relational-connection-editor__general", children: [_jsxs(PanelFormSection, { children: [_jsx("div", { className: "panel__content__form__section__header__label", children: "Database Type" }), _jsx(CustomSelectorInput, { options: dbTypes, onChange: onTypeChange, value: selectedDbType, darkMode: !applicationStore.layoutService
.TEMPORARY__isLightColorThemeEnabled })] }), _jsx(PanelFormBooleanField, { isReadOnly: isReadOnly, value: connection.quoteIdentifiers, name: "Quote identifiers", prompt: "Specifies whether to use double-quotes for SQL identifiers", update: (value) => dBConnection_setQuoteIdentifiers(connection, Boolean(value)) }), _jsxs("div", { className: "panel__content__form__section", children: [_jsx("div", { className: "panel__content__form__section__header__label", children: "Query timeout (in seconds)" }), _jsx("input", { className: "panel__content__form__section__input panel__content__form__section__number-input", spellCheck: false, type: "number", disabled: isReadOnly, value: connection.queryTimeOutInSeconds, onChange: changeTimeOut })] })] })] }) }), _jsx(ResizablePanelSplitter, {}), _jsx(ResizablePanel, { children: _jsx("div", { className: "relational-connection-editor__content", children: _jsxs(ResizablePanelGroup, { orientation: "vertical", children: [_jsx(ResizablePanel, { size: 450, minSize: 50, children: _jsxs("div", { className: "relational-connection-editor__auth", children: [_jsx(PanelHeader, { title: "datasource specification" }), _jsxs(PanelContent, { className: "relational-connection-editor__auth__content", children: [_jsxs(PanelFormSection, { children: [_jsx("div", { style: { width: '100%' }, children: _jsx("div", { style: { display: 'inline-block', width: '10px' }, className: "panel__content__form__section__header__label", children: "Datasource" }) }), _jsx(CustomSelectorInput, { options: sourceSpecOptions, onChange: onSourceSpecChange, value: selectedSourceSpec(connection.datasourceSpecification), darkMode: !applicationStore.layoutService
.TEMPORARY__isLightColorThemeEnabled })] }), _jsx(PanelDivider, {}), _jsx("div", { className: "relational-connection-editor__auth__properties", children: renderDatasourceSpecificationEditor(connection, isReadOnly, plugins) })] })] }) }), _jsx(ResizablePanelSplitter, {}), _jsx(ResizablePanel, { children: _jsxs("div", { className: "relational-connection-editor__source", children: [_jsx(PanelHeader, { title: "authentication strategy" }), _jsxs(PanelContent, { className: "relational-connection-editor__source__content", children: [_jsxs(PanelFormSection, { children: [_jsx("div", { style: { width: '100%' }, children: _jsx("div", { style: { display: 'inline-block', width: '10px' }, className: "panel__content__form__section__header__label", children: "Authentication" }) }), _jsx(CustomSelectorInput, { options: authOptions, onChange: onAuthStrategyChange, value: selectedAuth(connection.authenticationStrategy), darkMode: !applicationStore.layoutService
.TEMPORARY__isLightColorThemeEnabled })] }), _jsx(PanelDivider, {}), _jsx("div", { className: "relational-connection-editor__source__properties", children: renderAuthenticationStrategyEditor(connection, isReadOnly, plugins) })] })] }) })] }) }) })] }) }));
});
export const RelationalDatabaseConnectionEditor = observer((props) => {
const { connectionValueState, isReadOnly } = props;
const selectedTab = connectionValueState.selectedTab;
const changeTab = (tab) => () => {
connectionValueState.setSelectedTab(tab);
};
return (_jsxs(Panel, { children: [_jsx(PanelTabs, { tabs: Object.values(RELATIONAL_DATABASE_TAB_TYPE), changeTab: changeTab, selectedTab: selectedTab, tabClassName: "relational-connection-editor__tab" }), _jsxs(PanelContent, { children: [selectedTab === RELATIONAL_DATABASE_TAB_TYPE.GENERAL && (_jsx(RelationalConnectionGeneralEditor, { connectionValueState: connectionValueState, isReadOnly: isReadOnly })), selectedTab === RELATIONAL_DATABASE_TAB_TYPE.STORE && (_jsx(RelationalConnectionStoreEditor, { connectionValueState: connectionValueState, isReadOnly: isReadOnly })), selectedTab === RELATIONAL_DATABASE_TAB_TYPE.POST_PROCESSORS && (_jsx(PostProcessorRelationalConnectionEditor, { connectionValueState: connectionValueState, isReadOnly: isReadOnly }))] })] }));
});
//# sourceMappingURL=RelationalDatabaseConnectionEditor.js.map