util.ts 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602
  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 omit from 'lodash/omit'
  21. import {
  22. getPreciseDefaultValue,
  23. getFilterParams,
  24. getVariableParams,
  25. getCustomOptionVariableParams
  26. } from 'app/components/Control/util'
  27. import { FieldSortTypes } from '../Widget/components/Config/Sort'
  28. import { decodeMetricName } from '../Widget/components/util'
  29. import {
  30. IDashboardItemInfo,
  31. IQueryConditions,
  32. IDataRequestParams,
  33. IDataRequestBody,
  34. IDashboardItem
  35. } from './types'
  36. import { IWidgetFormed } from '../Widget/types'
  37. import ChartTypes from '../Widget/config/chart/ChartTypes'
  38. import {
  39. IControl,
  40. IGlobalControlConditionsByItem,
  41. ILocalControlConditions,
  42. IGlobalControlConditions
  43. } from 'app/components/Control/types'
  44. import {
  45. ControlPanelTypes,
  46. ControlFieldTypes
  47. } from 'app/components/Control/constants'
  48. import {
  49. IFormedViews,
  50. IShareFormedViews,
  51. IViewQueryResponse
  52. } from '../View/types'
  53. import { IPaginationParams } from '../Widget/components/Widget'
  54. export function getInitialPagination(widget: IWidgetFormed): IPaginationParams {
  55. const { mode, selectedChart, chartStyles } = widget.config
  56. if (mode === 'chart' && selectedChart === ChartTypes.Table) {
  57. const { withPaging, pageSize } = chartStyles.table
  58. return {
  59. withPaging,
  60. pageSize: withPaging ? Number(pageSize) : 0,
  61. pageNo: withPaging ? 1 : 0,
  62. totalCount: 0
  63. }
  64. } else {
  65. return null
  66. }
  67. }
  68. export function getInitialNativeQuery(widget: IWidgetFormed): boolean {
  69. const { mode, selectedChart, chartStyles } = widget.config
  70. if (mode === 'chart' && selectedChart === ChartTypes.Table) {
  71. return chartStyles.table.withNoAggregators
  72. } else {
  73. return false
  74. }
  75. }
  76. export function getInitialPaginationAndNativeQuery(widget: IWidgetFormed) {
  77. return {
  78. pagination: getInitialPagination(widget),
  79. nativeQuery: getInitialNativeQuery(widget)
  80. }
  81. }
  82. export function getUpdatedPagination(
  83. pagination: IPaginationParams,
  84. result: IViewQueryResponse
  85. ): IPaginationParams {
  86. if (!pagination) {
  87. return pagination
  88. }
  89. const { pageNo, pageSize, totalCount } = result
  90. return {
  91. ...pagination,
  92. pageNo: pagination.withPaging ? pageNo : 0,
  93. pageSize: pagination.withPaging ? pageSize : 0,
  94. totalCount
  95. }
  96. }
  97. export function getInitialItemInfo(
  98. widget: IWidgetFormed,
  99. formedViews: IFormedViews
  100. ): IDashboardItemInfo {
  101. return {
  102. datasource: {
  103. columns: [],
  104. pageNo: 0,
  105. pageSize: 0,
  106. totalCount: 0,
  107. resultList: []
  108. },
  109. loading: false,
  110. queryConditions: {
  111. linkageFilters: [],
  112. globalFilters: [],
  113. linkageVariables: [],
  114. globalVariables: [],
  115. drillpathInstance: [],
  116. ...getLocalControlInitialValues(widget.config.controls, formedViews),
  117. ...getInitialPaginationAndNativeQuery(widget)
  118. },
  119. shareToken: '',
  120. shareLoading: false,
  121. authorizedShareToken: '',
  122. downloadCsvLoading: false,
  123. interactId: '',
  124. rendered: false,
  125. renderType: 'rerender',
  126. selectedItems: [],
  127. errorMessage: ''
  128. }
  129. }
  130. interface IGlobalControlInitialValues {
  131. [itemId: string]: IGlobalControlConditions
  132. }
  133. export function getGlobalControlInitialValues(
  134. controls: IControl[],
  135. formedViews: IFormedViews | IShareFormedViews
  136. ): IGlobalControlInitialValues {
  137. const initialValues: IGlobalControlInitialValues = {}
  138. controls.forEach((control: IControl) => {
  139. const { optionWithVariable, relatedItems, relatedViews } = control
  140. const defaultValue = getPreciseDefaultValue(control)
  141. if (defaultValue) {
  142. Object.entries(relatedItems).forEach(([itemId, config]) => {
  143. Object.entries(relatedViews).forEach(([viewId, relatedView]) => {
  144. if (
  145. config.checked &&
  146. config.viewId === Number(viewId) &&
  147. formedViews[viewId]
  148. ) {
  149. const { model, variable } = formedViews[viewId]
  150. if (!initialValues[itemId]) {
  151. initialValues[itemId] = {
  152. globalFilters: [],
  153. globalVariables: []
  154. }
  155. }
  156. if (optionWithVariable) {
  157. const filterValue = getCustomOptionVariableParams(
  158. control,
  159. Number(viewId),
  160. defaultValue,
  161. variable
  162. )
  163. initialValues[itemId].globalVariables = initialValues[
  164. itemId
  165. ].globalVariables.concat(filterValue)
  166. } else {
  167. if (relatedView.fieldType === ControlFieldTypes.Column) {
  168. const filterValue = getFilterParams(
  169. control,
  170. relatedView.fields,
  171. defaultValue,
  172. model
  173. )
  174. initialValues[itemId].globalFilters = initialValues[
  175. itemId
  176. ].globalFilters.concat(filterValue)
  177. } else {
  178. const filterValue = getVariableParams(
  179. control,
  180. relatedView.fields,
  181. defaultValue,
  182. variable
  183. )
  184. initialValues[itemId].globalVariables = initialValues[
  185. itemId
  186. ].globalVariables.concat(filterValue)
  187. }
  188. }
  189. }
  190. })
  191. })
  192. }
  193. })
  194. return initialValues
  195. }
  196. export function getLocalControlInitialValues(
  197. controls: IControl[],
  198. formedViews: IFormedViews | IShareFormedViews
  199. ): ILocalControlConditions {
  200. const initialValues: ILocalControlConditions = {
  201. tempFilters: [], // @TODO combine widget static filters with local filters
  202. variables: []
  203. }
  204. controls.forEach((control: IControl) => {
  205. const { optionWithVariable, relatedViews } = control
  206. const defaultValue = getPreciseDefaultValue(control)
  207. if (defaultValue) {
  208. Object.entries(relatedViews).forEach(([viewId, relatedView]) => {
  209. if (formedViews[viewId]) {
  210. const { model, variable } = formedViews[viewId]
  211. if (optionWithVariable) {
  212. const filterValue = getCustomOptionVariableParams(
  213. control,
  214. Number(viewId),
  215. defaultValue,
  216. variable
  217. )
  218. initialValues.variables = initialValues.variables.concat(
  219. filterValue
  220. )
  221. } else {
  222. if (relatedView.fieldType === ControlFieldTypes.Column) {
  223. const filterValue = getFilterParams(
  224. control,
  225. relatedView.fields,
  226. defaultValue,
  227. model
  228. )
  229. initialValues.tempFilters = initialValues.tempFilters.concat(
  230. filterValue
  231. )
  232. } else {
  233. const filterValue = getVariableParams(
  234. control,
  235. relatedView.fields,
  236. defaultValue,
  237. variable
  238. )
  239. initialValues.variables = initialValues.variables.concat(
  240. filterValue
  241. )
  242. }
  243. }
  244. }
  245. })
  246. }
  247. })
  248. return initialValues
  249. }
  250. export function getRequestParams(
  251. widget: IWidgetFormed,
  252. cachedQueryConditions: IQueryConditions,
  253. flush: boolean,
  254. inputQueryConditions?: Partial<IQueryConditions>
  255. ): IDataRequestParams {
  256. const {
  257. cols,
  258. rows,
  259. metrics,
  260. secondaryMetrics,
  261. color,
  262. label,
  263. size,
  264. xAxis,
  265. tip,
  266. limit,
  267. cache,
  268. expired
  269. } = widget.config
  270. const customOrders = cols
  271. .concat(rows)
  272. .filter(({ sort }) => sort && sort.sortType === FieldSortTypes.Custom)
  273. .map(({ name, sort }) => ({
  274. name,
  275. list: sort[FieldSortTypes.Custom].sortList
  276. }))
  277. // @TODO combine widget static filters with local filters
  278. let tempFilters = cachedQueryConditions.tempFilters
  279. let linkageFilters = cachedQueryConditions.linkageFilters
  280. let globalFilters = cachedQueryConditions.globalFilters
  281. let paginationOrders = cachedQueryConditions.orders
  282. let variables = cachedQueryConditions.variables
  283. let linkageVariables = cachedQueryConditions.linkageVariables
  284. let globalVariables = cachedQueryConditions.globalVariables
  285. let pagination = cachedQueryConditions.pagination
  286. let nativeQuery = cachedQueryConditions.nativeQuery
  287. let drillStatus = cachedQueryConditions.drillStatus
  288. const prevDrillHistory = cachedQueryConditions.drillHistory
  289. ? cachedQueryConditions.drillHistory[
  290. cachedQueryConditions.drillHistory.length - 1
  291. ]
  292. : {}
  293. if (inputQueryConditions) {
  294. tempFilters = inputQueryConditions.tempFilters || tempFilters
  295. linkageFilters = inputQueryConditions.linkageFilters || linkageFilters
  296. globalFilters = inputQueryConditions.globalFilters || globalFilters
  297. paginationOrders = inputQueryConditions.orders || paginationOrders
  298. variables = inputQueryConditions.variables || variables
  299. linkageVariables = inputQueryConditions.linkageVariables || linkageVariables
  300. globalVariables = inputQueryConditions.globalVariables || globalVariables
  301. drillStatus = inputQueryConditions.drillStatus || prevDrillHistory
  302. pagination = inputQueryConditions.pagination || pagination
  303. nativeQuery =
  304. inputQueryConditions.nativeQuery !== void 0
  305. ? inputQueryConditions.nativeQuery
  306. : nativeQuery
  307. }
  308. let groups = cols
  309. .concat(rows)
  310. .filter((g) => g.name !== '指标名称')
  311. .map((g) => g.name)
  312. let aggregators = metrics.map((m) => ({
  313. column: decodeMetricName(m.name),
  314. func: m.agg
  315. }))
  316. let orders = widget.config.orders
  317. const filters = widget.config.filters.reduce(
  318. (a, b) => a.concat(b.config.sqlModel),
  319. []
  320. )
  321. if (secondaryMetrics && secondaryMetrics.length) {
  322. aggregators = aggregators.concat(
  323. secondaryMetrics.map((second) => ({
  324. column: decodeMetricName(second.name),
  325. func: second.agg
  326. }))
  327. )
  328. }
  329. if (color) {
  330. groups = groups.concat(color.items.map((c) => c.name))
  331. }
  332. if (label) {
  333. groups = groups.concat(
  334. label.items.filter((l) => l.type === 'category').map((l) => l.name)
  335. )
  336. aggregators = aggregators.concat(
  337. label.items
  338. .filter((l) => l.type === 'value')
  339. .map((l) => ({
  340. column: decodeMetricName(l.name),
  341. func: l.agg
  342. }))
  343. )
  344. }
  345. if (size) {
  346. aggregators = aggregators.concat(
  347. size.items.map((s) => ({
  348. column: decodeMetricName(s.name),
  349. func: s.agg
  350. }))
  351. )
  352. }
  353. if (xAxis) {
  354. aggregators = aggregators.concat(
  355. xAxis.items.map((x) => ({
  356. column: decodeMetricName(x.name),
  357. func: x.agg
  358. }))
  359. )
  360. }
  361. if (tip) {
  362. aggregators = aggregators.concat(
  363. tip.items.map((t) => ({
  364. column: decodeMetricName(t.name),
  365. func: t.agg
  366. }))
  367. )
  368. }
  369. if (paginationOrders) {
  370. orders = orders.concat(paginationOrders)
  371. }
  372. return {
  373. groups,
  374. aggregators,
  375. filters,
  376. tempFilters,
  377. linkageFilters,
  378. globalFilters,
  379. variables,
  380. linkageVariables,
  381. globalVariables,
  382. orders,
  383. limit,
  384. cache,
  385. expired,
  386. flush,
  387. pagination,
  388. nativeQuery,
  389. customOrders,
  390. drillStatus
  391. }
  392. }
  393. export function getRequestBody(
  394. requestParams: IDataRequestParams
  395. ): IDataRequestBody {
  396. const {
  397. filters,
  398. tempFilters, // @TODO combine widget static filters with local filters
  399. linkageFilters,
  400. globalFilters,
  401. variables,
  402. linkageVariables,
  403. globalVariables,
  404. pagination,
  405. drillStatus,
  406. groups,
  407. ...rest
  408. } = requestParams
  409. const { pageSize, pageNo } = pagination || { pageSize: 0, pageNo: 0 }
  410. let combinedFilters = filters
  411. .concat(tempFilters)
  412. .concat(linkageFilters)
  413. .concat(globalFilters)
  414. if (drillStatus && drillStatus.filters) {
  415. combinedFilters = combinedFilters.concat(drillStatus.filters)
  416. }
  417. return {
  418. ...omit(rest, 'customOrders'),
  419. groups: drillStatus && drillStatus.groups ? drillStatus.groups : groups,
  420. filters: combinedFilters,
  421. params: variables.concat(linkageVariables).concat(globalVariables),
  422. pageSize,
  423. pageNo
  424. }
  425. }
  426. export function getFormValuesRelatedItems(
  427. controls: IControl[],
  428. currentItems: IDashboardItem[],
  429. formValues: object
  430. ): number[] {
  431. return Object.keys(formValues).reduce((items, key) => {
  432. const control = controls.find((c) => c.key === key)
  433. const { relatedItems } = control
  434. const checkedItems = Object.entries(relatedItems)
  435. .filter(
  436. ([itemId, config]) =>
  437. config.checked && currentItems.find((c) => c.id === Number(itemId))
  438. )
  439. .map(([itemId]) => itemId)
  440. return Array.from(new Set([...items, ...checkedItems]))
  441. }, [])
  442. }
  443. export function getCurrentControlValues(
  444. type: ControlPanelTypes,
  445. controls: IControl[],
  446. formedViews: IFormedViews | IShareFormedViews,
  447. allFormValues: object,
  448. changedFormValues?: object,
  449. currentItems?: IDashboardItem[]
  450. ): IGlobalControlConditionsByItem | ILocalControlConditions {
  451. const updatedFormValues = {
  452. ...allFormValues,
  453. ...changedFormValues
  454. }
  455. if (type === ControlPanelTypes.Global) {
  456. const changedFormValuesRelatedItems = getFormValuesRelatedItems(
  457. controls,
  458. currentItems,
  459. changedFormValues || allFormValues
  460. )
  461. const conditionsByItem: IGlobalControlConditionsByItem = {}
  462. changedFormValuesRelatedItems.forEach((itemId) => {
  463. Object.entries(updatedFormValues).forEach(([key, value]) => {
  464. const control = controls.find((c) => c.key === key)
  465. if (control) {
  466. const { optionWithVariable, relatedViews, relatedItems } = control
  467. const relatedItem = relatedItems[itemId]
  468. if (
  469. relatedItem &&
  470. relatedItem.checked &&
  471. relatedViews[relatedItem.viewId] &&
  472. formedViews[relatedItem.viewId]
  473. ) {
  474. const relatedView = relatedViews[relatedItem.viewId]
  475. const { model, variable } = formedViews[relatedItem.viewId]
  476. if (!conditionsByItem[itemId]) {
  477. conditionsByItem[itemId] = {
  478. globalVariables: [],
  479. globalFilters: []
  480. }
  481. }
  482. if (optionWithVariable) {
  483. const controlVariables = getCustomOptionVariableParams(
  484. control,
  485. relatedItem.viewId,
  486. value,
  487. variable
  488. )
  489. conditionsByItem[itemId].globalVariables = conditionsByItem[
  490. itemId
  491. ].globalVariables.concat(controlVariables)
  492. } else {
  493. if (relatedView.fieldType === ControlFieldTypes.Column) {
  494. const controlFilters = getFilterParams(
  495. control,
  496. relatedView.fields,
  497. value,
  498. model
  499. )
  500. conditionsByItem[itemId].globalFilters = conditionsByItem[
  501. itemId
  502. ].globalFilters.concat(controlFilters)
  503. } else {
  504. const controlVariables = getVariableParams(
  505. control,
  506. relatedView.fields,
  507. value,
  508. variable
  509. )
  510. conditionsByItem[itemId].globalVariables = conditionsByItem[
  511. itemId
  512. ].globalVariables.concat(controlVariables)
  513. }
  514. }
  515. }
  516. }
  517. })
  518. })
  519. return conditionsByItem
  520. } else {
  521. const conditions: ILocalControlConditions = {
  522. tempFilters: [],
  523. variables: []
  524. }
  525. Object.entries(updatedFormValues).forEach(([key, value]) => {
  526. const control = controls.find((c) => c.key === key)
  527. if (control) {
  528. const [viewId, relatedView] = Object.entries(control.relatedViews)[0]
  529. if (formedViews[viewId]) {
  530. const { model, variable } = formedViews[viewId]
  531. if (control.optionWithVariable) {
  532. const controlVariables = getCustomOptionVariableParams(
  533. control,
  534. Number(viewId),
  535. value,
  536. variable
  537. )
  538. conditions.variables = conditions.variables.concat(controlVariables)
  539. } else {
  540. if (relatedView.fieldType === ControlFieldTypes.Column) {
  541. const controlFilters = getFilterParams(
  542. control,
  543. relatedView.fields,
  544. value,
  545. model
  546. )
  547. conditions.tempFilters = conditions.tempFilters.concat(
  548. controlFilters
  549. )
  550. } else {
  551. const controlVariables = getVariableParams(
  552. control,
  553. relatedView.fields,
  554. value,
  555. variable
  556. )
  557. conditions.variables = conditions.variables.concat(
  558. controlVariables
  559. )
  560. }
  561. }
  562. }
  563. }
  564. })
  565. return conditions
  566. }
  567. }