import { useField, useFieldSchema } from '@formily/react'; import { GeneralSchemaDesigner, SchemaSettingsBlockTitleItem, SchemaSettingsDivider, SchemaSettingsItem, SchemaSettingsRemove, gridRowColWrap, useAPIClient, useCollection_deprecated, useDataSource, useDesignable, } from '@nocobase/client'; import { Empty, Result, Spin, Typography } from 'antd'; import React, { useContext, useEffect, useRef } from 'react'; import { ErrorBoundary } from 'react-error-boundary'; import { ChartConfigContext } from '../configure'; import { useData, useFieldTransformer, useFieldsWithAssociation } from '../hooks'; import { useChartsTranslation } from '../locale'; import { createRendererSchema, getField } from '../utils'; import { ChartRendererContext } from './ChartRendererProvider'; import { useChart } from '../chart/group'; import { ChartDataContext } from '../block/ChartDataProvider'; const { Paragraph, Text } = Typography; export const ChartRenderer: React.FC & { Designer: React.FC; } = (props) => { const { t } = useChartsTranslation(); const ctx = useContext(ChartRendererContext); const { config, transform, dataSource, collection, service, data: _data } = ctx; const fields = useFieldsWithAssociation(dataSource, collection); const data = useData(_data, dataSource, collection); const general = config?.general || {}; const advanced = config?.advanced || {}; const api = useAPIClient(); const chartRef = useRef(null); const [height, setHeight] = React.useState(0); const chart = useChart(config?.chartType); const locale = api.auth.getLocale(); const transformers = useFieldTransformer(transform, locale); const chartProps = chart?.getProps({ data, general, advanced, fieldProps: Object.keys(data[0] || {}).reduce((props, name) => { if (!props[name]) { const field = getField(fields, name.split('.')); const transformer = transformers[name]; props[name] = { label: field?.label || name, transformer, interface: field?.interface }; } return props; }, {}), }); const C = chart?.Component; useEffect(() => { const el = chartRef.current; if (!el || service.loading === true) { return; } const observer = new ResizeObserver((entries) => { entries.forEach((entry) => { setHeight(entry.contentRect.height); }); }); observer.observe(el); return () => observer.disconnect(); }, [service.loading]); if (!chart) { return ; } if (!(data && data.length) && !service.loading) { return ; } return ( { console.error(error); }} FallbackComponent={ErrorFallback} >
); }; ChartRenderer.Designer = function Designer() { const { t } = useChartsTranslation(); const { setVisible, setCurrent } = useContext(ChartConfigContext); const { removeChart } = useContext(ChartDataContext); const { service } = useContext(ChartRendererContext); const field = useField(); const schema = useFieldSchema(); const { insertAdjacent } = useDesignable(); const dataSource = useDataSource(); const { name, title } = useCollection_deprecated(); return ( { setCurrent({ schema, field, dataSource: dataSource.key, collection: name, service, data: service.data }); setVisible(true); }} > {t('Configure')} insertAdjacent('afterEnd', gridRowColWrap(createRendererSchema(schema?.['x-decorator-props'])))} > {t('Duplicate')} { removeChart(schema['x-uid']); }, }} /> ); }; const ErrorFallback = ({ error }) => { const { t } = useChartsTranslation(); return (
{error.message}
); };