1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321 |
- /*
- * <<
- * 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, { createRef, RefObject } from 'react'
- import { findDOMNode } from 'react-dom'
- import Helmet from 'react-helmet'
- import { connect } from 'react-redux'
- import { createStructuredSelector } from 'reselect'
- import { Link } from 'react-router-dom'
- import { compose } from 'redux'
- import injectReducer from 'utils/injectReducer'
- import injectSaga from 'utils/injectSaga'
- import viewReducer from 'containers/View/reducer'
- import viewSaga from 'containers/View/sagas'
- import controlReducer from 'app/containers/ControlPanel/reducer'
- import {
- IDashboard,
- IDashboardItem,
- QueryVariable,
- IQueryConditions,
- TShareVizsType
- } from './types'
- import { RouteComponentWithParams } from 'utils/types'
- import Container, { ContainerTitle, ContainerBody } from 'components/Container'
- import Toolbar from './components/Toolbar'
- import DashboardItemForm from './components/DashboardItemForm'
- import DashboardItem from './components/DashboardItem'
- import DashboardLinkageConfig from './components/DashboardLinkageConfig'
- import { IDistinctValueReqeustParams } from 'app/components/Control/types'
- import { ControlPanelLayoutTypes, ControlPanelTypes } from 'app/components/Control/constants'
- import GlobalControlPanel from '../ControlPanel/Global'
- import GlobalControlConfig from 'app/components/Control/Config'
- import SharePanel from './SharePanel'
- import { getMappingLinkage, processLinkage, removeLinkage } from 'components/Linkages'
- import { hasVizEditPermission } from '../Account/components/checkUtilPermission'
- import { Responsive, WidthProvider } from 'react-grid-layout'
- import AntdFormType from 'antd/lib/form/Form'
- import { Row, Col, Button, Modal, Breadcrumb, Menu, message } from 'antd'
- import FullScreenPanel from './FullScreenPanel'
- import { DashboardActions } from './actions'
- const {
- loadDashboardDetail,
- addDashboardItems,
- editDashboardItem,
- editDashboardItems,
- deleteDashboardItem,
- clearCurrentDashboard,
- loadDashboardItemData,
- loadBatchDataWithControlValues,
- initiateDownloadTask,
- renderDashboardItem,
- resizeDashboardItem,
- resizeAllDashboardItem,
- renderChartError,
- openSharePanel,
- drillDashboardItem,
- deleteDrillHistory,
- drillPathsetting,
- selectDashboardItemChart,
- setFullScreenPanelItemId,
- monitoredSyncDataAction,
- monitoredLinkageDataAction,
- monitoredSearchDataAction
- } = DashboardActions
- import {
- makeSelectCurrentDashboard,
- makeSelectCurrentDashboardLoading,
- makeSelectCurrentItems,
- makeSelectCurrentItemsInfo,
- makeSelectCurrentLinkages
- } from './selectors'
- import VizActions from 'containers/Viz/actions'
- import { makeSelectCurrentPortal, makeSelectCurrentDashboards } from 'containers/Viz/selectors'
- import ViewActions from 'containers/View/actions'
- import { ControlActions } from 'containers/ControlPanel/actions'
- const {
- loadViews,
- loadViewsDetail,
- loadSelectOptions,
- loadColumnDistinctValue
- } = ViewActions
- const { setSelectOptions } = ControlActions
- import { makeSelectWidgets } from 'containers/Widget/selectors'
- import { makeSelectViews, makeSelectFormedViews } from 'containers/View/selectors'
- import { makeSelectCurrentProject } from 'containers/Projects/selectors'
- import {
- DEFAULT_SPLITER,
- GRID_BREAKPOINTS,
- GRID_COLS,
- GRID_ITEM_MARGIN,
- GRID_ROW_HEIGHT
- } from 'app/globalConstants'
- import { RenderType } from '../Widget/components/Widget'
- import { DownloadTypes } from '../App/constants'
- import { statistic, IVizData } from 'utils/statistic/statistic.dv'
- const utilStyles = require('assets/less/util.less')
- const styles = require('./Dashboard.less')
- const ResponsiveReactGridLayout = WidthProvider(Responsive)
- import { IDrillDetail } from 'components/DataDrill/types'
- import { IView } from '../View/types'
- type MappedStates = ReturnType<typeof mapStateToProps>
- type MappedDispatches = ReturnType<typeof mapDispatchToProps>
- type IGridProps = MappedStates & MappedDispatches
- interface IGridStates {
- mounted: boolean
- layoutInitialized: boolean
- dashboardItemFormType: string
- dashboardItemFormVisible: boolean
- dashboardItemFormStep: number
- modalLoading: boolean
- selectedWidgets: number[]
- currentItemId: number | boolean
- polling: boolean
- linkageConfigVisible: boolean
- interactingStatus: { [itemId: number]: boolean }
- globalControlConfigVisible: boolean
- nextMenuTitle: string
- }
- interface IDashboardItemForm extends AntdFormType {
- onReset: () => void
- }
- export class Grid extends React.Component<IGridProps & RouteComponentWithParams, IGridStates> {
- constructor (props) {
- super(props)
- this.state = {
- mounted: false,
- layoutInitialized: false,
- dashboardItemFormType: '',
- dashboardItemFormVisible: false,
- dashboardItemFormStep: 0,
- modalLoading: false,
- selectedWidgets: [],
- polling: false,
- currentItemId: false,
- linkageConfigVisible: false,
- interactingStatus: {},
- globalControlConfigVisible: false,
- nextMenuTitle: ''
- }
- }
- private containerBody: RefObject<HTMLDivElement> = createRef()
- private containerBodyScrollThrottle: boolean = false
- private interactCallbacks: object = {}
- private interactingLinkagers: object = {}
- private interactGlobalFilters: object = {}
- private resizeSign: number
- private dashboardItemForm: IDashboardItemForm = null
- private refHandles = {
- dashboardItemForm: (f) => { this.dashboardItemForm = f }
- }
- public componentWillMount () {
- const { match, widgets, onLoadDashboardDetail } = this.props
- const { portalId, dashboardId } = match.params
- if (dashboardId && Number(dashboardId) !== -1 && widgets) {
- onLoadDashboardDetail(+portalId, Number(dashboardId))
- }
- }
- private getVizDataForStatistic ({
- portalId,
- projectId,
- dashboardId,
- currentPortal,
- currentProject,
- currentDashboard
- }): IVizData {
- return {
- project_id: +projectId,
- project_name: currentProject && currentProject.name,
- org_id: currentProject && currentProject.orgId,
- viz_type: 'dashboard',
- viz_id: +portalId,
- viz_name: currentPortal && currentPortal.name,
- sub_viz_id: +dashboardId,
- sub_viz_name: currentDashboard && currentDashboard['name']
- }
- }
- public componentWillReceiveProps (nextProps: IGridProps & RouteComponentWithParams) {
- const {
- currentDashboard,
- currentDashboardLoading,
- currentItems,
- currentPortal,
- match: { params: nextParams },
- onLoadDashboardDetail
- } = nextProps
- const { layoutInitialized } = this.state
- const { match, currentProject} = this.props
- const { projectId, portalId, dashboardId } = match.params
- const getVizData = this.getVizDataForStatistic({
- projectId,
- portalId,
- dashboardId: nextParams.dashboardId,
- currentPortal,
- currentProject,
- currentDashboard
- })
- if (nextParams.dashboardId === dashboardId) {
- if (nextProps.currentDashboard !== this.props.currentDashboard) {
- statistic.setOperations({
- ...getVizData,
- create_time: statistic.getCurrentDateTime()
- }, (data) => {
- const visitRecord = {
- ...data,
- action: 'visit'
- }
- statistic.sendOperation(visitRecord).then((res) => {
- statistic.updateSingleFleld('operation', 'action', 'initial')
- })
- })
- }
- }
- if (nextParams.dashboardId !== dashboardId) {
- this.setState({
- nextMenuTitle: ''
- })
- if (nextParams.dashboardId && Number(nextParams.dashboardId) !== -1) {
- onLoadDashboardDetail(+nextParams.portalId, +nextParams.dashboardId)
- }
- statistic.setDurations({
- ...getVizData,
- end_time: statistic.getCurrentDateTime()
- }, (data) => {
- statistic.sendDuration([data]).then((res) => {
- statistic.setDurations({
- start_time: statistic.getCurrentDateTime() // 初始化下一时段
- })
- })
- })
- }
- if (!currentDashboardLoading) {
- if (currentItems && !layoutInitialized) {
- this.setState({
- mounted: true
- }, () => {
- this.lazyLoad()
- this.containerBody.current.removeEventListener('scroll', this.lazyLoad, false)
- this.containerBody.current.addEventListener('scroll', this.lazyLoad, false)
- })
- }
- }
- if (currentDashboard && currentDashboard.name) {
- statistic.setDurations({
- sub_viz_name: currentDashboard.name
- })
- }
- if (currentProject && currentProject.name) {
- statistic.setDurations({
- project_name: currentProject.name,
- org_id: currentProject.orgId
- })
- }
- if (currentPortal && currentPortal.name) {
- statistic.setDurations({
- viz_name: currentPortal.name
- })
- }
- }
- private statisticTimeFuc = () => {
- statistic.isTimeout()
- }
- public componentDidMount () {
- const {
- match,
- currentProject,
- currentDashboard,
- currentPortal,
- match: { params }
- } = this.props
- const { projectId, portalId } = match.params
- const getVizData = this.getVizDataForStatistic({
- projectId,
- portalId,
- dashboardId: params.dashboardId,
- currentPortal,
- currentProject,
- currentDashboard
- })
- window.addEventListener('resize', this.onWindowResize, false)
- window.addEventListener('beforeunload', function (event) {
- statistic.setDurations({
- end_time: statistic.getCurrentDateTime()
- }, (data) => {
- statistic.setPrevDurationRecord(data, () => {
- statistic.setDurations({
- start_time: statistic.getCurrentDateTime(),
- end_time: ''
- })
- })
- })
- }, false)
- statistic.setDurations({
- ...getVizData,
- start_time: statistic.getCurrentDateTime()
- })
- statistic.startClock()
- window.addEventListener('mousemove', this.statisticTimeFuc, false)
- window.addEventListener('visibilitychange', this.onVisibilityChanged, false)
- window.addEventListener('keydown', this.statisticTimeFuc, false)
- }
- private onVisibilityChanged (event) {
- const flag = event.target.webkitHidden
- if (flag) {
- statistic.setDurations({
- end_time: statistic.getCurrentDateTime()
- }, (data) => {
- statistic.sendDuration([data]).then((res) => {
- statistic.resetClock()
- })
- })
- } else {
- statistic.setDurations({
- start_time: statistic.getCurrentDateTime()
- }, (data) => {
- statistic.startClock()
- })
- }
- }
- public componentWillUnmount () {
- statistic.setDurations({
- end_time: statistic.getCurrentDateTime()
- }, (data) => {
- statistic.sendDuration([data])
- })
- window.removeEventListener('resize', this.onWindowResize, false)
- window.removeEventListener('mousemove', this.statisticTimeFuc, false)
- window.removeEventListener('visibilitychange', this.onVisibilityChanged, false)
- window.removeEventListener('keydown', this.statisticTimeFuc, false)
- this.containerBody.current.removeEventListener('scroll', this.lazyLoad, false)
- this.props.onClearCurrentDashboard()
- statistic.resetClock()
- }
- private lazyLoad = () => {
- if (!this.containerBodyScrollThrottle) {
- requestAnimationFrame(() => {
- const { currentItems, currentItemsInfo, onRenderDashboardItem } = this.props
- const waitingItems = currentItems.filter((item) => !currentItemsInfo[item.id].rendered)
- if (waitingItems.length) {
- const { offsetHeight, scrollTop } = this.containerBody.current
- waitingItems.forEach((item) => {
- const itemTop = this.calcItemTop(item.y)
- if (itemTop - scrollTop < offsetHeight) {
- onRenderDashboardItem(item.id)
- }
- })
- } else {
- if (this.containerBody.current) {
- this.containerBody.current.removeEventListener('scroll', this.lazyLoad, false)
- }
- }
- this.containerBodyScrollThrottle = false
- })
- this.containerBodyScrollThrottle = true
- }
- }
- private calcItemTop = (y: number) => Math.round((GRID_ROW_HEIGHT + GRID_ITEM_MARGIN) * y)
- private loadViews = () => {
- const { match, onLoadViews } = this.props
- const { projectId } = match.params
- onLoadViews(Number(projectId))
- }
- private initiateWidgetDownloadTask = (itemId: number) => {
- this.props.onInitiateDownloadTask(DownloadTypes.Widget, void 0, itemId)
- }
- private initiateDashboardDownloadTask = () => {
- const { currentDashboard, onInitiateDownloadTask } = this.props
- onInitiateDownloadTask(DownloadTypes.Dashboard, currentDashboard.id)
- }
- private onDragStop = (layout) => {
- this.onEditDashboardItemsPosition(layout)
- }
- private onResizeStop = (layout, oldItem) => {
- this.onEditDashboardItemsPosition(layout)
- this.props.onResizeDashboardItem(Number(oldItem.i))
- }
- private onEditDashboardItemsPosition = (layout) => {
- const { currentItems, onEditDashboardItems, match } = this.props
- const portalId = +match.params.portalId
- const changedItems = currentItems.map((item) => {
- const { x, y, w, h } = layout.find((l) => Number(l.i) === item.id)
- return {
- ...item,
- x,
- y,
- width: w,
- height: h
- }
- })
- onEditDashboardItems(portalId, changedItems)
- }
- private onBreakpointChange = () => {
- this.props.onResizeAllDashboardItem()
- }
- private onWindowResize = () => {
- if (this.resizeSign) {
- clearTimeout(this.resizeSign)
- }
- this.resizeSign = window.setTimeout(() => {
- this.props.onResizeAllDashboardItem()
- clearTimeout(this.resizeSign)
- this.resizeSign = void 0
- }, 500)
- }
- private showAddDashboardItemForm = () => {
- this.setState({
- dashboardItemFormType: 'add',
- dashboardItemFormVisible: true
- })
- }
- private showEditDashboardItemForm = (itemId) => () => {
- const dashboardItem = this.props.currentItems.find((c) => c.id === itemId)
- this.setState({
- dashboardItemFormType: 'edit',
- dashboardItemFormVisible: true,
- dashboardItemFormStep: 1,
- selectedWidgets: [dashboardItem.widgetId],
- polling: dashboardItem.polling
- }, () => {
- setTimeout(() => {
- this.dashboardItemForm.props.form.setFieldsValue({
- id: dashboardItem.id,
- polling: dashboardItem.polling ? 'true' : 'false',
- frequency: dashboardItem.frequency,
- alias: dashboardItem.alias
- })
- }, 0)
- })
- }
- private showDrillDashboardItemForm = (itemId) => () => {
- const dashboardItem = this.props.currentItems.find((c) => c.id === itemId)
- this.setState({
- selectedWidgets: [dashboardItem.widgetId],
- currentItemId: itemId
- })
- }
- private hideDashboardItemForm = () => {
- this.setState({
- modalLoading: false,
- dashboardItemFormVisible: false,
- selectedWidgets: []
- })
- }
- private afterDashboardItemFormClose = () => {
- this.setState({
- selectedWidgets: [],
- polling: false,
- dashboardItemFormStep: 0
- })
- this.dashboardItemForm.onReset()
- this.dashboardItemForm.props.form.resetFields()
- }
- private widgetSelect = (selectedRowKeys) => {
- this.setState({
- selectedWidgets: selectedRowKeys
- })
- }
- private pollingSelect = (val) => {
- this.setState({
- polling: val === 'true'
- })
- }
- private changeDashboardItemFormStep = (sign) => () => {
- this.setState({
- dashboardItemFormStep: sign
- })
- }
- private saveDashboardItem = () => {
- const { match, currentDashboard, currentItems, widgets, formedViews, onLoadDashboardItemData } = this.props
- const portalId = +match.params.portalId
- const { selectedWidgets, dashboardItemFormType } = this.state
- const formdata: any = this.dashboardItemForm.props.form.getFieldsValue()
- const cols = GRID_COLS.lg
- const yArr = [...currentItems.map((item) => item.y + item.height), 0]
- const maxY = Math.max(...yArr)
- const secondMaxY = maxY === 0 ? 0 : Math.max(...yArr.filter((y) => y !== maxY))
- let maxX = 0
- if (maxY) {
- const maxYItems = currentItems.filter((item) => item.y + item.height === maxY)
- maxX = Math.max(...maxYItems.map((item) => item.x + item.width))
- // if (maxX + 6 > cols) {
- // maxX = 0
- // }
- }
- this.setState({ modalLoading: true })
- const newItem = {
- dashboardId: currentDashboard.id,
- polling: formdata.polling !== 'false',
- frequency: formdata.frequency
- }
- if (dashboardItemFormType === 'add') {
- const positionInfo = {
- width: 6,
- height: 6
- }
- const newItems = selectedWidgets.map((key, index) => {
- const xAxisTemp = index % 2 !== 0 ? 6 : 0
- const yAxisTemp = index % 2 === 0
- ? secondMaxY + 6 * Math.floor(index / 2)
- : maxY + 6 * Math.floor(index / 2)
- let xAxis
- let yAxis
- if (maxX > 0 && maxX <= 6) {
- xAxis = index % 2 === 0 ? 6 : 0
- yAxis = yAxisTemp
- } else if (maxX === 0) {
- xAxis = xAxisTemp
- yAxis = yAxisTemp
- } else if (maxX > 6) {
- xAxis = xAxisTemp
- yAxis = maxY + 6 * Math.floor(index / 2)
- }
- const item = {
- widgetId: key,
- x: xAxis,
- y: yAxis,
- ...newItem,
- ...positionInfo
- }
- return item
- })
- const selectedWidgetsViewIds = widgets.filter((w) => selectedWidgets.includes(w.id)).map((w) => w.viewId)
- const viewIds = selectedWidgetsViewIds
- .filter((viewId, idx) => selectedWidgetsViewIds.indexOf(viewId) === idx)
- .filter((viewId) => !formedViews[viewId])
- if (viewIds.length) {
- this.props.onLoadViewsDetail(viewIds, () => {
- this.props.onAddDashboardItems(portalId, newItems, () => {
- this.hideDashboardItemForm()
- })
- })
- } else {
- this.props.onAddDashboardItems(portalId, newItems, () => {
- this.hideDashboardItemForm()
- })
- }
- } else {
- const dashboardItem = currentItems.find((item) => item.id === Number(formdata.id))
- const modifiedDashboardItem = {
- ...dashboardItem,
- ...newItem,
- widgetId: selectedWidgets[0],
- alias: formdata['alias']
- }
- this.props.onEditDashboardItem(portalId, modifiedDashboardItem, () => {
- onLoadDashboardItemData('rerender', modifiedDashboardItem.id)
- this.hideDashboardItemForm()
- })
- }
- }
- private deleteItem = (id) => () => {
- this.props.onDeleteDashboardItem(id)
- }
- private navDropdownClick = (e) => {
- const { match } = this.props
- const { projectId, portalId } = match.params
- this.props.history.push(`/project/${projectId}/portal/${portalId}/dashboard/${e.key}`)
- }
- private nextNavDropdownClick = (e) => {
- const {widgets} = this.props
- const itemId = e.item && e.item.props && e.item.props.id
- const widgetId = e.item && e.item.props && e.item.props.widgetId
- const widgetDOM = findDOMNode(this[`dashboardItem${itemId}`])
- if (widgetDOM) {
- const widgetParentDOM = widgetDOM.parentNode as HTMLElement
- const scrollCount = widgetParentDOM.style.transform && widgetParentDOM.style.transform.match(/\d+/g)[1]
- const containerBody = widgetParentDOM.parentNode.parentNode as HTMLElement
- const scrollHeight = parseInt(scrollCount, 10) - GRID_ITEM_MARGIN
- containerBody.scrollTop = scrollHeight
- }
- this.setState({
- nextMenuTitle: widgets.find((widget) => widget.id === widgetId)['name']
- })
- }
- private openLinkageConfig = () => {
- this.setState({
- linkageConfigVisible: true
- })
- }
- private closeLinkageConfig = () => {
- this.setState({
- linkageConfigVisible: false
- })
- }
- private saveLinkageConfig = (linkages: any[]) => {
- const { currentDashboard, onEditCurrentDashboard } = this.props
- onEditCurrentDashboard(
- {
- ...currentDashboard,
- config: {
- ...currentDashboard.config,
- linkages
- }
- },
- 'linkage',
- () => {
- this.closeLinkageConfig()
- this.clearAllInteracts()
- }
- )
- }
- private checkInteract = (itemId: number) => {
- const { currentLinkages } = this.props
- const isInteractiveItem = currentLinkages.some((c) => {
- const { trigger } = c
- const triggerId = +trigger[0]
- return triggerId === itemId
- })
- return isInteractiveItem
- }
- private doInteract = (itemId: number, triggerData) => {
- const {
- currentLinkages,
- onLoadDashboardItemData,
- onMonitoredLinkageDataAction
- } = this.props
- const mappingLinkage = getMappingLinkage(itemId, currentLinkages)
- this.interactingLinkagers = processLinkage(itemId, triggerData, mappingLinkage, this.interactingLinkagers)
- Object.keys(mappingLinkage).forEach((linkagerItemId) => {
- const { filters, variables } = this.interactingLinkagers[linkagerItemId]
- onLoadDashboardItemData('clear', +linkagerItemId, {
- linkageFilters: Object.values(filters).reduce<string[]>((arr, f: string[]) => arr.concat(...f), []),
- linkageVariables: Object.values(variables).reduce<QueryVariable>((arr, p: QueryVariable) => arr.concat(...p), [])
- })
- })
- this.setState({
- interactingStatus: {
- ...this.state.interactingStatus,
- [itemId]: true
- }
- })
- if (onMonitoredLinkageDataAction) {
- onMonitoredLinkageDataAction()
- }
- }
- private clearAllInteracts = () => {
- const { onLoadDashboardItemData } = this.props
- Object.keys(this.interactingLinkagers).forEach((linkagerItemId) => {
- onLoadDashboardItemData('clear', +linkagerItemId, {
- linkageFilters: [],
- linkageVariables: []
- })
- })
- this.interactingLinkagers = {} // FIXME need remove interact effect
- this.setState({ interactingStatus: {} })
- }
- private turnOffInteract = (itemId) => {
- const {
- currentLinkages,
- onLoadDashboardItemData,
- onMonitoredLinkageDataAction
- } = this.props
- const refreshItemIds = removeLinkage(itemId, currentLinkages, this.interactingLinkagers)
- refreshItemIds.forEach((linkagerItemId) => {
- const { filters, variables } = this.interactingLinkagers[linkagerItemId]
- onLoadDashboardItemData('rerender', linkagerItemId, {
- linkageFilters: Object.values(filters).reduce<string[]>((arr, f: string[]) => arr.concat(...f), []),
- linkageVariables: Object.values(variables).reduce<QueryVariable>((arr, p: QueryVariable) => arr.concat(...p), [])
- })
- })
- this.setState({
- interactingStatus: {
- ...this.state.interactingStatus,
- [itemId]: false
- }
- }, () => {
- onLoadDashboardItemData('clear', itemId)
- })
- if (onMonitoredLinkageDataAction) {
- onMonitoredLinkageDataAction()
- }
- }
- private openGlobalControlConfig = () => {
- this.setState({
- globalControlConfigVisible: true
- })
- }
- private closeGlobalControlConfig = () => {
- this.setState({
- globalControlConfigVisible: false
- })
- }
- private saveControls = (controls, queryMode) => {
- const {
- currentDashboard,
- onEditCurrentDashboard
- } = this.props
- onEditCurrentDashboard(
- {
- ...currentDashboard,
- config: {
- ...currentDashboard.config,
- filters: controls,
- queryMode
- }
- },
- 'control',
- () => {
- this.closeGlobalControlConfig()
- }
- )
- }
- private getControlSelectOptions = (controlKey: string, useOptions: boolean, paramsOrOptions, itemId?: number) => {
- if (useOptions) {
- this.props.onSetSelectOptions(controlKey, paramsOrOptions, itemId)
- } else {
- this.props.onLoadSelectOptions(controlKey, paramsOrOptions, itemId)
- }
- }
- private openDashboardSharePanel = () => {
- const { currentDashboard, onOpenSharePanel } = this.props
- const { id, name } = currentDashboard
- onOpenSharePanel(id, 'dashboard', name)
- }
- private getWidgetInfo = (dashboardItemId) => {
- const { currentItems, widgets } = this.props
- const dashboardItem = currentItems.find((ci) => ci.id === dashboardItemId)
- const widget = widgets.find((w) => w.id === dashboardItem.widgetId)
- return {
- name: widget.name
- }
- }
- private toWorkbench = (itemId, widgetId) => {
- const { projectId, portalId, dashboardId } = this.props.match.params
- const editSign = [projectId, portalId, dashboardId, itemId].join(DEFAULT_SPLITER)
- sessionStorage.setItem('editWidgetFromDashboard', editSign)
- const prefix = window.localStorage.getItem('inDataService') ?? ''
- const prefixPath = prefix ? '/' + prefix : prefix
- this.props.history.push(`/project/${projectId}${prefixPath}/widget/${widgetId}`)
- }
- private dataDrill = (drillDetail) => {
- const { onDrillDashboardItem, onLoadDashboardItemData } = this.props
- const { itemId, widgetId, cols, rows, type, groups, filters, currentGroup } = drillDetail
- const currentDrillStatus: IDrillDetail = { cols, rows, type, groups, filters, currentGroup }
- onDrillDashboardItem(itemId, currentDrillStatus)
- onLoadDashboardItemData('rerender', itemId, {
- drillStatus: currentDrillStatus
- })
- }
- private selectDrillHistory = (history, item, itemId) => {
- const { onLoadDashboardItemData, onDeleteDrillHistory } = this.props
- setTimeout(() => {
- if (history) {
- onLoadDashboardItemData('rerender', itemId, {
- drillStatus: history
- })
- } else {
- onLoadDashboardItemData('rerender', itemId)
- }
- }, 50)
- onDeleteDrillHistory(itemId, item)
- }
- private selectChartsItems = (itemId, renderType, selectedItems) => {
- const { onSelectDashboardItemChart } = this.props
- onSelectDashboardItemChart(itemId, renderType, selectedItems)
- }
- public render () {
- const {
- dashboards,
- widgets,
- currentDashboard,
- currentDashboardLoading,
- currentItems,
- currentItemsInfo,
- views,
- formedViews,
- currentProject,
- currentLinkages,
- onLoadViewsDetail,
- onOpenSharePanel,
- onLoadDashboardItemData,
- onLoadBatchDataWithControlValues,
- onLoadColumnDistinctValue,
- onResizeDashboardItem,
- onRenderChartError,
- onSetFullScreenPanelItemId,
- onMonitoredSyncDataAction,
- onMonitoredSearchDataAction
- } = this.props
- const {
- mounted,
- dashboardItemFormType,
- dashboardItemFormVisible,
- modalLoading,
- selectedWidgets,
- polling,
- currentItemId,
- dashboardItemFormStep,
- linkageConfigVisible,
- interactingStatus,
- globalControlConfigVisible
- } = this.state
- let navDropdown = (<span />)
- let grids = void 0
- if (dashboards) {
- const navDropdownItems = dashboards.map((d) => (
- <Menu.Item key={d.id}>
- {d.name}
- </Menu.Item>
- ))
- navDropdown = (
- <Menu onClick={this.navDropdownClick}>
- {navDropdownItems}
- </Menu>
- )
- }
- let nextNavDropdown = (<span />)
- if (currentDashboard && widgets) {
- const navDropdownItems = currentItems.map((d) => {
- const wid = (widgets.find((widget) => widget.id === d.widgetId))
- return (
- <Menu.Item key={d.id}>
- {d.widgetId ?
- wid && wid.name ? wid.name : ''
- : ''}
- </Menu.Item>
- )})
- nextNavDropdown = (
- <Menu onClick={this.nextNavDropdownClick}>
- {navDropdownItems}
- </Menu>
- )
- }
- let gridEditable = false
- if (currentProject && currentItems && widgets) {
- const itemblocks = []
- const layouts = { lg: [] }
- gridEditable = hasVizEditPermission(currentProject.permission)
- currentItems.forEach((dashboardItem) => {
- const { id, x, y, width, height, widgetId, polling, frequency, alias } = dashboardItem
- const {
- datasource,
- loading,
- shareToken,
- shareLoading,
- downloadCsvLoading,
- interactId,
- rendered,
- renderType,
- queryConditions,
- selectedItems,
- errorMessage
- } = currentItemsInfo[id]
- const widget = widgets.find((w) => w.id === widgetId)
- const interacting = interactingStatus[id] || false
- const view = formedViews[widget.viewId]
- const isTrigger = currentLinkages && currentLinkages.length ? currentLinkages.map((linkage) => linkage.trigger[0]
- ).some((tr) => tr === String(id)) : false
- itemblocks.push((
- <div key={id} className={styles.authSizeTag}>
- <DashboardItem
- itemId={id}
- alias={alias}
- widgets={widgets}
- formedViews={formedViews}
- widget={widget}
- isTrigger={isTrigger}
- datasource={datasource}
- loading={loading}
- polling={polling}
- interacting={interacting}
- frequency={frequency}
- shareToken={shareToken}
- view={view}
- shareLoading={shareLoading}
- downloadCsvLoading={downloadCsvLoading}
- currentProject={currentProject}
- rendered={rendered}
- renderType={renderType}
- queryConditions={queryConditions}
- errorMessage={errorMessage}
- onSelectDrillHistory={this.selectDrillHistory}
- onLoadData={onLoadDashboardItemData}
- onShowEdit={this.showEditDashboardItemForm}
- onShowDrillEdit={this.showDrillDashboardItemForm}
- onDeleteDashboardItem={this.deleteItem}
- onResizeDashboardItem={onResizeDashboardItem}
- onRenderChartError={onRenderChartError}
- onOpenSharePanel={onOpenSharePanel}
- onDownloadCsv={this.initiateWidgetDownloadTask}
- onTurnOffInteract={this.turnOffInteract}
- onCheckTableInteract={this.checkInteract}
- onDoTableInteract={this.doInteract}
- onShowFullScreen={onSetFullScreenPanelItemId}
- onEditWidget={this.toWorkbench}
- onDrillData={this.dataDrill}
- onSelectChartsItems={this.selectChartsItems}
- onGetControlOptions={this.getControlSelectOptions}
- onControlSearch={onLoadBatchDataWithControlValues}
- selectedItems={selectedItems}
- onMonitoredSyncDataAction={onMonitoredSyncDataAction}
- onMonitoredSearchDataAction={onMonitoredSearchDataAction}
- ref={(f) => this[`dashboardItem${id}`] = f}
- />
- </div>
- ))
- layouts.lg.push({
- x,
- y,
- w: width,
- h: height,
- i: `${id}`
- })
- })
- grids = (
- <ResponsiveReactGridLayout
- className={styles.grid}
- rowHeight={GRID_ROW_HEIGHT}
- margin={[GRID_ITEM_MARGIN, GRID_ITEM_MARGIN]}
- breakpoints={GRID_BREAKPOINTS}
- cols={GRID_COLS}
- layouts={layouts}
- onDragStop={this.onDragStop}
- onResizeStop={this.onResizeStop}
- onBreakpointChange={this.onBreakpointChange}
- measureBeforeMount={false}
- draggableHandle={`.${styles.title}`}
- useCSSTransforms={mounted}
- isDraggable={gridEditable}
- isResizable={gridEditable}
- >
- {itemblocks}
- </ResponsiveReactGridLayout>
- )
- }
- const saveDashboardItemButton = (
- <Button
- key="submit"
- size="large"
- type="primary"
- loading={modalLoading}
- disabled={modalLoading}
- onClick={this.saveDashboardItem}
- >
- 保 存
- </Button>
- )
- const modalButtons = dashboardItemFormType === 'add'
- ? dashboardItemFormStep
- ? [(
- <Button
- key="back"
- size="large"
- onClick={this.changeDashboardItemFormStep(0)}
- >
- 上一步
- </Button>
- ), saveDashboardItemButton]
- : [(
- <Button
- key="forward"
- size="large"
- type="primary"
- disabled={selectedWidgets.length === 0}
- onClick={this.changeDashboardItemFormStep(1)}
- >
- 下一步
- </Button>
- )]
- : saveDashboardItemButton
- return (
- <Container>
- <Helmet title={currentDashboard && currentDashboard.name} />
- <ContainerTitle>
- <Row>
- <Col sm={12}>
- <Breadcrumb className={utilStyles.breadcrumb}>
- {
- currentDashboard && (
- <Breadcrumb.Item>
- <Link to="">
- {`${currentDashboard.name} `}
- </Link>
- </Breadcrumb.Item>
- )
- }
- </Breadcrumb>
- </Col>
- <Toolbar
- currentProject={currentProject}
- currentDashboard={currentDashboard}
- showAddDashboardItem={this.showAddDashboardItemForm}
- onOpenSharePanel={this.openDashboardSharePanel}
- onOpenGlobalControlConfig={this.openGlobalControlConfig}
- onOpenLinkageConfig={this.openLinkageConfig}
- onDownloadDashboard={this.initiateDashboardDownloadTask}
- />
- </Row>
- <GlobalControlPanel
- currentDashboard={currentDashboard}
- currentItems={currentItems}
- formedViews={formedViews}
- layoutType={ControlPanelLayoutTypes.Dashboard}
- onGetOptions={this.getControlSelectOptions}
- onSearch={onLoadBatchDataWithControlValues}
- onMonitoredSearchDataAction={onMonitoredSearchDataAction}
- />
- </ContainerTitle>
- <ContainerBody grid ref={this.containerBody}>
- {grids}
- <div className={styles.gridBottom} />
- </ContainerBody>
- <FullScreenPanel
- currentDashboard={currentDashboard}
- widgets={widgets}
- formedViews={formedViews}
- currentItems={currentItems}
- currentItemsInfo={currentItemsInfo}
- onLoadData={onLoadDashboardItemData}
- onGetOptions={this.getControlSelectOptions}
- onSearch={onLoadBatchDataWithControlValues}
- onMonitoredSearchDataAction={onMonitoredSearchDataAction}
- />
- <SharePanel />
- {gridEditable && (
- <>
- <Modal
- title={`${dashboardItemFormType === 'add' ? '新增' : '修改'} Widget`}
- wrapClassName="ant-modal-large"
- visible={dashboardItemFormVisible}
- footer={modalButtons}
- onCancel={this.hideDashboardItemForm}
- afterClose={this.afterDashboardItemFormClose}
- >
- <DashboardItemForm
- type={dashboardItemFormType}
- widgets={widgets || []}
- selectedWidgets={selectedWidgets}
- currentDashboard={this.props.currentDashboard}
- polling={polling}
- step={dashboardItemFormStep}
- onWidgetSelect={this.widgetSelect}
- onPollingSelect={this.pollingSelect}
- wrappedComponentRef={this.refHandles.dashboardItemForm}
- />
- </Modal>
- <DashboardLinkageConfig
- currentDashboard={currentDashboard}
- currentItems={currentItems}
- currentItemsInfo={currentItemsInfo}
- views={formedViews}
- widgets={widgets}
- visible={linkageConfigVisible}
- loading={currentDashboardLoading}
- onGetWidgetInfo={this.getWidgetInfo}
- onSave={this.saveLinkageConfig}
- onCancel={this.closeLinkageConfig}
- linkages={currentLinkages}
- />
- <GlobalControlConfig
- type={ControlPanelTypes.Global}
- originalControls={currentDashboard.config.filters}
- currentItems={currentItems}
- views={views}
- formedViews={formedViews}
- widgets={widgets}
- visible={globalControlConfigVisible}
- loading={currentDashboardLoading}
- queryMode={currentDashboard.config.queryMode}
- onCancel={this.closeGlobalControlConfig}
- onSave={this.saveControls}
- onLoadViews={this.loadViews}
- onLoadViewDetail={onLoadViewsDetail}
- onGetOptions={onLoadColumnDistinctValue}
- />
- </>
- )}
- </Container>
- )
- }
- }
- const mapStateToProps = createStructuredSelector({
- currentProject: makeSelectCurrentProject(),
- dashboards: makeSelectCurrentDashboards(),
- widgets: makeSelectWidgets(),
- views: makeSelectViews(),
- formedViews: makeSelectFormedViews(),
- currentPortal: makeSelectCurrentPortal(),
- currentDashboard: makeSelectCurrentDashboard(),
- currentDashboardLoading: makeSelectCurrentDashboardLoading(),
- currentItems: makeSelectCurrentItems(),
- currentItemsInfo: makeSelectCurrentItemsInfo(),
- currentLinkages: makeSelectCurrentLinkages()
- })
- export function mapDispatchToProps (dispatch) {
- return {
- onLoadDashboardDetail: (
- portalId: number,
- dashboardId: number
- ) => dispatch(loadDashboardDetail(portalId, dashboardId)),
- onAddDashboardItems: (
- portalId: number,
- items: Array<Omit<IDashboardItem, 'id' | 'config'>>,
- resolve: (items: IDashboardItem[]) => void
- ) => dispatch(addDashboardItems(portalId, items, resolve)),
- onEditCurrentDashboard: (
- dashboard: IDashboard,
- type: 'linkage' | 'control',
- resolve: () => void
- ) => dispatch(VizActions.editCurrentDashboard(dashboard, type, resolve)),
- onEditDashboardItem: (
- portalId: number,
- item: IDashboardItem,
- resolve: () => void
- ) => dispatch(editDashboardItem(portalId, item, resolve)),
- onEditDashboardItems: (
- portalId: number,
- items: IDashboardItem[]
- ) => dispatch(editDashboardItems(portalId, items)),
- onDeleteDashboardItem: (
- id: number,
- resolve?: () => void
- ) => dispatch(deleteDashboardItem(id, resolve)),
- onLoadDashboardItemData: (
- renderType: RenderType,
- itemId: number,
- queryConditions?: Partial<IQueryConditions>
- ) => dispatch(loadDashboardItemData(renderType, itemId, queryConditions)),
- onLoadBatchDataWithControlValues: (
- type: ControlPanelTypes,
- relatedItems: number[],
- formValues?: object,
- itemId?: number
- ) => dispatch(loadBatchDataWithControlValues(type, relatedItems, formValues, itemId)),
- onLoadColumnDistinctValue: (
- paramsByViewId: {
- [viewId: string]: Omit<IDistinctValueReqeustParams, 'cache' | 'expired'>
- },
- callback: (options?: object[]) => void
- ) => dispatch(loadColumnDistinctValue(paramsByViewId, callback)),
- onLoadViews: (projectId: number) => dispatch(loadViews(projectId)),
- onLoadViewsDetail: (
- viewIds: number[],
- resolve: (views: IView[]) => void
- ) => dispatch(loadViewsDetail(viewIds, resolve)),
- onClearCurrentDashboard: () => dispatch(clearCurrentDashboard()),
- onInitiateDownloadTask: (
- type: DownloadTypes,
- id?: number,
- itemId?: number
- ) => dispatch(initiateDownloadTask(type, id, itemId)),
- onLoadSelectOptions: (
- controlKey: string,
- requestParams: { [viewId: string]: IDistinctValueReqeustParams },
- itemId?: number
- ) => dispatch(loadSelectOptions(controlKey, requestParams, itemId)),
- onSetSelectOptions: (
- controlKey: string,
- options: any[],
- itemId?: number
- ) => dispatch(setSelectOptions(controlKey, options, itemId)),
- onRenderDashboardItem: (itemId: number) => dispatch(renderDashboardItem(itemId)),
- onResizeDashboardItem: (itemId: number) => dispatch(resizeDashboardItem(itemId)),
- onResizeAllDashboardItem: () => dispatch(resizeAllDashboardItem()),
- onRenderChartError: (itemId: number, error: Error) =>
- dispatch(renderChartError(itemId, error)),
- onOpenSharePanel: (
- id: number,
- type: TShareVizsType,
- title: string,
- itemId?: number
- ) => dispatch(openSharePanel(id, type, title, itemId)),
- onDrillDashboardItem: (
- itemId: number,
- drillHistory: any
- ) => dispatch(drillDashboardItem(itemId, drillHistory)),
- onDrillPathSetting: (
- itemId: number,
- history: any[]
- ) => dispatch(drillPathsetting(itemId, history)),
- onDeleteDrillHistory: (
- itemId: number,
- index: number
- ) => dispatch(deleteDrillHistory(itemId, index)),
- onSelectDashboardItemChart: (
- itemId: number,
- renderType: RenderType,
- selectedItems: number[]
- ) => dispatch(selectDashboardItemChart(itemId, renderType, selectedItems)),
- onSetFullScreenPanelItemId: (itemId: number) => dispatch(setFullScreenPanelItemId(itemId)),
- onMonitoredSyncDataAction: () => dispatch(monitoredSyncDataAction()),
- onMonitoredLinkageDataAction: () => dispatch(monitoredLinkageDataAction()),
- onMonitoredSearchDataAction: () => dispatch(monitoredSearchDataAction())
- }
- }
- const withConnect = connect(mapStateToProps, mapDispatchToProps)
- const withViewReducer = injectReducer({ key: 'view', reducer: viewReducer })
- const withViewSaga = injectSaga({ key: 'view', saga: viewSaga })
- const withControlReducer = injectReducer({ key: 'control', reducer: controlReducer })
- export default compose(
- withViewReducer,
- withControlReducer,
- withViewSaga,
- withConnect
- )(Grid)
|