123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975 |
- /*
- * <<
- * 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, { Suspense } from 'react'
- import Helmet from 'react-helmet'
- import { connect } from 'react-redux'
- import { createStructuredSelector } from 'reselect'
- import { Route } from 'react-router-dom'
- import { compose } from 'redux'
- import injectReducer from 'utils/injectReducer'
- import injectSaga from 'utils/injectSaga'
- import reducer from './reducer'
- import saga from './sagas'
- import projectReducer from '../Projects/reducer'
- import projectSaga from '../Projects/sagas'
- import vizReducer from '../Viz/reducer'
- import vizSaga from '../Viz/sagas'
- import widgetReducer from 'containers/Widget/reducer'
- import widgetSaga from 'containers/Widget/sagas'
- import viewReducer from '../View/reducer'
- import viewSaga from '../View/sagas'
- import DashboardForm from './components/DashboardForm'
- import DashboardAction from './components/DashboardAction'
- import { Button, Icon, Tooltip, Popover, Modal, Input, Tree } from 'antd'
- const TreeNode = Tree.TreeNode
- import { IconProps } from 'antd/lib/icon/index'
- import AntdFormType from 'antd/lib/form/Form'
- const Search = Input.Search
- import { VizActions } from 'containers/Viz/actions'
- import DashboardActions from './actions'
- import WidgetActions from 'containers/Widget/actions'
- import { makeSelectCurrentDashboards, makeSelectCurrentPortal, makeSelectVizLoading } from 'containers/Viz/selectors'
- import { makeSelectCurrentDashboard } from './selectors'
- import { makeSelectWidgets } from 'containers/Widget/selectors'
- import {
- hideNavigator,
- checkNameUniqueAction,
- loadDownloadList,
- downloadFile
- } from '../App/actions'
- import { makeSelectDownloadList, makeSelectDownloadListLoading } from '../App/selectors'
- import { IDownloadRecord } from '../App/types'
- import { DownloadTypes } from '../App/constants'
- import { listToTree, findFirstLeaf } from './components/localPositionUtil'
- import { ProjectActions } from '../Projects/actions'
- const { loadProjectDetail, excludeRoles } = ProjectActions
- import {IExludeRoles} from '../Viz/components/PortalList'
- const styles = require('./Dashboard.less')
- import {makeSelectCurrentProject, makeSelectProjectRoles} from '../Projects/selectors'
- import ModulePermission from '../Account/components/checkModulePermission'
- import { initializePermission } from '../Account/components/checkUtilPermission'
- import { IProject } from '../Projects/types'
- import EditorHeader from 'components/EditorHeader'
- import 'assets/less/resizer.less'
- const SplitPane = React.lazy(() => import('react-split-pane'))
- import {IProjectRoles} from '../Organizations/component/ProjectRole'
- import { OrganizationActions } from '../Organizations/actions'
- const { loadProjectRoles } = OrganizationActions
- import { RouteComponentWithParams } from 'utils/types'
- import { IWidgetFormed } from '../Widget/types'
- import { Grid } from './Loadable'
- interface IDashboardProps extends RouteComponentWithParams {
- modalLoading: {
- portal: boolean
- display: boolean
- editing: boolean
- dashboards: boolean
- slides: boolean
- }
- dashboards: IDashboard[]
- widgets: IWidgetFormed[]
- currentDashboard: IDashboard,
- currentProject: IProject
- currentPortal: any
- projectRoles: IProjectRoles[]
- downloadList: IDownloadRecord[]
- onLoadDashboards: (portalId: number, resolve: any) => void
- onLoadWidgets: (projectId: number) => void
- onAddDashboard: (dashboard: IDashboard, resolve: any) => any
- onEditDashboard: (type: string, dashboard: IDashboard[], resolve: any) => void
- onDeleteDashboard: (id: number, portalId: number, resolve: any) => void
- onHideNavigator: () => void
- onCheckUniqueName: (pathname: string, data: any, resolve: () => any, reject: (error: string) => any) => any
- onLoadPortals: (projectId) => void
- onLoadProjectDetail: (id) => any
- onExcludeRoles: (type: string, id: number, resolve?: any) => any
- onLoadProjectRoles: (id: number) => any
- onInitiateDownloadTask: (id: number, type: DownloadTypes, downloadParams?: any[]) => void
- onLoadDownloadList: () => void
- onDownloadFile: (id) => void
- onLoadViews: (projectId: number) => void
- }
- export interface IDashboard {
- id?: number
- name?: string
- config?: string
- parentId?: number
- dashboardPortalId?: number
- index?: number
- type?: number
- children?: any[]
- }
- interface IDashboardStates {
- formType: 'add' | 'edit' | 'copy' | 'move' | 'delete' | ''
- formVisible: boolean
- expandedKeys: string[],
- autoExpandParent: boolean
- searchValue: IDashboard[]
- dashboardData: any
- itemId: number
- dataList: any[]
- isExpand: boolean
- searchVisible: boolean
- isGrid: boolean
- checkedKeys: any[]
- splitSize: number
- portalTreeWidth: number
- exludeRoles: IExludeRoles[]
- }
- export class Dashboard extends React.Component<IDashboardProps, IDashboardStates> {
- private defaultSplitSize = 190
- private maxSplitSize = this.defaultSplitSize * 1.5
- constructor (props) {
- super(props)
- const splitSize = +localStorage.getItem('dashboardSplitSize') || this.defaultSplitSize
- this.state = {
- formType: '',
- formVisible: false,
- expandedKeys: [],
- autoExpandParent: true,
- searchValue: [],
- dashboardData: [],
- itemId: 0,
- dataList: [],
- isExpand: true,
- searchVisible: false,
- isGrid: true,
- checkedKeys: [],
- splitSize,
- portalTreeWidth: 0,
- exludeRoles: []
- }
- }
- private dashboardForm: AntdFormType = null
- private refHandlers = {
- dashboardForm: (ref) => this.dashboardForm = ref
- }
- public componentWillMount () {
- const {
- match,
- onLoadWidgets,
- onLoadPortals,
- onLoadProjectDetail,
- onLoadProjectRoles
- } = this.props
- const { projectId, portalId } = match.params
- onLoadWidgets(Number(projectId))
- onLoadPortals(projectId)
- onLoadProjectDetail(projectId)
- onLoadProjectRoles(Number(projectId))
- this.initPortal(projectId, portalId)
- }
- public componentWillReceiveProps (nextProps: IDashboardProps) {
- const { match, dashboards } = nextProps
- const { projectId, portalId } = match.params
- if (portalId !== this.props.match.params.portalId) {
- this.initPortal(projectId, portalId)
- }
- if (dashboards !== this.props.dashboards) {
- this.initalDashboardData(dashboards)
- }
- }
- public componentDidMount () {
- this.props.onHideNavigator()
- }
- private initPortal = (projectId, portalId) => {
- const { history, onLoadDashboards } = this.props
- const dashboardId = this.getDashboardIdFromLocation()
- onLoadDashboards(+portalId, (result) => {
- let defaultDashboardId = 0
- const dashboardData = listToTree(result, 0)
- const treeData = {
- id: -1,
- type: 2,
- children: dashboardData
- }
- defaultDashboardId = findFirstLeaf(treeData)
- if (defaultDashboardId >= 0 && !dashboardId) {
- history.replace(`/project/${projectId}/portal/${portalId}/dashboard/${defaultDashboardId}`)
- }
- this.setState({
- dashboardData,
- isGrid: defaultDashboardId >= 0,
- portalTreeWidth: Number(localStorage.getItem('dashboardSplitSize'))
- })
- this.expandAll(result)
- })
- }
- private initalDashboardData = (dashboards) => {
- this.setState({
- dashboardData: listToTree(dashboards, 0)
- })
- this.expandAll(dashboards)
- }
- private getDashboardIdFromLocation = () => {
- const urlPieces = location.href.split('/')
- const lastModuleName = urlPieces[urlPieces.length - 2]
- const lastModuleId = urlPieces[urlPieces.length - 1]
- return lastModuleName === 'dashboard' ? Number(lastModuleId) : 0
- }
- private changeDashboard = (dashboardId) => (e) => {
- const { match, history } = this.props
- const { projectId, portalId } = match.params
- const currentDashboardId = this.getDashboardIdFromLocation()
- if (currentDashboardId === dashboardId) {
- return
- }
- this.setState({
- isGrid: true
- }, () => {
- history.replace(`/project/${projectId}/portal/${portalId}/dashboard/${dashboardId}`)
- })
- }
- private hideDashboardForm = () => {
- this.setState({
- formVisible: false,
- checkedKeys: []
- }, () => {
- this.dashboardForm.props.form.resetFields()
- })
- }
- private onModalOk = () => {
- const { formType, checkedKeys } = this.state
- if (formType === 'delete') {
- const id = this.dashboardForm.props.form.getFieldValue('id')
- this.confirmDeleteDashboard(id)
- } else {
- this.dashboardForm.props.form.validateFieldsAndScroll((err, values) => {
- if (!err) {
- const { dashboards, match, history, onEditDashboard, onAddDashboard } = this.props
- const { id, name, folder, selectType, index, config } = values
- const dashArr = folder === '0'
- ? dashboards.filter((d) => d.parentId === 0)
- : dashboards.filter((d) => d.parentId === Number(folder))
- const indexTemp = dashArr.length === 0 ? 0 : dashArr[dashArr.length - 1].index + 1
- const obj = {
- config,
- dashboardPortalId: +match.params.portalId,
- name,
- // type: selectType ? 1 : 0 // todo selectType 更改位置
- type: Number(selectType)
- }
- const addObj = {
- ...obj,
- parentId: Number(folder),
- index: indexTemp,
- roleIds: this.state.exludeRoles.filter((role) => !role.permission).map((p) => p.id)
- }
- const editObj = [{
- ...obj,
- parentId: Number(folder),
- id,
- index,
- roleIds: this.state.exludeRoles.filter((role) => !role.permission).map((p) => p.id)
- }]
- const currentArr = dashboards.filter((d) => d.parentId === Number(folder))
- const moveObj = [{
- ...obj,
- parentId: Number(folder),
- id,
- index: currentArr.length ? currentArr[currentArr.length - 1].index + 1 : 0
- }]
- switch (formType) {
- case 'add':
- // case 'copy':
- onAddDashboard(addObj, (dashboardId) => {
- this.hideDashboardForm()
- this.setState({ isGrid: true })
- const { projectId, portalId } = match.params
- addObj.type === 0
- ? history.replace(`/project/${projectId}/portal/${portalId}`)
- : history.replace(`/project/${projectId}/portal/${portalId}/dashboard/${dashboardId}`)
- })
- break
- case 'edit':
- onEditDashboard('edit', editObj, () => { this.hideDashboardForm() })
- break
- case 'move':
- onEditDashboard('move', moveObj, () => { this.hideDashboardForm() })
- break
- }
- }
- })
- }
- }
- private onExpand = (expandedKeys) => {
- this.setState({
- expandedKeys,
- autoExpandParent: false
- })
- }
- private onDrop = (info) => {
- const { dashboards } = this.props
- const dragKey = info.dragNode.props.eventKey // 开始(要拖拽元素)id Number(dragKey) === dragNodesKeys[0] === 每一项的id
- // const dragPos = info.dragNode.props.pos // 开始的位置'0-1-0'
- const dropKey = info.node.props.eventKey // 结束的id
- // const dropPos = info.node.props.pos.split('-')// 结束位置的树形结构层级'0-1'
- // const dropPosition = info.dropPosition - Number(dropPos[dropPos.length - 1])
- // const dragNodesKeys = info.dragNodesKeys;
- const loop = (data, key, callback) => {
- data.forEach((item, index, arr) => {
- if (item.id === Number(key)) {
- return callback(item, index, arr)
- }
- if (item.children) {
- return loop(item.children, key, callback)
- }
- })
- }
- const data = [...this.state.dashboardData]
- let dragItem = null
- loop(data, dragKey, (item) => {
- dragItem = item
- })
- // let dragObj
- loop(data, dropKey, (item, i, arr) => {
- const { config, dashboardPortalId, id, name, type } = dragItem
- let dropObj = dashboards.find((d) => d.id === Number(dropKey))
- const dropObjParentId = dropObj.parentId
- let value = []
- if (!info.dropToGap && dropObj.type === 1) {
- if (dragItem.type === 0) {
- return
- }
- }
- if (!info.dropToGap && dropObj.type === 0) {
- const currentArr = dropObj.children
- value = [{
- config,
- dashboardPortalId,
- id,
- index: currentArr.length ? currentArr[currentArr.length - 1].index + 1 : 0,
- name,
- parentId: Number(dropKey),
- type
- }]
- this.props.onEditDashboard('move', value, (result) => {
- // dragObj = result
- })
- return
- }
- let partArr = Number(dropObj.parentId) === 0
- ? dashboards.filter((d) => d.parentId === 0)
- : (dashboards.find((d) => d.id === Number(dropObj.parentId))).children
- dropObj = i > info.dropPosition ? partArr[i] : partArr[i + 1] // a trick 判断拖拽位置是哪条线,如果是下面那条线则上移一位
- const dropObjIndex = dropObj ? dropObj.index : partArr[i].index + 1
- if (!dropObj) {
- value.unshift({
- config,
- dashboardPortalId,
- id,
- index: dropObjIndex,
- name,
- parentId: dropObjParentId,
- type
- })
- }
- if (!!dropObj && (info.dropToGap || dropObj.type === 1)) {
- // const dropObj = dashboards.find((d) => d.id === Number(dropKey))
- partArr = Number(dropObj.parentId) === 0
- ? dashboards.filter((d) => d.parentId === 0)
- : (dashboards.find((d) => d.id === Number(dropObj.parentId))).children
- const othersArr = partArr.filter((p) => p.index >= dropObj.index).filter((o) => o.id !== id)
- value = othersArr.map((o) => {
- const { config, dashboardPortalId, id, index, name, parentId, type } = o
- return {
- config,
- dashboardPortalId,
- id,
- index: index + 1,
- name,
- parentId,
- type
- }
- })
- value.unshift({
- config,
- dashboardPortalId,
- id,
- index: dropObjIndex,
- name,
- parentId: dropObj.parentId,
- type
- })
- }
- this.props.onEditDashboard('move', value, (result) => {
- // dragObj = result
- })
- })
- this.setState({
- dashboardData: data
- })
- }
- private onAddItem = () => {
- this.setState({
- formVisible: true,
- formType: 'add'
- }, () => {
- this.setState({
- exludeRoles: this.props.projectRoles.map((role) => {
- return {
- ...role,
- permission: true
- }
- })
- })
- })
- }
- private onCollapseAll = () => {
- this.onExpand([])
- this.setState({
- isExpand: false
- })
- }
- private onExpandAll = () => {
- const { dashboards } = this.props
- if (dashboards) {
- this.expandAll(dashboards)
- }
- }
- private expandAll (dashboards) {
- const expandArr = []
- dashboards.filter((d) => d.type === 0)
- .forEach((i) => expandArr.push(`${i.id}`))
- this.onExpand(expandArr)
- this.setState({
- isExpand: true
- })
- }
- private onShowDashboardForm (item, formType) {
- const { dashboards, match, onLoadDashboards } = this.props
- this.setState({
- formVisible: true,
- itemId: item.id
- }, () => {
- onLoadDashboards(+match.params.portalId, (result) => {
- setTimeout(() => {
- const {
- config,
- id,
- name,
- parentId,
- type,
- index
- } = (result as any[]).find((g) => g.id === item.id)
- this.dashboardForm.props.form.setFieldsValue({
- id,
- folder: parentId ? `${(dashboards as any[]).find((g) => g.id === parentId).id}` : '0',
- config,
- name: formType === 'copy' ? `${name}_copy` : name,
- // selectType: type === 1,
- selectType: type,
- index
- })
- }, 0)
- })
- const { onExcludeRoles, projectRoles } = this.props
- if (onExcludeRoles && item && item.id) {
- onExcludeRoles('dashboard', item.id, (result: number[]) => {
- this.setState({
- exludeRoles: projectRoles.map((role) => {
- return result.some((re) => re === role.id) ? {...role, permission: false} : {...role, permission: true}
- })
- })
- })
- }
- })
- }
- private onOperateMore = (item, type) => {
- if (type === 'download') {
- this.props.onInitiateDownloadTask(item.id, item.type === 0 ? DownloadTypes.Folder : DownloadTypes.Dashboard, [])
- } else {
- this.setState({
- formType: type
- }, () => {
- this.onShowDashboardForm(item, this.state.formType)
- })
- }
- }
- private searchDashboard = (e) => {
- const { dashboards } = this.props
- const { value } = e.target
- this.setState({
- searchValue: value ? dashboards.filter((d) => d.name.includes(value)) : []
- })
- }
- private pickSearchDashboard = (dashboardId) => (e) => {
- const { dashboards } = this.props
- this.setState({
- searchVisible: false
- })
- const currentDashoboard = dashboards.find((d) => d.id === dashboardId)
- if (currentDashoboard.type === 1) {
- this.changeDashboard(dashboardId)(e)
- } else if (currentDashoboard.type === 0) {
- const currentFolderArr = dashboards.filter((d) => d.parentId === dashboardId)
- if (currentFolderArr.length !== 0) {
- this.changeDashboard(currentFolderArr[0].id)(e)
- }
- }
- }
- private confirmDeleteDashboard = (id) => {
- const { match, history, onDeleteDashboard, dashboards } = this.props
- const { dashboardData } = this.state
- const dashboardId = this.getDashboardIdFromLocation()
- onDeleteDashboard(id, +match.params.portalId, () => {
- const { projectId, portalId } = match.params
- const paramsDashboard = dashboards.find((d) => d.id === dashboardId)
- const noCurrentDashboards = dashboardData.filter((d) => d.id !== id)
- if (noCurrentDashboards.length !== 0 && paramsDashboard) {
- const remainDashboards = noCurrentDashboards.filter((r) => r.parentId !== id)
- const treeData = {
- id: -1,
- type: 2,
- children: remainDashboards
- }
- if (dashboardId === id || paramsDashboard.parentId === id) {
- const defaultDashboardId = findFirstLeaf(treeData)
- history.replace(`/project/${projectId}/portal/${portalId}/dashboard/${defaultDashboardId}`)
- }
- } else {
- history.replace(`/project/${projectId}/portal/${portalId}/dashboard/-1`)
- this.setState({
- isGrid: false
- })
- }
- this.hideDashboardForm()
- })
- }
- private searchVisibleChange = (visible) => {
- this.setState({
- searchVisible: visible
- })
- }
- private handleTree = (clickKey, obj) => {
- const { expandedKeys } = this.state
- this.setState({
- autoExpandParent: false
- })
- if (obj.selected) {
- if (expandedKeys.indexOf(clickKey[0]) < 0) {
- expandedKeys.push(clickKey[0])
- this.setState({
- expandedKeys
- })
- } else {
- this.setState({
- expandedKeys: expandedKeys.filter((e) => e !== clickKey[0])
- })
- }
- } else {
- let currentKey = []
- if (expandedKeys.length === 0) {
- expandedKeys.push(obj.node.props.eventKey)
- currentKey = expandedKeys
- } else {
- currentKey = expandedKeys.filter((e) => e !== obj.node.props.title)
- }
- this.setState({
- expandedKeys: currentKey
- })
- }
- }
- private cancel = () => {
- const { history, match } = this.props
- const prefix = window.localStorage.getItem('inDataService') ?? ''
- const prefixPath = prefix ? '/' + prefix : prefix
- history.replace(`/project/${match.params.projectId}${prefixPath}/vizs`)
- }
- private initCheckNodes = (checkedKeys) => {
- this.setState({
- checkedKeys
- })
- }
- private changePortalTreeWidth = (newSize: number) => {
- this.setState({
- portalTreeWidth: newSize
- })
- }
- private saveSplitSize = (newSize: number) => {
- localStorage.setItem('dashboardSplitSize', newSize.toString())
- this.changePortalTreeWidth(newSize)
- // triggering ResponsiveReactGridLayout readjustment
- const resizeEvent = document.createEvent('Event')
- resizeEvent.initEvent('resize', false, true)
- window.dispatchEvent(resizeEvent)
- }
- private changePermission = (scope: IExludeRoles, event) => {
- scope.permission = event.target.checked
- this.setState({
- exludeRoles: this.state.exludeRoles.map((role) => role && role.id === scope.id ? scope : role)
- })
- }
- public render () {
- const {
- match,
- currentDashboard,
- dashboards,
- widgets,
- modalLoading,
- currentProject,
- currentPortal,
- downloadList,
- onCheckUniqueName,
- onLoadDownloadList,
- onDownloadFile
- } = this.props
- const {
- formType,
- formVisible,
- searchValue,
- dashboardData,
- isGrid,
- searchVisible,
- checkedKeys,
- splitSize,
- portalTreeWidth
- } = this.state
- const items = searchValue.map((s) => {
- return <li key={s.id} onClick={this.pickSearchDashboard(s.id)}>{s.name}</li>
- })
- const dashboardId = this.getDashboardIdFromLocation().toString()
- let modalTitle = ''
- switch (formType) {
- case 'add':
- modalTitle = '新增'
- break
- case 'edit':
- modalTitle = '修改'
- break
- case 'copy':
- modalTitle = '复制'
- break
- case 'move':
- modalTitle = '移动'
- break
- case 'delete':
- modalTitle = '提示'
- break
- }
- const modalButtons = [(
- <Button
- key="back"
- size="large"
- onClick={this.hideDashboardForm}
- >
- 取 消
- </Button>
- ), (
- <Button
- key="submit"
- size="large"
- type="primary"
- loading={modalLoading.editing}
- onClick={this.onModalOk}
- >
- {formType === 'delete' ? '确 定' : '保 存'}
- </Button>
- )]
- const loop = (data, depth = 0) => data.map((item) => {
- const dashboardAction = (
- <DashboardAction
- currentProject={currentProject}
- depth={depth}
- item={item}
- splitWidth={portalTreeWidth || 190}
- onInitOperateMore={this.onOperateMore}
- initChangeDashboard={this.changeDashboard}
- />
- )
- if (item.type === 0) {
- return (
- <TreeNode icon={<Icon type="smile-o" />} key={item.id} title={dashboardAction} >
- {loop(item.children, depth + 1)}
- </TreeNode>
- )
- }
- return <TreeNode icon={<Icon type="smile-o" />} key={item.id} title={dashboardAction} />
- })
- const AdminIcon = ModulePermission<IconProps>(currentProject, 'viz', true)(Icon)
- const portalName = currentPortal && currentPortal.name
- const portalDesc = currentPortal && currentPortal.description
- return (
- <div className={styles.portal}>
- <EditorHeader
- className={styles.portalHeader}
- currentType="dashboard"
- name={portalName}
- description={portalDesc}
- downloadList={downloadList}
- onCancel={this.cancel}
- onLoadDownloadList={onLoadDownloadList}
- onDownloadFile={onDownloadFile}
- />
- <Helmet title={portalName} />
- <div className={styles.portalBody}>
- <Suspense fallback={null}>
- <SplitPane
- split="vertical"
- defaultSize={splitSize}
- minSize={this.defaultSplitSize}
- maxSize={this.maxSplitSize}
- onChange={this.changePortalTreeWidth}
- onDragFinished={this.saveSplitSize}
- >
- <div className={styles.portalTree} style={{ width: portalTreeWidth || 190 }}>
- <div className={styles.portalRow}>
- <span className={styles.portalAction}>
- <Popover
- placement="bottom"
- content={
- <div className={styles.portalTreeSearch}>
- <Search
- placeholder="Search"
- onChange={this.searchDashboard}
- />
- <ul>
- {items}
- </ul>
- </div>}
- trigger="click"
- visible={searchVisible}
- onVisibleChange={this.searchVisibleChange}
- >
- <Tooltip placement="top" title="搜索">
- <Icon
- type="search"
- className={styles.search}
- />
- </Tooltip>
- </Popover>
- <Tooltip placement="top" title="新增">
- <AdminIcon
- type="plus"
- className={styles.plus}
- onClick={this.onAddItem}
- />
- </Tooltip>
- <Popover
- placement="bottom"
- content={
- <ul className={styles.menu}>
- <li onClick={this.onCollapseAll}>收起全部</li>
- <li onClick={this.onExpandAll}>展开全部</li>
- </ul>}
- trigger="click"
- >
- <Tooltip placement="top" title="更多">
- <Icon
- type="ellipsis"
- className={styles.more}
- />
- </Tooltip>
- </Popover>
- </span>
- </div>
- { dashboardData.length
- ? <div className={styles.portalTreeNode}>
- <Tree
- onExpand={this.onExpand}
- expandedKeys={this.state.expandedKeys}
- autoExpandParent={this.state.autoExpandParent}
- selectedKeys={[dashboardId]}
- draggable={initializePermission(currentProject, 'vizPermission')}
- onDrop={this.onDrop}
- onSelect={this.handleTree}
- >
- {loop(dashboardData)}
- </Tree>
- </div>
- : isGrid ? <h3 className={styles.loadingTreeMsg}>Loading tree......</h3> : ''
- }
- </div>
- <div className={styles.gridClass}>
- {
- isGrid && widgets
- ? <Route path="/project/:projectId/portal/:portalId/dashboard/:dashboardId" component={Grid} />
- : (
- <div className={styles.noDashboard}>
- <img src={require('assets/images/noDashboard.png')} onClick={this.onAddItem}/>
- <p>请创建文件夹或 Dashboard</p>
- </div>
- )
- }
- </div>
- </SplitPane>
- </Suspense>
- </div>
- <Modal
- title={modalTitle}
- wrapClassName="ant-modal-small"
- visible={formVisible}
- footer={modalButtons}
- onCancel={this.hideDashboardForm}
- >
- <DashboardForm
- type={formType}
- itemId={this.state.itemId}
- dashboards={dashboards}
- portalId={Number(match.params.portalId)}
- exludeRoles={this.state.exludeRoles}
- onCheckUniqueName={onCheckUniqueName}
- onChangePermission={this.changePermission}
- wrappedComponentRef={this.refHandlers.dashboardForm}
- />
- </Modal>
- </div>
- )
- }
- }
- const mapStateToProps = createStructuredSelector({
- dashboards: makeSelectCurrentDashboards(),
- widgets: makeSelectWidgets(),
- currentDashboard: makeSelectCurrentDashboard(),
- modalLoading: makeSelectVizLoading(),
- currentProject: makeSelectCurrentProject(),
- currentPortal: makeSelectCurrentPortal(),
- projectRoles: makeSelectProjectRoles(),
- downloadList: makeSelectDownloadList()
- })
- export function mapDispatchToProps (dispatch) {
- return {
- onLoadDashboards: (portalId, resolve) => dispatch(VizActions.loadPortalDashboards(portalId, resolve, false)),
- onLoadWidgets: (projectId: number) => dispatch(WidgetActions.loadWidgets(projectId)),
- onAddDashboard: (dashboard, resolve) => dispatch(VizActions.addDashboard(dashboard, resolve)),
- onEditDashboard: (formType, dashboard, resolve) => dispatch(VizActions.editDashboard(formType, dashboard, resolve)),
- onDeleteDashboard: (id, portalId, resolve) => dispatch(VizActions.deleteDashboard(id, portalId, resolve)),
- onHideNavigator: () => dispatch(hideNavigator()),
- onCheckUniqueName: (pathname, data, resolve, reject) => dispatch(checkNameUniqueAction(pathname, data, resolve, reject)),
- onLoadPortals: (projectId) => dispatch(VizActions.loadPortals(projectId)),
- onLoadProjectDetail: (id) => dispatch(loadProjectDetail(id)),
- onExcludeRoles: (type, id, resolve) => dispatch(excludeRoles(type, id, resolve)),
- onLoadProjectRoles: (id) => dispatch(loadProjectRoles(id)),
- onInitiateDownloadTask: (id, type, downloadParams?) => dispatch(DashboardActions.initiateDownloadTask(id, type, downloadParams)),
- onLoadDownloadList: () => dispatch(loadDownloadList()),
- onDownloadFile: (id) => dispatch(downloadFile(id))
- }
- }
- const withConnect = connect(mapStateToProps, mapDispatchToProps)
- const withReducer = injectReducer({ key: 'dashboard', reducer })
- const withSaga = injectSaga({ key: 'dashboard', saga })
- const withProjectReducer = injectReducer({ key: 'project', reducer: projectReducer })
- const withProjectSaga = injectSaga({ key: 'project', saga: projectSaga })
- const withVizReducer = injectReducer({ key: 'viz', reducer: vizReducer })
- const withVizSaga = injectSaga({ key: 'viz', saga: vizSaga })
- const withWidgetReducer = injectReducer({ key: 'widget', reducer: widgetReducer })
- const withWidgetSaga = injectSaga({ key: 'widget', saga: widgetSaga })
- const withViewReducer = injectReducer({ key: 'view', reducer: viewReducer })
- const withViewSaga = injectSaga({ key: 'view', saga: viewSaga })
- export default compose(
- withReducer,
- withProjectReducer,
- withVizReducer,
- withWidgetReducer,
- withViewReducer,
- withSaga,
- withProjectSaga,
- withVizSaga,
- withWidgetSaga,
- withViewSaga,
- withConnect
- )(Dashboard)
|