refactor(bi): improve chart frontend api (#2721)
* refactor: improve chart frontend api * chore: remove redundant import * fix: rename chartType * chore: add migration check * fix: add migration * fix: change version * chore: update
This commit is contained in:
parent
729fdd04b7
commit
ae988d00b0
@ -0,0 +1,24 @@
|
|||||||
|
import { SchemaInitializerContext, SchemaInitializerProvider } from '@nocobase/client';
|
||||||
|
import React, { useContext } from 'react';
|
||||||
|
import { ChartInitializers } from './block';
|
||||||
|
import { useChartsTranslation } from './locale';
|
||||||
|
|
||||||
|
export const DataVisualization: React.FC = (props) => {
|
||||||
|
const { t } = useChartsTranslation();
|
||||||
|
const initializers = useContext<any>(SchemaInitializerContext);
|
||||||
|
const children = initializers.BlockInitializers.items[0].children;
|
||||||
|
const has = children.some((initializer) => initializer.component === 'ChartV2BlockInitializer');
|
||||||
|
if (!has) {
|
||||||
|
children.push({
|
||||||
|
key: 'chart-v2',
|
||||||
|
type: 'item',
|
||||||
|
title: t('Charts'),
|
||||||
|
component: 'ChartV2BlockInitializer',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<SchemaInitializerProvider initializers={{ ...initializers, ChartInitializers }}>
|
||||||
|
{props.children}
|
||||||
|
</SchemaInitializerProvider>
|
||||||
|
);
|
||||||
|
};
|
@ -1,43 +0,0 @@
|
|||||||
import { CheckOutlined } from '@ant-design/icons';
|
|
||||||
import { Form, FormItem } from '@formily/antd-v5';
|
|
||||||
import { css } from '@nocobase/client';
|
|
||||||
import { Button, Card } from 'antd';
|
|
||||||
import cls from 'classnames';
|
|
||||||
import React, { useContext } from 'react';
|
|
||||||
import { useChartsTranslation } from './locale';
|
|
||||||
import { ChartLibraryContext, useToggleChartLibrary } from './chart/library';
|
|
||||||
|
|
||||||
export const Settings = () => {
|
|
||||||
const { t } = useChartsTranslation();
|
|
||||||
const libraries = useContext(ChartLibraryContext);
|
|
||||||
const { toggle } = useToggleChartLibrary();
|
|
||||||
const list = Object.entries(libraries).map(([library, { enabled }]) => {
|
|
||||||
return (
|
|
||||||
<Button
|
|
||||||
key={library}
|
|
||||||
icon={enabled ? <CheckOutlined /> : ''}
|
|
||||||
className={cls(
|
|
||||||
css`
|
|
||||||
margin: 8px 8px 8px 0;
|
|
||||||
`,
|
|
||||||
enabled
|
|
||||||
? css`
|
|
||||||
color: #40a9ff;
|
|
||||||
border-color: #40a9ff;
|
|
||||||
`
|
|
||||||
: '',
|
|
||||||
)}
|
|
||||||
onClick={() => toggle(library)}
|
|
||||||
>
|
|
||||||
{library}
|
|
||||||
</Button>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
return (
|
|
||||||
<Card>
|
|
||||||
<Form layout="vertical">
|
|
||||||
<FormItem label={t('Enabled Chart Library')}>{list}</FormItem>
|
|
||||||
</Form>
|
|
||||||
</Card>
|
|
||||||
);
|
|
||||||
};
|
|
@ -1,4 +1,3 @@
|
|||||||
import { ISchema } from '@formily/react';
|
|
||||||
import { AntdChart } from './antd';
|
import { AntdChart } from './antd';
|
||||||
import { Statistic as AntdStatistic } from 'antd';
|
import { Statistic as AntdStatistic } from 'antd';
|
||||||
import { lang } from '../../locale';
|
import { lang } from '../../locale';
|
||||||
|
@ -3,7 +3,7 @@ import { FieldOption } from '../hooks';
|
|||||||
import { QueryProps } from '../renderer';
|
import { QueryProps } from '../renderer';
|
||||||
import { parseField } from '../utils';
|
import { parseField } from '../utils';
|
||||||
import { ISchema } from '@formily/react';
|
import { ISchema } from '@formily/react';
|
||||||
import configs, { AnySchemaProperties, ConfigProps } from './configs';
|
import configs, { AnySchemaProperties, Config } from './configs';
|
||||||
|
|
||||||
export type RenderProps = {
|
export type RenderProps = {
|
||||||
data: any[];
|
data: any[];
|
||||||
@ -21,21 +21,6 @@ export interface ChartType {
|
|||||||
title: string;
|
title: string;
|
||||||
component: React.FC<any>;
|
component: React.FC<any>;
|
||||||
schema: ISchema;
|
schema: ISchema;
|
||||||
infer: (
|
|
||||||
fields: FieldOption[],
|
|
||||||
{
|
|
||||||
measures,
|
|
||||||
dimensions,
|
|
||||||
}: {
|
|
||||||
measures?: QueryProps['measures'];
|
|
||||||
dimensions?: QueryProps['dimensions'];
|
|
||||||
},
|
|
||||||
) => {
|
|
||||||
xField: FieldOption;
|
|
||||||
yField: FieldOption;
|
|
||||||
seriesField: FieldOption;
|
|
||||||
yFields: FieldOption[];
|
|
||||||
};
|
|
||||||
init?: (
|
init?: (
|
||||||
fields: FieldOption[],
|
fields: FieldOption[],
|
||||||
query: {
|
query: {
|
||||||
@ -46,38 +31,25 @@ export interface ChartType {
|
|||||||
general?: any;
|
general?: any;
|
||||||
advanced?: any;
|
advanced?: any;
|
||||||
};
|
};
|
||||||
/**
|
render: (props: RenderProps) => React.FC<any>;
|
||||||
* getProps
|
|
||||||
* Accept the information that the chart component needs to render,
|
|
||||||
* process it and return the props of the chart component.
|
|
||||||
*/
|
|
||||||
getProps: (props: RenderProps) => any;
|
|
||||||
getReference?: () => {
|
getReference?: () => {
|
||||||
title: string;
|
title: string;
|
||||||
link: string;
|
link: string;
|
||||||
};
|
};
|
||||||
render: (props: RenderProps) => React.FC<any>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type Config = (
|
|
||||||
| (ConfigProps & {
|
|
||||||
property?: string;
|
|
||||||
})
|
|
||||||
| string
|
|
||||||
)[];
|
|
||||||
|
|
||||||
export type ChartProps = {
|
export type ChartProps = {
|
||||||
name: string;
|
name: string;
|
||||||
title: string;
|
title: string;
|
||||||
component: React.FC<any>;
|
component: React.FC<any>;
|
||||||
config?: Config;
|
config?: Config[];
|
||||||
};
|
};
|
||||||
|
|
||||||
export class Chart implements ChartType {
|
export class Chart implements ChartType {
|
||||||
name: string;
|
name: string;
|
||||||
title: string;
|
title: string;
|
||||||
component: React.FC<any>;
|
component: React.FC<any>;
|
||||||
config: Config;
|
config: Config[];
|
||||||
configs = new Map<string, Function>();
|
configs = new Map<string, Function>();
|
||||||
|
|
||||||
constructor({ name, title, component, config }: ChartProps) {
|
constructor({ name, title, component, config }: ChartProps) {
|
||||||
@ -184,6 +156,11 @@ export class Chart implements ChartType {
|
|||||||
return { xField, yField, seriesField, yFields };
|
return { xField, yField, seriesField, yFields };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* getProps
|
||||||
|
* Accept the information that the chart component needs to render,
|
||||||
|
* process it and return the props of the chart component.
|
||||||
|
*/
|
||||||
getProps(props: RenderProps) {
|
getProps(props: RenderProps) {
|
||||||
return props;
|
return props;
|
||||||
}
|
}
|
||||||
|
@ -11,10 +11,16 @@ export type FieldConfigProps = Partial<{
|
|||||||
export type AnySchemaProperties = SchemaProperties<any, any, any, any, any, any, any, any>;
|
export type AnySchemaProperties = SchemaProperties<any, any, any, any, any, any, any, any>;
|
||||||
export type ConfigProps = FieldConfigProps | AnySchemaProperties | (() => AnySchemaProperties);
|
export type ConfigProps = FieldConfigProps | AnySchemaProperties | (() => AnySchemaProperties);
|
||||||
|
|
||||||
|
export type Config =
|
||||||
|
| (ConfigProps & {
|
||||||
|
property?: string;
|
||||||
|
})
|
||||||
|
| string;
|
||||||
|
|
||||||
const selectField = ({ name, title, required, defaultValue }: FieldConfigProps) => {
|
const selectField = ({ name, title, required, defaultValue }: FieldConfigProps) => {
|
||||||
return {
|
return {
|
||||||
[name]: {
|
[name || 'field']: {
|
||||||
title: lang(title),
|
title: lang(title || 'Field'),
|
||||||
type: 'string',
|
type: 'string',
|
||||||
'x-decorator': 'FormItem',
|
'x-decorator': 'FormItem',
|
||||||
'x-component': 'Select',
|
'x-component': 'Select',
|
||||||
@ -27,8 +33,8 @@ const selectField = ({ name, title, required, defaultValue }: FieldConfigProps)
|
|||||||
|
|
||||||
const booleanField = ({ name, title, defaultValue = false }: FieldConfigProps) => {
|
const booleanField = ({ name, title, defaultValue = false }: FieldConfigProps) => {
|
||||||
return {
|
return {
|
||||||
[name]: {
|
[name || 'field']: {
|
||||||
'x-content': lang(title),
|
'x-content': lang(title || 'Field'),
|
||||||
type: 'boolean',
|
type: 'boolean',
|
||||||
'x-decorator': 'FormItem',
|
'x-decorator': 'FormItem',
|
||||||
'x-component': 'Checkbox',
|
'x-component': 'Checkbox',
|
||||||
|
@ -0,0 +1,86 @@
|
|||||||
|
import { usePlugin } from '@nocobase/client';
|
||||||
|
import { ChartType } from './chart';
|
||||||
|
import DataVisualizationPlugin from '..';
|
||||||
|
import { lang } from '../locale';
|
||||||
|
|
||||||
|
export class ChartGroup {
|
||||||
|
charts: Map<string, ChartType[]> = new Map();
|
||||||
|
|
||||||
|
setGroup(name: string, charts: ChartType[]) {
|
||||||
|
this.charts.set(name, charts);
|
||||||
|
}
|
||||||
|
|
||||||
|
addGroup(name: string, charts: ChartType[]) {
|
||||||
|
if (this.charts.has(name)) {
|
||||||
|
throw new Error(`[data-visualization] Chart group "${name}" already exists`);
|
||||||
|
}
|
||||||
|
this.setGroup(name, charts);
|
||||||
|
}
|
||||||
|
|
||||||
|
add(group: string, chart: ChartType) {
|
||||||
|
if (!this.charts.has(group)) {
|
||||||
|
this.setGroup(group, []);
|
||||||
|
}
|
||||||
|
this.charts.get(group)?.push(chart);
|
||||||
|
}
|
||||||
|
|
||||||
|
getChartTypes(): {
|
||||||
|
label: string;
|
||||||
|
children: {
|
||||||
|
key: string;
|
||||||
|
label: string;
|
||||||
|
value: string;
|
||||||
|
}[];
|
||||||
|
}[] {
|
||||||
|
const result = [];
|
||||||
|
this.charts.forEach((charts, group) => {
|
||||||
|
const children = charts.map((chart) => ({
|
||||||
|
key: `${group}.${chart.name}`,
|
||||||
|
label: lang(chart.title),
|
||||||
|
value: `${group}.${chart.name}`,
|
||||||
|
}));
|
||||||
|
result.push({
|
||||||
|
label: lang(group),
|
||||||
|
children,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
getCharts(): {
|
||||||
|
[key: string]: ChartType;
|
||||||
|
} {
|
||||||
|
const result = {};
|
||||||
|
this.charts.forEach((charts, group) => {
|
||||||
|
charts.forEach((chart) => {
|
||||||
|
result[`${group}.${chart.name}`] = chart;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
getChart(type: string): ChartType {
|
||||||
|
const charts = this.getCharts();
|
||||||
|
return charts[type];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useChartTypes = () => {
|
||||||
|
const plugin = usePlugin(DataVisualizationPlugin);
|
||||||
|
return plugin.charts.getChartTypes();
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useDefaultChartType = () => {
|
||||||
|
const chartTypes = useChartTypes();
|
||||||
|
return chartTypes[0]?.children?.[0]?.value;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useCharts = () => {
|
||||||
|
const plugin = usePlugin(DataVisualizationPlugin);
|
||||||
|
return plugin.charts.getCharts();
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useChart = (type: string) => {
|
||||||
|
const plugin = usePlugin(DataVisualizationPlugin);
|
||||||
|
return plugin.charts.getChart(type);
|
||||||
|
};
|
@ -1,89 +0,0 @@
|
|||||||
import React, { createContext, useContext } from 'react';
|
|
||||||
import { lang } from '../locale';
|
|
||||||
import { ChartType } from './chart';
|
|
||||||
|
|
||||||
export type ChartLibraries = {
|
|
||||||
[library: string]: {
|
|
||||||
enabled: boolean;
|
|
||||||
charts: ChartType[];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export const ChartLibraryContext = createContext<ChartLibraries>({});
|
|
||||||
|
|
||||||
export const useCharts = (): {
|
|
||||||
[name: string]: ChartType;
|
|
||||||
} => {
|
|
||||||
const library = useContext(ChartLibraryContext);
|
|
||||||
return Object.values(library)
|
|
||||||
.filter((l) => l.enabled)
|
|
||||||
.reduce((allCharts, l) => {
|
|
||||||
const charts = Object.values(l.charts);
|
|
||||||
return {
|
|
||||||
...allCharts,
|
|
||||||
...charts.reduce((all, chart) => {
|
|
||||||
return {
|
|
||||||
...all,
|
|
||||||
[chart.name]: chart,
|
|
||||||
};
|
|
||||||
}, {}),
|
|
||||||
};
|
|
||||||
}, {});
|
|
||||||
};
|
|
||||||
|
|
||||||
export const useChartTypes = (): {
|
|
||||||
label: string;
|
|
||||||
children: {
|
|
||||||
key: string;
|
|
||||||
label: string;
|
|
||||||
value: string;
|
|
||||||
}[];
|
|
||||||
}[] => {
|
|
||||||
const library = useContext(ChartLibraryContext);
|
|
||||||
return Object.entries(library)
|
|
||||||
.filter(([_, l]) => l.enabled)
|
|
||||||
.reduce((charts, [name, l]) => {
|
|
||||||
const children = Object.values(l.charts).map((chart) => ({
|
|
||||||
key: chart.name,
|
|
||||||
label: lang(chart.title),
|
|
||||||
value: chart.name,
|
|
||||||
}));
|
|
||||||
return [
|
|
||||||
...charts,
|
|
||||||
{
|
|
||||||
label: lang(name),
|
|
||||||
children,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
}, []);
|
|
||||||
};
|
|
||||||
|
|
||||||
export const useDefaultChartType = () => {
|
|
||||||
const chartTypes = useChartTypes();
|
|
||||||
return chartTypes[0]?.children?.[0]?.value;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const useToggleChartLibrary = () => {
|
|
||||||
const ctx = useContext(ChartLibraryContext);
|
|
||||||
return {
|
|
||||||
toggle: (library: string) => {
|
|
||||||
ctx[library].enabled = !ctx[library].enabled;
|
|
||||||
},
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export const ChartLibraryProvider: React.FC<{
|
|
||||||
name: string;
|
|
||||||
charts: ChartType[];
|
|
||||||
}> = (props) => {
|
|
||||||
const { children, charts, name } = props;
|
|
||||||
const ctx = useContext(ChartLibraryContext);
|
|
||||||
const library = {
|
|
||||||
...ctx,
|
|
||||||
[name]: {
|
|
||||||
charts,
|
|
||||||
enabled: true,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
return <ChartLibraryContext.Provider value={library}>{children}</ChartLibraryContext.Provider>;
|
|
||||||
};
|
|
@ -29,7 +29,7 @@ import { useChartsTranslation } from '../locale';
|
|||||||
import { ChartRenderer, ChartRendererContext } from '../renderer';
|
import { ChartRenderer, ChartRendererContext } from '../renderer';
|
||||||
import { createRendererSchema, getField, getSelectedFields } from '../utils';
|
import { createRendererSchema, getField, getSelectedFields } from '../utils';
|
||||||
import { getConfigSchema, querySchema, transformSchema } from './schemas/configure';
|
import { getConfigSchema, querySchema, transformSchema } from './schemas/configure';
|
||||||
import { useChartTypes, useCharts, useDefaultChartType } from '../chart/library';
|
import { useChartTypes, useCharts, useDefaultChartType } from '../chart/group';
|
||||||
import { FilterDynamicComponent } from './FilterDynamicComponent';
|
import { FilterDynamicComponent } from './FilterDynamicComponent';
|
||||||
const { Paragraph, Text } = Typography;
|
const { Paragraph, Text } = Typography;
|
||||||
|
|
||||||
|
@ -1,51 +1,28 @@
|
|||||||
import { Plugin, SchemaComponentOptions, SchemaInitializerContext, SchemaInitializerProvider } from '@nocobase/client';
|
import { Plugin } from '@nocobase/client';
|
||||||
import React, { useContext } from 'react';
|
import { DataVisualization } from './DataVisualization';
|
||||||
import { ChartInitializers, ChartV2Block, ChartV2BlockDesigner, ChartV2BlockInitializer } from './block';
|
import { ChartGroup } from './chart/group';
|
||||||
import { useChartsTranslation } from './locale';
|
|
||||||
import { ChartRenderer, ChartRendererProvider } from './renderer';
|
|
||||||
import { ChartLibraryProvider } from './chart/library';
|
|
||||||
import g2plot from './chart/g2plot';
|
import g2plot from './chart/g2plot';
|
||||||
import antd from './chart/antd';
|
import antd from './chart/antd';
|
||||||
|
import { ChartV2Block, ChartV2BlockDesigner, ChartV2BlockInitializer } from './block';
|
||||||
|
import { ChartRenderer, ChartRendererProvider } from './renderer';
|
||||||
|
|
||||||
const DataVisualization: React.FC = (props) => {
|
class DataVisualizationPlugin extends Plugin {
|
||||||
const { t } = useChartsTranslation();
|
public charts: ChartGroup = new ChartGroup();
|
||||||
const initializers = useContext<any>(SchemaInitializerContext);
|
|
||||||
const children = initializers.BlockInitializers.items[0].children;
|
async load() {
|
||||||
const has = children.some((initializer) => initializer.component === 'ChartV2BlockInitializer');
|
this.charts.setGroup('Built-in', [...g2plot, ...antd]);
|
||||||
if (!has) {
|
|
||||||
children.push({
|
this.app.addComponents({
|
||||||
key: 'chart-v2',
|
|
||||||
type: 'item',
|
|
||||||
title: t('Charts'),
|
|
||||||
component: 'ChartV2BlockInitializer',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<SchemaComponentOptions
|
|
||||||
components={{
|
|
||||||
ChartV2BlockInitializer,
|
ChartV2BlockInitializer,
|
||||||
ChartRenderer,
|
ChartRenderer,
|
||||||
ChartV2BlockDesigner,
|
ChartV2BlockDesigner,
|
||||||
ChartV2Block,
|
ChartV2Block,
|
||||||
ChartRendererProvider,
|
ChartRendererProvider,
|
||||||
}}
|
});
|
||||||
>
|
|
||||||
<SchemaInitializerProvider initializers={{ ...initializers, ChartInitializers }}>
|
|
||||||
<ChartLibraryProvider name="Built-in" charts={[...g2plot, ...antd]}>
|
|
||||||
{props.children}
|
|
||||||
</ChartLibraryProvider>
|
|
||||||
</SchemaInitializerProvider>
|
|
||||||
</SchemaComponentOptions>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
class DataVisualizationPlugin extends Plugin {
|
|
||||||
async load() {
|
|
||||||
this.app.addProvider(DataVisualization);
|
this.app.addProvider(DataVisualization);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default DataVisualizationPlugin;
|
export default DataVisualizationPlugin;
|
||||||
export { ChartLibraryProvider };
|
|
||||||
export { Chart } from './chart/chart';
|
export { Chart } from './chart/chart';
|
||||||
export type { ChartType } from './chart/chart';
|
export type { ChartType } from './chart/chart';
|
||||||
|
@ -14,8 +14,8 @@ import { ChartConfigContext } from '../configure/ChartConfigure';
|
|||||||
import { useData, useFieldTransformer, useFieldsWithAssociation } from '../hooks';
|
import { useData, useFieldTransformer, useFieldsWithAssociation } from '../hooks';
|
||||||
import { useChartsTranslation } from '../locale';
|
import { useChartsTranslation } from '../locale';
|
||||||
import { createRendererSchema, getField } from '../utils';
|
import { createRendererSchema, getField } from '../utils';
|
||||||
import { useCharts } from '../chart/library';
|
|
||||||
import { ChartRendererContext } from './ChartRendererProvider';
|
import { ChartRendererContext } from './ChartRendererProvider';
|
||||||
|
import { useChart } from '../chart/group';
|
||||||
const { Paragraph, Text } = Typography;
|
const { Paragraph, Text } = Typography;
|
||||||
|
|
||||||
export const ChartRenderer: React.FC & {
|
export const ChartRenderer: React.FC & {
|
||||||
@ -30,8 +30,7 @@ export const ChartRenderer: React.FC & {
|
|||||||
const advanced = config?.advanced || {};
|
const advanced = config?.advanced || {};
|
||||||
const api = useAPIClient();
|
const api = useAPIClient();
|
||||||
|
|
||||||
const charts = useCharts();
|
const chart = useChart(config?.chartType);
|
||||||
const chart = charts[config?.chartType];
|
|
||||||
const locale = api.auth.getLocale();
|
const locale = api.auth.getLocale();
|
||||||
const transformers = useFieldTransformer(transform, locale);
|
const transformers = useFieldTransformer(transform, locale);
|
||||||
const Component = chart?.render({
|
const Component = chart?.render({
|
||||||
|
@ -0,0 +1,32 @@
|
|||||||
|
import { Migration } from '@nocobase/server';
|
||||||
|
import { Repository } from '@nocobase/database';
|
||||||
|
|
||||||
|
export default class RenameChartTypeMigration extends Migration {
|
||||||
|
async up() {
|
||||||
|
const result = await this.app.version.satisfies('<=0.14.0-alpha.7');
|
||||||
|
|
||||||
|
if (!result) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const r = this.db.getRepository<Repository>('uiSchemas');
|
||||||
|
const items = await r.find({
|
||||||
|
filter: {
|
||||||
|
'schema.x-decorator': 'ChartRendererProvider',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
await this.db.sequelize.transaction(async (transaction) => {
|
||||||
|
for (const item of items) {
|
||||||
|
const schema = item.schema;
|
||||||
|
const chartType = schema['x-decorator-props']?.config?.chartType;
|
||||||
|
if (!chartType || chartType.startsWith('Built-in.')) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
schema['x-decorator-props'].config.chartType = `Built-in.${chartType}`;
|
||||||
|
item.set('schema', schema);
|
||||||
|
await item.save({ transaction });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,7 @@
|
|||||||
import { Cache, createCache } from '@nocobase/cache';
|
import { Cache, createCache } from '@nocobase/cache';
|
||||||
import { InstallOptions, Plugin } from '@nocobase/server';
|
import { InstallOptions, Plugin } from '@nocobase/server';
|
||||||
import { query } from './actions/query';
|
import { query } from './actions/query';
|
||||||
|
import { resolve } from 'path';
|
||||||
|
|
||||||
export class DataVisualizationPlugin extends Plugin {
|
export class DataVisualizationPlugin extends Plugin {
|
||||||
cache: Cache;
|
cache: Cache;
|
||||||
@ -18,6 +19,14 @@ export class DataVisualizationPlugin extends Plugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async load() {
|
async load() {
|
||||||
|
this.db.addMigrations({
|
||||||
|
namespace: 'data-visulization',
|
||||||
|
directory: resolve(__dirname, 'migrations'),
|
||||||
|
context: {
|
||||||
|
plugin: this,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
this.cache = createCache({
|
this.cache = createCache({
|
||||||
ttl: 30, // seconds
|
ttl: 30, // seconds
|
||||||
max: 1000,
|
max: 1000,
|
||||||
|
Loading…
Reference in New Issue
Block a user