reducer.ts 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. /*
  2. * <<
  3. * Davinci
  4. * ==
  5. * Copyright (C) 2016 - 2017 EDP
  6. * ==
  7. * Licensed under the Apache License, Version 2.0 (the "License");
  8. * you may not use this file except in compliance with the License.
  9. * You may obtain a copy of the License at
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  13. * Unless required by applicable law or agreed to in writing, software
  14. * distributed under the License is distributed on an "AS IS" BASIS,
  15. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  16. * See the License for the specific language governing permissions and
  17. * limitations under the License.
  18. * >>
  19. */
  20. import produce from 'immer'
  21. import pick from 'lodash/pick'
  22. import { IViewState, IView, IFormedViews, IViewBase } from './types'
  23. import { getFormedView, getValidModel } from './util'
  24. import { ActionTypes, DEFAULT_SQL_LIMIT } from './constants'
  25. import { ViewActionType } from './actions'
  26. import { ActionTypes as SourceActionTypes } from 'containers/Source/constants'
  27. import { SourceActionType } from 'containers/Source/actions'
  28. import { ActionTypes as WidgetActionTypes } from 'containers/Widget/constants'
  29. import { WidgetActionType } from 'containers/Widget/actions'
  30. import { ActionTypes as DashboardActionTypes } from 'containers/Dashboard/constants'
  31. import { DashboardActionType } from 'containers/Dashboard/actions'
  32. import { ActionTypes as DisplayActionTypes } from 'containers/Display/constants'
  33. import { DisplayActionType } from 'containers/Display/actions'
  34. import { LOCATION_CHANGE, LocationChangeAction } from 'connected-react-router'
  35. const emptyView: IView = {
  36. id: null,
  37. name: '',
  38. sql: '',
  39. model: '',
  40. variable: '',
  41. roles: [],
  42. config: '',
  43. description: '',
  44. projectId: null,
  45. sourceId: null
  46. }
  47. const initialState: IViewState = {
  48. views: [],
  49. formedViews: {},
  50. editingView: emptyView,
  51. editingViewInfo: {
  52. model: {},
  53. variable: [],
  54. roles: []
  55. },
  56. sources: [],
  57. schema: {
  58. mapDatabases: {},
  59. mapTables: {},
  60. mapColumns: {}
  61. },
  62. sqlValidation: {
  63. code: null,
  64. message: null
  65. },
  66. sqlDataSource: {
  67. columns: [],
  68. totalCount: 0,
  69. resultList: []
  70. },
  71. sqlLimit: DEFAULT_SQL_LIMIT,
  72. loading: {
  73. view: false,
  74. table: false,
  75. modal: false,
  76. execute: false,
  77. copy: false
  78. },
  79. channels: [],
  80. tenants: [],
  81. bizs: [],
  82. cancelTokenSources: [],
  83. isLastExecuteWholeSql: true
  84. }
  85. const viewReducer = (
  86. state = initialState,
  87. action:
  88. | ViewActionType
  89. | WidgetActionType
  90. | DashboardActionType
  91. | DisplayActionType
  92. | SourceActionType
  93. | LocationChangeAction
  94. ): IViewState =>
  95. produce(state, (draft) => {
  96. switch (action.type) {
  97. case ActionTypes.LOAD_VIEWS:
  98. case ActionTypes.DELETE_VIEW:
  99. draft.loading.view = true
  100. break
  101. case ActionTypes.LOAD_VIEWS_FAILURE:
  102. case ActionTypes.DELETE_VIEW_FAILURE:
  103. draft.loading.view = false
  104. break
  105. case ActionTypes.LOAD_VIEWS_SUCCESS:
  106. draft.views = action.payload.views
  107. draft.formedViews = Object.entries(draft.formedViews).reduce(
  108. (obj, [viewId, formedView]) => {
  109. const existView = action.payload.views.find(
  110. (v) => v.id === Number(viewId)
  111. )
  112. if (existView) {
  113. obj[viewId] = formedView
  114. }
  115. return obj
  116. },
  117. {}
  118. )
  119. draft.loading.view = false
  120. break
  121. case ActionTypes.LOAD_VIEWS_DETAIL:
  122. draft.formedViews = action.payload.viewIds.reduce((acc, id) => {
  123. if (!acc[id]) {
  124. acc[id] = {
  125. id,
  126. name: '',
  127. description: '',
  128. sql: '',
  129. config: '',
  130. sourceId: 0,
  131. projectId: 0,
  132. model: {},
  133. variable: [],
  134. roles: []
  135. }
  136. }
  137. return acc
  138. }, draft.formedViews)
  139. break
  140. case ActionTypes.LOAD_VIEWS_DETAIL_SUCCESS:
  141. const detailedViews = action.payload.views
  142. if (action.payload.isEditing) {
  143. draft.editingView = detailedViews[0]
  144. draft.editingViewInfo = pick(getFormedView(detailedViews[0]), [
  145. 'model',
  146. 'variable',
  147. 'roles'
  148. ])
  149. }
  150. draft.formedViews = detailedViews.reduce((acc, view) => {
  151. const { id, model, variable, roles } = getFormedView(view)
  152. acc[id] = {
  153. ...view,
  154. model,
  155. variable,
  156. roles
  157. }
  158. return acc
  159. }, draft.formedViews)
  160. break
  161. case SourceActionTypes.LOAD_SOURCES_SUCCESS:
  162. draft.sources = action.payload.sources
  163. draft.schema = {
  164. mapDatabases: {},
  165. mapTables: {},
  166. mapColumns: {}
  167. }
  168. break
  169. case SourceActionTypes.LOAD_SOURCE_DATABASES_SUCCESS:
  170. const { sourceDatabases } = action.payload
  171. draft.schema.mapDatabases[sourceDatabases.sourceId] =
  172. sourceDatabases.databases
  173. break
  174. case SourceActionTypes.LOAD_SOURCE_DATABASE_TABLES_SUCCESS:
  175. const { databaseTables } = action.payload
  176. draft.schema.mapTables[
  177. `${databaseTables.sourceId}_${databaseTables.dbName}`
  178. ] = databaseTables
  179. break
  180. case SourceActionTypes.LOAD_SOURCE_TABLE_COLUMNS_SUCCESS:
  181. const { databaseName, tableColumns } = action.payload
  182. draft.schema.mapColumns[
  183. `${tableColumns.sourceId}_${databaseName}_${tableColumns.tableName}`
  184. ] = tableColumns
  185. break
  186. case ActionTypes.IS_LAST_EXECUTE_WHOLE_SQL:
  187. draft.isLastExecuteWholeSql = action.payload.isLastExecuteWholeSql
  188. break
  189. case ActionTypes.EXECUTE_SQL:
  190. draft.loading.execute = true
  191. draft.sqlValidation = { code: null, message: null }
  192. break
  193. case ActionTypes.EXECUTE_SQL_SUCCESS:
  194. const sqlResponse = action.payload.result
  195. const validModel = getValidModel(
  196. draft.editingViewInfo.model,
  197. sqlResponse.payload.columns
  198. )
  199. draft.sqlDataSource = sqlResponse.payload
  200. draft.editingViewInfo.model = validModel
  201. draft.loading.execute = false
  202. draft.sqlValidation = {
  203. code: sqlResponse.header.code,
  204. message: sqlResponse.header.msg
  205. }
  206. break
  207. case ActionTypes.EXECUTE_SQL_FAILURE:
  208. draft.sqlDataSource = {
  209. ...draft.sqlDataSource,
  210. columns: [],
  211. totalCount: 0,
  212. resultList: []
  213. }
  214. draft.loading.execute = false
  215. draft.sqlValidation = {
  216. code: action.payload.err.code,
  217. message: action.payload.err.msg
  218. }
  219. break
  220. case ActionTypes.EXECUTE_SQL_CANCEL:
  221. draft.sqlDataSource = {
  222. ...draft.sqlDataSource,
  223. columns: [],
  224. totalCount: 0,
  225. resultList: []
  226. }
  227. draft.loading.execute = false
  228. break
  229. case ActionTypes.UPDATE_EDITING_VIEW:
  230. draft.editingView = action.payload.view
  231. break
  232. case ActionTypes.UPDATE_EDITING_VIEW_INFO:
  233. draft.editingViewInfo = action.payload.viewInfo
  234. break
  235. case ActionTypes.SET_SQL_LIMIT:
  236. draft.sqlLimit = action.payload.limit
  237. break
  238. case ActionTypes.EDIT_VIEW_SUCCESS:
  239. draft.editingView = emptyView
  240. draft.editingViewInfo = { model: {}, variable: [], roles: [] }
  241. draft.formedViews[action.payload.result.id] = getFormedView(
  242. action.payload.result
  243. )
  244. break
  245. case ActionTypes.COPY_VIEW:
  246. draft.loading.copy = true
  247. break
  248. case ActionTypes.COPY_VIEW_SUCCESS:
  249. const fromViewId = action.payload.fromViewId
  250. const { id, name, description, source } = action.payload.result
  251. const copiedView: IViewBase = {
  252. id,
  253. name,
  254. description,
  255. sourceName: source.name
  256. }
  257. draft.views.splice(
  258. draft.views.findIndex(({ id }) => id === fromViewId) + 1,
  259. 0,
  260. copiedView
  261. )
  262. draft.loading.copy = false
  263. break
  264. case ActionTypes.COPY_VIEW_FAILURE:
  265. draft.loading.copy = false
  266. break
  267. case ActionTypes.LOAD_DAC_CHANNELS_SUCCESS:
  268. draft.channels = action.payload.channels
  269. break
  270. case ActionTypes.LOAD_DAC_TENANTS_SUCCESS:
  271. draft.tenants = action.payload.tenants
  272. break
  273. case ActionTypes.LOAD_DAC_TENANTS_FAILURE:
  274. draft.tenants = []
  275. break
  276. case ActionTypes.LOAD_DAC_BIZS_SUCCESS:
  277. draft.bizs = action.payload.bizs
  278. break
  279. case ActionTypes.LOAD_DAC_BIZS_FAILURE:
  280. draft.bizs = []
  281. break
  282. case ActionTypes.RESET_VIEW_STATE:
  283. return initialState
  284. break
  285. case WidgetActionTypes.LOAD_WIDGET_DETAIL_SUCCESS:
  286. const widgetView = action.payload.view
  287. draft.formedViews[widgetView.id] = {
  288. ...widgetView,
  289. model: JSON.parse(widgetView.model || '{}'),
  290. variable: JSON.parse(widgetView.variable || '[]')
  291. }
  292. break
  293. case DashboardActionTypes.LOAD_DASHBOARD_DETAIL_SUCCESS:
  294. case DisplayActionTypes.LOAD_SLIDE_DETAIL_SUCCESS:
  295. draft.formedViews = {
  296. ...draft.formedViews,
  297. ...action.payload.formedViews
  298. }
  299. break
  300. case ActionTypes.LOAD_VIEW_DATA_FROM_VIZ_ITEM:
  301. case ActionTypes.LOAD_SELECT_OPTIONS:
  302. draft.cancelTokenSources.push(action.payload.cancelTokenSource)
  303. break
  304. case LOCATION_CHANGE:
  305. if (state.cancelTokenSources.length) {
  306. state.cancelTokenSources.forEach((source) => {
  307. source.cancel()
  308. })
  309. draft.cancelTokenSources = []
  310. }
  311. break
  312. default:
  313. break
  314. }
  315. })
  316. export { initialState as viewInitialState }
  317. export default viewReducer