123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387 |
- /*
- * <<
- * 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, { PureComponent, GetDerivedStateFromProps } from 'react'
- import {
- IControl,
- OnGetControlOptions,
- IMapControlOptions,
- IRenderTreeItem
- } from '../types'
- import { IFormedViews, IShareFormedViews } from 'app/containers/View/types'
- import {
- getVariableParams,
- getFilterParams,
- getAllChildren,
- getParents,
- getPanelRenderState,
- getCustomOptionVariableParams,
- cleanInvisibleConditionalControlValues
- } from '../util'
- import {
- SHOULD_LOAD_OPTIONS,
- CHANGE_IMMEDIATELY,
- ControlPanelTypes,
- ControlPanelLayoutTypes,
- ControlQueryMode,
- ControlFieldTypes,
- ControlOptionTypes
- } from '../constants'
- import DashboardControlPanelLayout from './Layouts/Dashboard'
- import DashboardItemControlPanelLayout from './Layouts/DashboardItem'
- import FullScreenControlPanelLayout from './Layouts/FullScreen'
- interface IControlPanelProps {
- controls: IControl[]
- formedViews: IFormedViews | IShareFormedViews
- items: string
- type: ControlPanelTypes
- layoutType: ControlPanelLayoutTypes
- viewId?: number
- reload: boolean
- queryMode: ControlQueryMode
- formValues: object
- mapOptions: IMapControlOptions
- onGetOptions: OnGetControlOptions
- onChange: (formValues: object) => void
- onSearch: (formValues?: object) => void
- }
- interface IControlPanelStates {
- renderTree: IRenderTreeItem[]
- flatTree: {
- [key: string]: IRenderTreeItem
- }
- defaultValues: object
- prevControls: IControl[]
- prevItems: string
- }
- class ControlPanel extends PureComponent<
- IControlPanelProps,
- IControlPanelStates
- > {
- public state: IControlPanelStates = {
- renderTree: [],
- flatTree: {},
- defaultValues: {},
- prevControls: [],
- prevItems: ''
- }
- public static getDerivedStateFromProps: GetDerivedStateFromProps<
- IControlPanelProps,
- IControlPanelStates
- > = (props, state) => {
- const { type, controls, items } = props
- let nextState: Partial<IControlPanelStates> = {
- prevControls: controls,
- prevItems: items
- }
- if (state.prevControls !== controls || state.prevItems !== items) {
- nextState = {
- ...nextState,
- ...getPanelRenderState(type, controls, items)
- }
- }
- return nextState
- }
- public componentDidMount() {
- this.initFormValuesAndSelectOptions(
- this.props,
- this.state,
- Object.keys(this.props.formValues).length > 0
- )
- }
- public componentDidUpdate(prevProps: IControlPanelProps) {
- const { controls, reload, onSearch } = this.props
- const { defaultValues } = this.state
- if (prevProps.controls !== controls) {
- this.initFormValuesAndSelectOptions(this.props, this.state, false)
- }
- if (reload) {
- onSearch(defaultValues)
- }
- }
- private initFormValuesAndSelectOptions(
- props: IControlPanelProps,
- state: IControlPanelStates,
- initiated: boolean
- ) {
- const { formValues, onChange } = props
- const { flatTree, defaultValues } = state
- const initialFormValues = initiated ? formValues : defaultValues
- onChange(initialFormValues)
- Object.values(flatTree).forEach((control) => {
- if (SHOULD_LOAD_OPTIONS[control.type]) {
- this.loadOptions(control, flatTree, initialFormValues)
- }
- })
- }
- private loadOptions = (
- renderControl: IRenderTreeItem,
- flatTree: { [key: string]: IRenderTreeItem },
- controlValues: { [key: string]: any }
- ) => {
- const { formedViews, type, items, onGetOptions } = this.props
- const {
- key,
- parent,
- cache,
- expired,
- optionType,
- valueViewId,
- valueField,
- textField,
- parentField,
- customOptions,
- relatedViews
- } = renderControl
- if (optionType === ControlOptionTypes.Custom) {
- onGetOptions(
- key,
- true,
- customOptions,
- type === ControlPanelTypes.Local ? Number(items) : void 0
- )
- } else {
- const parents = getParents(parent, flatTree)
- const requestParams = {}
- // get cascading conditions
- Object.entries(relatedViews).forEach(([viewId, relatedView]) => {
- let filters = []
- let variables = []
- parents.forEach((parentControl) => {
- const parentValue = controlValues[parentControl.key]
- Object.entries(parentControl.relatedViews).forEach(
- ([parentViewId, parentRelatedView]) => {
- if (viewId === parentViewId) {
- let cascadeRelatedViewId: string | number
- let cascadeRelatedFields: string[]
- let onlyFilters = false
- switch (optionType) {
- case ControlOptionTypes.Auto:
- cascadeRelatedViewId = parentViewId
- cascadeRelatedFields = parentRelatedView.fields
- break
- case ControlOptionTypes.Manual:
- if (
- parentControl.optionType === ControlOptionTypes.Auto &&
- valueViewId === Number(parentViewId)
- ) {
- cascadeRelatedViewId = parentViewId
- cascadeRelatedFields = parentRelatedView.fields
- } else if (
- parentControl.optionType === ControlOptionTypes.Manual &&
- valueViewId === parentControl.valueViewId
- ) {
- cascadeRelatedViewId = parentControl.valueViewId
- cascadeRelatedFields = [parentControl.valueField]
- onlyFilters = true
- }
- break
- }
- if (
- cascadeRelatedViewId &&
- cascadeRelatedFields &&
- formedViews[cascadeRelatedViewId]
- ) {
- const { model, variable } = formedViews[cascadeRelatedViewId]
- if (onlyFilters) {
- filters = filters.concat(
- getFilterParams(
- parentControl,
- cascadeRelatedFields,
- parentValue,
- model
- )
- )
- } else {
- if (parentControl.optionWithVariable) {
- variables = variables.concat(
- getCustomOptionVariableParams(
- parentControl,
- Number(cascadeRelatedViewId),
- parentValue,
- variable
- )
- )
- } else {
- if (
- parentRelatedView.fieldType === ControlFieldTypes.Column
- ) {
- filters = filters.concat(
- getFilterParams(
- parentControl,
- cascadeRelatedFields,
- parentValue,
- model
- )
- )
- } else {
- variables = variables.concat(
- getVariableParams(
- parentControl,
- cascadeRelatedFields,
- parentValue,
- variable
- )
- )
- }
- }
- }
- }
- }
- }
- )
- })
- switch (optionType) {
- case ControlOptionTypes.Auto:
- if (relatedView.fieldType === ControlFieldTypes.Column) {
- requestParams[viewId] = {
- columns: relatedView.fields,
- filters,
- variables,
- cache,
- expired
- }
- }
- break
- case ControlOptionTypes.Manual:
- requestParams[valueViewId] = {
- columns: [valueField, textField, parentField].filter((f) => !!f),
- filters,
- variables,
- cache,
- expired
- }
- break
- }
- })
- if (Object.keys(requestParams).length) {
- onGetOptions(
- key,
- false,
- requestParams,
- type === ControlPanelTypes.Local ? Number(items) : void 0
- )
- }
- }
- }
- private change = (control: IControl, val) => {
- const { controls, queryMode, formValues, onChange, onSearch } = this.props
- const { flatTree } = this.state
- const { key, type } = control
- const childrenKeys = getAllChildren(key, flatTree)
- const controlValue = {
- [key]: val
- }
- const cleanedInvisibleValues = cleanInvisibleConditionalControlValues(
- controls,
- control,
- formValues
- )
- const updatedFormValues = {
- ...formValues,
- ...controlValue,
- ...cleanedInvisibleValues
- }
- if (childrenKeys.length) {
- childrenKeys.forEach((childKey) => {
- const child = flatTree[childKey]
- if (SHOULD_LOAD_OPTIONS[child.type]) {
- this.loadOptions(child, flatTree, updatedFormValues)
- }
- })
- }
- onChange(updatedFormValues)
- if (
- queryMode === ControlQueryMode.Immediately &&
- CHANGE_IMMEDIATELY[type]
- ) {
- onSearch(controlValue)
- }
- }
- private reset = () => {
- const { queryMode, onChange, onSearch } = this.props
- const { defaultValues } = this.state
- onChange(defaultValues)
- if (queryMode === ControlQueryMode.Immediately) {
- onSearch(defaultValues)
- }
- }
- public render() {
- const {
- layoutType,
- queryMode,
- formValues,
- mapOptions,
- onSearch
- } = this.props
- const { renderTree } = this.state
- const layoutProps = {
- queryMode,
- renderTree,
- formValues,
- mapOptions,
- onChange: this.change,
- onSearch,
- onReset: this.reset
- }
- switch (layoutType) {
- case ControlPanelLayoutTypes.Dashboard:
- return <DashboardControlPanelLayout {...layoutProps} />
- case ControlPanelLayoutTypes.DashboardItem:
- return <DashboardItemControlPanelLayout {...layoutProps} />
- case ControlPanelLayoutTypes.Fullscreen:
- return <FullScreenControlPanelLayout {...layoutProps} />
- default:
- return null
- }
- }
- }
- export default ControlPanel
|