tachybase_todo/packages/plugins/@nocobase/plugin-data-visualization/src/client/renderer/ChartRendererProvider.tsx
sealday 2d991ba7cf 合并对main的所有修改
<!-- Note -->
<!-- This is a template for submitting a new feature.
Use the bug fix template if you're submitting a bug fix pull request by adding `template=bug_fix.md` to your pull request URL. -->

<!-- Describe the new feature or modification to an existing feature clearly and consciously. -->

<!-- Explain the reason for adding or modifying this feature. -->

<!-- Provide a technically detailed description of the key changes made. -->
- Frontend
- Backend

<!-- Provide any suggestions or recommendations for improvements in the testing plan. -->

<!-- Identify any potential risks or issues that may arise from the new feature or modification. -->

<!-- Including any screenshots of the new feature or modification. -->

Co-authored-by: sealday <sealday@gmail.com>
Co-authored-by: wjh <wwwjh0710@163.com>
Co-authored-by: 吕延祥 <2256334253@qq.com>
Reviewed-on: daoyoucloud/nocobase#317
2024-03-10 04:06:04 +08:00

145 lines
4.4 KiB
TypeScript

import { useFieldSchema } from '@formily/react';
import {
CollectionManagerProvider,
MaybeCollectionProvider,
useAPIClient,
useDataSourceManager,
useRequest,
} from '@nocobase/client';
import React, { createContext, useContext } from 'react';
import { parseField, removeUnparsableFilter } from '../utils';
import { ChartDataContext } from '../block/ChartDataProvider';
import { ConfigProvider } from 'antd';
import { useChartFilter } from '../hooks';
import { ChartFilterContext } from '../filter/FilterProvider';
export type MeasureProps = {
field: string | string[];
aggregation?: string;
alias?: string;
};
export type DimensionProps = {
field: string | string[];
alias?: string;
format?: string;
};
export type TransformProps = {
field: string;
type: string;
format: string;
specific?: string;
};
export type QueryProps = Partial<{
measures: MeasureProps[];
dimensions: DimensionProps[];
orders: {
field: string;
order: 'asc' | 'desc';
}[];
filter: any;
limit: number;
sql: {
fields?: string;
clauses?: string;
};
}>;
export type ChartRendererProps = {
collection: string;
dataSource?: string;
query?: QueryProps;
config?: {
chartType: string;
general: any;
advanced: any;
};
transform?: TransformProps[];
mode?: 'builder' | 'sql';
};
export const ChartRendererContext = createContext<
{
service: any;
data?: any[];
} & ChartRendererProps
>({} as any);
ChartRendererContext.displayName = 'ChartRendererContext';
export const ChartRendererProvider: React.FC<ChartRendererProps> = (props) => {
const { query, config, collection, transform, dataSource } = props;
const { addChart } = useContext(ChartDataContext);
const { ready, form, enabled } = useContext(ChartFilterContext);
const { getFilter, hasFilter, appendFilter } = useChartFilter();
const schema = useFieldSchema();
const api = useAPIClient();
const service = useRequest(
(collection, query, manual) =>
new Promise((resolve, reject) => {
// Check if the chart is configured
if (!(collection && query?.measures?.length)) return resolve(undefined);
// If the filter block is enabled, the filter form is required to be rendered
if (enabled && !form) return resolve(undefined);
const filterValues = getFilter();
const queryWithFilter =
!manual && hasFilter({ collection, query }, filterValues)
? appendFilter({ collection, query }, filterValues)
: query;
api
.request({
url: 'charts:query',
method: 'POST',
data: {
uid: schema?.['x-uid'],
collection,
...queryWithFilter,
filter: removeUnparsableFilter(queryWithFilter.filter),
dimensions: (query?.dimensions || []).map((item: DimensionProps) => {
const dimension = { ...item };
if (item.format && !item.alias) {
const { alias } = parseField(item.field);
dimension.alias = alias;
}
return dimension;
}),
measures: (query?.measures || []).map((item: MeasureProps) => {
const measure = { ...item };
if (item.aggregation && !item.alias) {
const { alias } = parseField(item.field);
measure.alias = alias;
}
return measure;
}),
},
})
.then((res) => {
resolve(res?.data?.data);
if (!manual && schema?.['x-uid']) {
addChart(schema?.['x-uid'], { collection, service, query });
}
})
.catch(reject);
}),
{
defaultParams: [collection, query],
// Wait until ChartFilterProvider is rendered and check the status of the filter form
// since the filter parameters should be applied if the filter block is enabled
ready: ready && (!enabled || !!form),
},
);
return (
<CollectionManagerProvider dataSource={dataSource}>
<MaybeCollectionProvider collection={collection} dataSource={dataSource}>
<ConfigProvider card={{ style: { boxShadow: 'none' } }}>
<ChartRendererContext.Provider value={{ collection, config, transform, service, query }}>
{props.children}
</ChartRendererContext.Provider>
</ConfigProvider>
</MaybeCollectionProvider>
</CollectionManagerProvider>
);
};