|
@@ -0,0 +1,552 @@
|
|
|
+/*
|
|
|
+ * <<
|
|
|
+ * Davinci
|
|
|
+ * ==
|
|
|
+ * Copyright (C) 2016 - 2017 EDP
|
|
|
+ * ==
|
|
|
+ * 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 React from 'react'
|
|
|
+import { compose, Dispatch } from 'redux'
|
|
|
+import { connect } from 'react-redux'
|
|
|
+import { createStructuredSelector } from 'reselect'
|
|
|
+import memoizeOne from 'memoize-one'
|
|
|
+import Helmet from 'react-helmet'
|
|
|
+
|
|
|
+import injectReducer from 'utils/injectReducer'
|
|
|
+import injectSaga from 'utils/injectSaga'
|
|
|
+import reducer from './reducer'
|
|
|
+import sagas from './sagas'
|
|
|
+import reducerSource from 'containers/Source/reducer'
|
|
|
+import sagasSource from 'containers/Source/sagas'
|
|
|
+import reducerProject from 'containers/Projects/reducer'
|
|
|
+import sagasProject from 'containers/Projects/sagas'
|
|
|
+
|
|
|
+import { RouteComponentWithParams } from 'utils/types'
|
|
|
+import { hideNavigator } from '../App/actions'
|
|
|
+import { ViewActions, ViewActionType } from './actions'
|
|
|
+import { SourceActions, SourceActionType } from 'containers/Source/actions'
|
|
|
+import { OrganizationActions, OrganizationActionType } from 'containers/Organizations/actions'
|
|
|
+
|
|
|
+import {
|
|
|
+ makeSelectEditingView,
|
|
|
+ makeSelectEditingViewInfo,
|
|
|
+ makeSelectSources,
|
|
|
+ makeSelectSchema,
|
|
|
+ makeSelectSqlDataSource,
|
|
|
+ makeSelectSqlLimit,
|
|
|
+ makeSelectSqlValidation,
|
|
|
+ makeSelectLoading,
|
|
|
+
|
|
|
+ makeSelectChannels,
|
|
|
+ makeSelectTenants,
|
|
|
+ makeSelectBizs,
|
|
|
+ makeSelectIsLastExecuteWholeSql
|
|
|
+} from './selectors'
|
|
|
+
|
|
|
+import { makeSelectProjectRoles } from 'containers/Projects/selectors'
|
|
|
+
|
|
|
+import {
|
|
|
+ IView, IViewModel, IViewRoleRaw, IViewRole, IViewVariable, IViewInfo,
|
|
|
+ IExecuteSqlParams, IExecuteSqlResponse, IViewLoading, ISqlValidation,
|
|
|
+ IDacChannel, IDacTenant, IDacBiz
|
|
|
+} from './types'
|
|
|
+import { ISource, ISchema } from '../Source/types'
|
|
|
+import { ViewVariableTypes } from './constants'
|
|
|
+
|
|
|
+import { message, notification, Tooltip } from 'antd'
|
|
|
+import EditorSteps from './components/EditorSteps'
|
|
|
+import EditorContainer from './components/EditorContainer'
|
|
|
+import ModelAuth from './components/ModelAuth'
|
|
|
+import SourceTable from './components/SourceTable'
|
|
|
+import SqlEditor from './components/SqlEditorByAce'
|
|
|
+import SqlPreview from './components/SqlPreview'
|
|
|
+import EditorBottom from './components/EditorBottom'
|
|
|
+import ViewVariableList from './components/ViewVariableList'
|
|
|
+import VariableModal from './components/VariableModal'
|
|
|
+
|
|
|
+import Styles from './View.less'
|
|
|
+
|
|
|
+interface IViewEditorStateProps {
|
|
|
+ editingView: IView
|
|
|
+ editingViewInfo: IViewInfo
|
|
|
+ sources: ISource[]
|
|
|
+ schema: ISchema
|
|
|
+ sqlDataSource: IExecuteSqlResponse
|
|
|
+ sqlLimit: number
|
|
|
+ sqlValidation: ISqlValidation
|
|
|
+ loading: IViewLoading
|
|
|
+ projectRoles: any[]
|
|
|
+
|
|
|
+ channels: IDacChannel[]
|
|
|
+ tenants: IDacTenant[]
|
|
|
+ bizs: IDacBiz[],
|
|
|
+
|
|
|
+ isLastExecuteWholeSql: boolean
|
|
|
+}
|
|
|
+
|
|
|
+export enum EExecuteType {
|
|
|
+ whole,
|
|
|
+ single
|
|
|
+}
|
|
|
+
|
|
|
+interface IViewEditorDispatchProps {
|
|
|
+ onHideNavigator: () => void
|
|
|
+ onLoadViewDetail: (viewId: number) => void
|
|
|
+ onLoadSources: (projectId: number) => void
|
|
|
+ onLoadSourceDatabases: (sourceId: number) => void
|
|
|
+ onLoadDatabaseTables: (sourceId: number, databaseName: string) => void
|
|
|
+ onLoadTableColumns: (sourceId: number, databaseName: string, tableName: string) => void
|
|
|
+ onExecuteSql: (params: IExecuteSqlParams, exeType: EExecuteType) => void
|
|
|
+ onAddView: (view: IView, resolve: () => void) => void
|
|
|
+ onEditView: (view: IView, resolve: () => void) => void
|
|
|
+ onUpdateEditingView: (view: IView) => void
|
|
|
+ onUpdateEditingViewInfo: (viewInfo: IViewInfo) => void
|
|
|
+ onSetSqlLimit: (limit: number) => void
|
|
|
+
|
|
|
+ onLoadDacChannels: () => void,
|
|
|
+ onLoadDacTenants: (channelName: string) => void,
|
|
|
+ onLoadDacBizs: (channelName: string, tenantId: number) => void,
|
|
|
+
|
|
|
+ onResetState: () => void
|
|
|
+ onLoadProjectRoles: (projectId: number) => void
|
|
|
+ onSetIsLastExecuteWholeSql: (isLastExecuteWholeSql: boolean) => void
|
|
|
+}
|
|
|
+
|
|
|
+type IViewEditorProps = IViewEditorStateProps & IViewEditorDispatchProps & RouteComponentWithParams
|
|
|
+
|
|
|
+interface IViewEditorStates {
|
|
|
+ containerHeight: number
|
|
|
+ sqlValidationCode: number
|
|
|
+ init: boolean
|
|
|
+ currentStep: number
|
|
|
+ lastSuccessExecutedSql: string
|
|
|
+ sqlFragment: string
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+export class ViewEditor extends React.Component<IViewEditorProps, IViewEditorStates> {
|
|
|
+
|
|
|
+ public state: Readonly<IViewEditorStates> = {
|
|
|
+ containerHeight: 0,
|
|
|
+ currentStep: 0,
|
|
|
+ sqlValidationCode: null,
|
|
|
+ init: true,
|
|
|
+ lastSuccessExecutedSql: null,
|
|
|
+ sqlFragment: ''
|
|
|
+ }
|
|
|
+
|
|
|
+ public constructor(props: IViewEditorProps) {
|
|
|
+ super(props)
|
|
|
+ const {
|
|
|
+ onHideNavigator,
|
|
|
+ onLoadSources,
|
|
|
+ onLoadViewDetail,
|
|
|
+ onLoadProjectRoles,
|
|
|
+ onLoadDacChannels,
|
|
|
+ match
|
|
|
+ } = this.props
|
|
|
+ onHideNavigator()
|
|
|
+ const { viewId, projectId } = match.params
|
|
|
+ if (projectId) {
|
|
|
+ onLoadSources(+projectId)
|
|
|
+ onLoadProjectRoles(+projectId)
|
|
|
+ }
|
|
|
+ if (viewId) {
|
|
|
+ onLoadViewDetail(+viewId)
|
|
|
+ }
|
|
|
+ onLoadDacChannels()
|
|
|
+ }
|
|
|
+
|
|
|
+ public static getDerivedStateFromProps:
|
|
|
+ React.GetDerivedStateFromProps<IViewEditorProps, IViewEditorStates>
|
|
|
+ = (props, state) => {
|
|
|
+ const { match, editingView, sqlValidation } = props
|
|
|
+ const { viewId } = match.params
|
|
|
+ const { init, sqlValidationCode } = state
|
|
|
+ let { lastSuccessExecutedSql } = state
|
|
|
+ if (sqlValidationCode !== sqlValidation.code && sqlValidation.code) {
|
|
|
+ notification.destroy()
|
|
|
+ sqlValidation.code === 200
|
|
|
+ ? notification.success({
|
|
|
+ message: '执行成功',
|
|
|
+ duration: 3
|
|
|
+ })
|
|
|
+ : notification.error({
|
|
|
+ message: '执行失败',
|
|
|
+ description: (
|
|
|
+ <Tooltip
|
|
|
+ placement='bottom'
|
|
|
+ trigger='click'
|
|
|
+ title={sqlValidation.message}
|
|
|
+ overlayClassName={Styles.errorMessage}
|
|
|
+ >
|
|
|
+ <a>点击查看错误信息</a>
|
|
|
+ </Tooltip>
|
|
|
+ ),
|
|
|
+ duration: null
|
|
|
+ })
|
|
|
+ if (sqlValidation.code === 200) {
|
|
|
+ lastSuccessExecutedSql = editingView.sql
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (editingView && editingView.id === +viewId) {
|
|
|
+ if (init) {
|
|
|
+ props.onLoadSourceDatabases(editingView.sourceId)
|
|
|
+ lastSuccessExecutedSql = editingView.sql
|
|
|
+ return {
|
|
|
+ init: false,
|
|
|
+ sqlValidationCode: sqlValidation.code,
|
|
|
+ lastSuccessExecutedSql
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return { sqlValidationCode: sqlValidation.code, lastSuccessExecutedSql }
|
|
|
+ }
|
|
|
+
|
|
|
+ public componentWillUnmount() {
|
|
|
+ this.props.onResetState()
|
|
|
+ notification.destroy()
|
|
|
+ }
|
|
|
+
|
|
|
+ private executeSql = () => {
|
|
|
+ const { sqlFragment } = this.state
|
|
|
+ const { onSetIsLastExecuteWholeSql } = this.props
|
|
|
+ if (sqlFragment != null) {
|
|
|
+ onSetIsLastExecuteWholeSql(false)
|
|
|
+ }
|
|
|
+ ViewEditor.ExecuteSql(this.props, this.state.sqlFragment)
|
|
|
+ }
|
|
|
+
|
|
|
+ private static ExecuteSql = (props: IViewEditorProps, sqlFragment?: string) => {
|
|
|
+ const { onExecuteSql, editingView, editingViewInfo, sqlLimit } = props
|
|
|
+ const { sourceId, sql } = editingView
|
|
|
+ const { variable } = editingViewInfo
|
|
|
+ const updatedParams: IExecuteSqlParams = {
|
|
|
+ sourceId,
|
|
|
+ sql: sqlFragment ?? sql,
|
|
|
+ limit: sqlLimit,
|
|
|
+ variables: variable
|
|
|
+ }
|
|
|
+ const exeType = sqlFragment == null ? EExecuteType.whole : EExecuteType.single
|
|
|
+ onExecuteSql(updatedParams, exeType)
|
|
|
+ }
|
|
|
+
|
|
|
+ private stepChange = (step: number) => {
|
|
|
+ const { currentStep } = this.state
|
|
|
+ if (currentStep + step < 0) {
|
|
|
+ this.goToViewList()
|
|
|
+ return
|
|
|
+ }
|
|
|
+ const { editingView } = this.props
|
|
|
+ const { name, sourceId, sql } = editingView
|
|
|
+ const errorMessages = ['名称不能为空', '请选择数据源', 'sql 不能为空']
|
|
|
+ const fieldsValue = [name, sourceId, sql]
|
|
|
+ const hasError = fieldsValue.some((val, idx) => {
|
|
|
+ if (!val) {
|
|
|
+ message.error(errorMessages[idx])
|
|
|
+ return true
|
|
|
+ }
|
|
|
+ })
|
|
|
+ if (hasError) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ this.setState({ currentStep: currentStep + step }, () => {
|
|
|
+ if (this.state.currentStep > 1) {
|
|
|
+ this.saveView()
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ private saveView = () => {
|
|
|
+ const { onAddView, onEditView, editingView, editingViewInfo, projectRoles, match } = this.props
|
|
|
+ const { projectId } = match.params
|
|
|
+ const { model, variable, roles } = editingViewInfo
|
|
|
+ const { id: viewId } = editingView
|
|
|
+ const validRoles = roles.filter(({ roleId }) => projectRoles && projectRoles.findIndex(({ id }) => id === roleId) >= 0)
|
|
|
+ const updatedView: IView = {
|
|
|
+ ...editingView,
|
|
|
+ projectId: +projectId,
|
|
|
+ model: JSON.stringify(model),
|
|
|
+ variable: JSON.stringify(variable),
|
|
|
+ roles: validRoles.map<IViewRoleRaw>(({ roleId, columnAuth, rowAuth }) => {
|
|
|
+ const validColumnAuth = columnAuth.filter((c) => !!model[c])
|
|
|
+ const validRowAuth = rowAuth.filter((r) => {
|
|
|
+ const v = variable.find((v) => v.name === r.name)
|
|
|
+ if (!v) {
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ return (v.type === ViewVariableTypes.Authorization && !v.fromService)
|
|
|
+ })
|
|
|
+ return {
|
|
|
+ roleId,
|
|
|
+ columnAuth: JSON.stringify(validColumnAuth),
|
|
|
+ rowAuth: JSON.stringify(validRowAuth)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+ viewId ? onEditView(updatedView, this.goToViewList) : onAddView(updatedView, this.goToViewList)
|
|
|
+ }
|
|
|
+
|
|
|
+ private goToViewList = () => {
|
|
|
+ const { history, match } = this.props
|
|
|
+ const { projectId } = match.params
|
|
|
+ const prefix = window.localStorage.getItem('inDataService') ?? ''
|
|
|
+ const prefixPath = prefix ? '/' + prefix : prefix
|
|
|
+ history.push(`/project/${projectId}${prefixPath}/views`)
|
|
|
+ }
|
|
|
+
|
|
|
+ private viewChange = (propName: keyof IView, value: string | number) => {
|
|
|
+ const { editingView, onUpdateEditingView } = this.props
|
|
|
+ const updatedView = {
|
|
|
+ ...editingView,
|
|
|
+ [propName]: value
|
|
|
+ }
|
|
|
+ onUpdateEditingView(updatedView)
|
|
|
+ }
|
|
|
+
|
|
|
+ private sqlChange = (sql: string) => {
|
|
|
+ this.viewChange('sql', sql)
|
|
|
+ }
|
|
|
+
|
|
|
+ private sqlSelect = (sqlFragment: string) => {
|
|
|
+ this.setState({ sqlFragment })
|
|
|
+ }
|
|
|
+
|
|
|
+ private modelChange = (partialModel: IViewModel) => {
|
|
|
+ const { editingViewInfo, onUpdateEditingViewInfo } = this.props
|
|
|
+ const { model } = editingViewInfo
|
|
|
+ const updatedViewInfo: IViewInfo = {
|
|
|
+ ...editingViewInfo,
|
|
|
+ model: { ...model, ...partialModel }
|
|
|
+ }
|
|
|
+ onUpdateEditingViewInfo(updatedViewInfo)
|
|
|
+ }
|
|
|
+
|
|
|
+ private variableChange = (updatedVariable: IViewVariable[]) => {
|
|
|
+ const { editingViewInfo, onUpdateEditingViewInfo } = this.props
|
|
|
+ const updatedViewInfo: IViewInfo = {
|
|
|
+ ...editingViewInfo,
|
|
|
+ variable: updatedVariable
|
|
|
+ }
|
|
|
+ onUpdateEditingViewInfo(updatedViewInfo)
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 数组长度1为单选,大于1为全选
|
|
|
+ * @param {IViewRole[]} viewRoles
|
|
|
+ * @private
|
|
|
+ * @memberof ViewEditor
|
|
|
+ */
|
|
|
+ private viewRoleChange = (viewRoles: IViewRole[]) => {
|
|
|
+ const { editingViewInfo, onUpdateEditingViewInfo } = this.props
|
|
|
+ let updatedRoles: IViewRole[] = []
|
|
|
+ if (viewRoles.length === 1) {
|
|
|
+ const [viewRole] = viewRoles
|
|
|
+ const { roles } = editingViewInfo
|
|
|
+ updatedRoles = roles.filter((role) => role.roleId !== viewRole.roleId)
|
|
|
+ updatedRoles.push(viewRole)
|
|
|
+ } else {
|
|
|
+ updatedRoles = viewRoles
|
|
|
+ }
|
|
|
+ const updatedViewInfo = {
|
|
|
+ ...editingViewInfo,
|
|
|
+ roles: updatedRoles
|
|
|
+ }
|
|
|
+ onUpdateEditingViewInfo(updatedViewInfo)
|
|
|
+ }
|
|
|
+
|
|
|
+ private getSqlHints = memoizeOne((sourceId: number, schema: ISchema, variables: IViewVariable[]) => {
|
|
|
+ if (!sourceId) {
|
|
|
+ return {}
|
|
|
+ }
|
|
|
+
|
|
|
+ const variableHints = variables.reduce((acc, v) => {
|
|
|
+ acc[`$${v.name}$`] = []
|
|
|
+ return acc
|
|
|
+ }, {})
|
|
|
+ const { mapDatabases, mapTables, mapColumns } = schema
|
|
|
+ if (!mapDatabases[sourceId]) {
|
|
|
+ return {}
|
|
|
+ }
|
|
|
+
|
|
|
+ const tableHints: { [tableName: string]: string[] } = Object.values(mapTables).reduce((acc, tablesInfo) => {
|
|
|
+ if (tablesInfo.sourceId !== sourceId) {
|
|
|
+ return acc
|
|
|
+ }
|
|
|
+
|
|
|
+ tablesInfo.tables.forEach(({ name: tableName }) => {
|
|
|
+ acc[tableName] = []
|
|
|
+ })
|
|
|
+ return acc
|
|
|
+ }, {})
|
|
|
+
|
|
|
+ Object.values(mapColumns).forEach((columnsInfo) => {
|
|
|
+ if (columnsInfo.sourceId !== sourceId) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ const { tableName, columns } = columnsInfo
|
|
|
+ if (tableHints[tableName]) {
|
|
|
+ tableHints[tableName] = tableHints[tableName].concat(columns.map((col) => col.name))
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ const hints = {
|
|
|
+ ...variableHints,
|
|
|
+ ...tableHints
|
|
|
+ }
|
|
|
+ return hints
|
|
|
+ })
|
|
|
+
|
|
|
+ public render() {
|
|
|
+ const {
|
|
|
+ sources, schema,
|
|
|
+ sqlDataSource, sqlLimit, loading, projectRoles,
|
|
|
+ channels, tenants, bizs,
|
|
|
+ editingView, editingViewInfo,
|
|
|
+ isLastExecuteWholeSql,
|
|
|
+ onLoadSourceDatabases, onLoadDatabaseTables, onLoadTableColumns, onSetSqlLimit,
|
|
|
+ onLoadDacTenants, onLoadDacBizs
|
|
|
+ } = this.props
|
|
|
+ const { currentStep, lastSuccessExecutedSql, sqlFragment } = this.state
|
|
|
+ const { model, variable, roles: viewRoles } = editingViewInfo
|
|
|
+ const sqlHints = this.getSqlHints(editingView.sourceId, schema, variable)
|
|
|
+ const containerVisible = !currentStep
|
|
|
+ const modelAuthVisible = !!currentStep
|
|
|
+ const nextDisabled = (editingView.sql !== lastSuccessExecutedSql)
|
|
|
+
|
|
|
+ return (
|
|
|
+ <>
|
|
|
+ <Helmet title='数据资产' />
|
|
|
+ <div className={Styles.viewEditor}>
|
|
|
+ <div className={Styles.header}>
|
|
|
+ <div className={Styles.steps}>
|
|
|
+ <EditorSteps current={currentStep} />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <EditorContainer
|
|
|
+ visible={containerVisible}
|
|
|
+ variable={variable}
|
|
|
+ onVariableChange={this.variableChange}
|
|
|
+ >
|
|
|
+ <SourceTable
|
|
|
+ key='SourceTable'
|
|
|
+ view={editingView}
|
|
|
+ sources={sources}
|
|
|
+ schema={schema}
|
|
|
+ onViewChange={this.viewChange}
|
|
|
+ onSourceSelect={onLoadSourceDatabases}
|
|
|
+ onDatabaseSelect={onLoadDatabaseTables}
|
|
|
+ onTableSelect={onLoadTableColumns}
|
|
|
+ />
|
|
|
+ <SqlEditor key='SqlEditor' value={editingView.sql} hints={sqlHints} onSqlChange={this.sqlChange}
|
|
|
+ onSelect={this.sqlSelect} onCmdEnter={this.executeSql} />
|
|
|
+ <SqlPreview key='SqlPreview' size='small' loading={loading.execute} response={sqlDataSource} />
|
|
|
+ <EditorBottom
|
|
|
+ key='EditorBottom'
|
|
|
+ sqlLimit={sqlLimit}
|
|
|
+ loading={loading.execute}
|
|
|
+ nextDisabled={nextDisabled}
|
|
|
+ sqlFragment={sqlFragment}
|
|
|
+ isLastExecuteWholeSql={isLastExecuteWholeSql}
|
|
|
+ onSetSqlLimit={onSetSqlLimit}
|
|
|
+ onExecuteSql={this.executeSql}
|
|
|
+ onStepChange={this.stepChange}
|
|
|
+ />
|
|
|
+ <ViewVariableList key='ViewVariableList' variables={variable} />
|
|
|
+ <VariableModal
|
|
|
+ key='VariableModal'
|
|
|
+ channels={channels}
|
|
|
+ tenants={tenants}
|
|
|
+ bizs={bizs}
|
|
|
+ onLoadDacTenants={onLoadDacTenants}
|
|
|
+ onLoadDacBizs={onLoadDacBizs}
|
|
|
+ />
|
|
|
+ </EditorContainer>
|
|
|
+ <ModelAuth
|
|
|
+ visible={modelAuthVisible}
|
|
|
+ model={model}
|
|
|
+ variable={variable}
|
|
|
+ sqlColumns={sqlDataSource.columns}
|
|
|
+ roles={projectRoles}
|
|
|
+ viewRoles={viewRoles}
|
|
|
+ onModelChange={this.modelChange}
|
|
|
+ onViewRoleChange={this.viewRoleChange}
|
|
|
+ onStepChange={this.stepChange}
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </>
|
|
|
+ )
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+const mapDispatchToProps = (dispatch) => ({
|
|
|
+ onHideNavigator: () => dispatch(hideNavigator()),
|
|
|
+ onLoadViewDetail: (viewId: number) => dispatch(ViewActions.loadViewsDetail([viewId], null, true)),
|
|
|
+ onLoadSources: (projectId) => dispatch(SourceActions.loadSources(projectId)),
|
|
|
+ onLoadSourceDatabases: (sourceId) => dispatch(SourceActions.loadSourceDatabases(sourceId)),
|
|
|
+ onLoadDatabaseTables: (sourceId, databaseName) => dispatch(SourceActions.loadDatabaseTables(sourceId, databaseName)),
|
|
|
+ onLoadTableColumns: (sourceId, databaseName, tableName) => dispatch(SourceActions.loadTableColumns(sourceId, databaseName, tableName)),
|
|
|
+ onExecuteSql: (params, exeType?) => dispatch(ViewActions.executeSql(params, exeType)),
|
|
|
+ onSetIsLastExecuteWholeSql: (isLastExecuteWholeSql: boolean) => dispatch(ViewActions.setIsLastExecuteWholeSql(isLastExecuteWholeSql)),
|
|
|
+ onAddView: (view, resolve) => dispatch(ViewActions.addView(view, resolve)),
|
|
|
+ onEditView: (view, resolve) => dispatch(ViewActions.editView(view, resolve)),
|
|
|
+ onUpdateEditingView: (view) => dispatch(ViewActions.updateEditingView(view)),
|
|
|
+ onUpdateEditingViewInfo: (viewInfo: IViewInfo) => dispatch(ViewActions.updateEditingViewInfo(viewInfo)),
|
|
|
+ onSetSqlLimit: (limit: number) => dispatch(ViewActions.setSqlLimit(limit)),
|
|
|
+
|
|
|
+ onLoadDacChannels: () => dispatch(ViewActions.loadDacChannels()),
|
|
|
+ onLoadDacTenants: (channelName) => dispatch(ViewActions.loadDacTenants(channelName)),
|
|
|
+ onLoadDacBizs: (channelName, tenantId) => dispatch(ViewActions.loadDacBizs(channelName, tenantId)),
|
|
|
+
|
|
|
+ onResetState: () => dispatch(ViewActions.resetViewState()),
|
|
|
+ onLoadProjectRoles: (projectId) => dispatch(OrganizationActions.loadProjectRoles(projectId))
|
|
|
+})
|
|
|
+
|
|
|
+const mapStateToProps = createStructuredSelector({
|
|
|
+ editingView: makeSelectEditingView(),
|
|
|
+ editingViewInfo: makeSelectEditingViewInfo(),
|
|
|
+ sources: makeSelectSources(),
|
|
|
+ schema: makeSelectSchema(),
|
|
|
+ sqlDataSource: makeSelectSqlDataSource(),
|
|
|
+ sqlLimit: makeSelectSqlLimit(),
|
|
|
+ sqlValidation: makeSelectSqlValidation(),
|
|
|
+ loading: makeSelectLoading(),
|
|
|
+ projectRoles: makeSelectProjectRoles(),
|
|
|
+
|
|
|
+ channels: makeSelectChannels(),
|
|
|
+ tenants: makeSelectTenants(),
|
|
|
+ bizs: makeSelectBizs(),
|
|
|
+
|
|
|
+ isLastExecuteWholeSql: makeSelectIsLastExecuteWholeSql()
|
|
|
+})
|
|
|
+
|
|
|
+const withConnect = connect(mapStateToProps, mapDispatchToProps)
|
|
|
+const withReducer = injectReducer({ key: 'view', reducer })
|
|
|
+const withSaga = injectSaga({ key: 'view', saga: sagas })
|
|
|
+const withReducerSource = injectReducer({ key: 'source', reducer: reducerSource })
|
|
|
+const withSagaSource = injectSaga({ key: 'source', saga: sagasSource })
|
|
|
+const withReducerProject = injectReducer({ key: 'project', reducer: reducerProject })
|
|
|
+const withSagaProject = injectSaga({ key: 'project', saga: sagasProject })
|
|
|
+
|
|
|
+export default compose(
|
|
|
+ withReducer,
|
|
|
+ withReducerSource,
|
|
|
+ withSaga,
|
|
|
+ withSagaSource,
|
|
|
+ withReducerProject,
|
|
|
+ withSagaProject,
|
|
|
+ withConnect
|
|
|
+)(ViewEditor)
|