fix: collection undefined (#1169)
Co-authored-by: sealday <sealday@gmail.com> Reviewed-on: daoyoucloud/tachybase#1169
This commit is contained in:
parent
0cf4a450de
commit
6fc13dd14f
@ -1,8 +1,8 @@
|
|||||||
import React, { FC, ReactNode, createContext, useContext, useMemo } from 'react';
|
import React, { createContext, FC, ReactNode, useContext, useMemo } from 'react';
|
||||||
|
|
||||||
import { useCollectionManager } from './CollectionManagerProvider';
|
|
||||||
import { CollectionDeletedPlaceholder } from '../components/CollectionDeletedPlaceholder';
|
import { CollectionDeletedPlaceholder } from '../components/CollectionDeletedPlaceholder';
|
||||||
import type { CollectionOptions, Collection, GetCollectionFieldPredicate } from './Collection';
|
import type { Collection, CollectionOptions, GetCollectionFieldPredicate } from './Collection';
|
||||||
|
import { useCollectionManager } from './CollectionManagerProvider';
|
||||||
|
|
||||||
export const CollectionContext = createContext<Collection>(null);
|
export const CollectionContext = createContext<Collection>(null);
|
||||||
CollectionContext.displayName = 'CollectionContext';
|
CollectionContext.displayName = 'CollectionContext';
|
||||||
|
@ -6,7 +6,6 @@ import { useFilterActionProps } from './filter/useFilterActionProps';
|
|||||||
import { formV1Settings } from './form';
|
import { formV1Settings } from './form';
|
||||||
import { filterFormItemSettings, formItemSettings } from './form-item';
|
import { filterFormItemSettings, formItemSettings } from './form-item';
|
||||||
import { formDetailsSettings, formSettings, readPrettyFormSettings } from './form-v2';
|
import { formDetailsSettings, formSettings, readPrettyFormSettings } from './form-v2';
|
||||||
import { requestChartData } from './g2plot/requestChartData';
|
|
||||||
import { pageSettings, pageTabSettings } from './page';
|
import { pageSettings, pageTabSettings } from './page';
|
||||||
|
|
||||||
export class AntdSchemaComponentPlugin extends Plugin {
|
export class AntdSchemaComponentPlugin extends Plugin {
|
||||||
@ -25,7 +24,6 @@ export class AntdSchemaComponentPlugin extends Plugin {
|
|||||||
|
|
||||||
addScopes() {
|
addScopes() {
|
||||||
this.app.addScopes({
|
this.app.addScopes({
|
||||||
requestChartData,
|
|
||||||
useFilterActionProps,
|
useFilterActionProps,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -22,16 +22,16 @@ export const useGetAriaLabelOfBlockItem = (defaultName?: string) => {
|
|||||||
const collection = useCollection();
|
const collection = useCollection();
|
||||||
const name = defaultName || blockName;
|
const name = defaultName || blockName;
|
||||||
|
|
||||||
const title = compile(fieldSchema['title']) || compile(collection.getField(fieldSchema.name)?.uiSchema?.title);
|
const title = compile(fieldSchema['title']) || compile(collection?.getField(fieldSchema.name)?.uiSchema?.title);
|
||||||
|
|
||||||
const getAriaLabel = useCallback(
|
const getAriaLabel = useCallback(
|
||||||
(postfix?: string) => {
|
(postfix?: string) => {
|
||||||
postfix = postfix ? `-${postfix}` : '';
|
postfix = postfix ? `-${postfix}` : '';
|
||||||
return ['block-item', component, collection.name, name, collectionField, title, postfix]
|
return ['block-item', component, collection?.name, name, collectionField, title, postfix]
|
||||||
.filter(Boolean)
|
.filter(Boolean)
|
||||||
.join('-');
|
.join('-');
|
||||||
},
|
},
|
||||||
[component, collection.name, name, collectionField, title],
|
[component, collection?.name, name, collectionField, title],
|
||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
@ -1,183 +0,0 @@
|
|||||||
import {
|
|
||||||
Area,
|
|
||||||
Bar,
|
|
||||||
BidirectionalBar,
|
|
||||||
Box,
|
|
||||||
Bullet,
|
|
||||||
Chord,
|
|
||||||
CirclePacking,
|
|
||||||
Column,
|
|
||||||
DualAxes,
|
|
||||||
Facet,
|
|
||||||
Funnel,
|
|
||||||
Gauge,
|
|
||||||
Heatmap,
|
|
||||||
Histogram,
|
|
||||||
Line,
|
|
||||||
Liquid,
|
|
||||||
Mix,
|
|
||||||
Pie,
|
|
||||||
Progress,
|
|
||||||
Radar,
|
|
||||||
RadialBar,
|
|
||||||
RingProgress,
|
|
||||||
Rose,
|
|
||||||
Sankey,
|
|
||||||
Scatter,
|
|
||||||
Stock,
|
|
||||||
Sunburst,
|
|
||||||
TinyArea,
|
|
||||||
TinyColumn,
|
|
||||||
TinyLine,
|
|
||||||
Treemap,
|
|
||||||
Venn,
|
|
||||||
Violin,
|
|
||||||
Waterfall,
|
|
||||||
WordCloud,
|
|
||||||
} from '@antv/g2plot';
|
|
||||||
import { Field } from '@tachybase/schema';
|
|
||||||
import { observer, useField } from '@tachybase/schema';
|
|
||||||
import { Spin } from 'antd';
|
|
||||||
import cls from 'classnames';
|
|
||||||
import React, { forwardRef, useEffect, useRef } from 'react';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
|
||||||
import { useAPIClient } from '../../../api-client';
|
|
||||||
import { G2PlotDesigner } from './G2PlotDesigner';
|
|
||||||
|
|
||||||
export type ReactG2PlotProps<O> = {
|
|
||||||
readonly className?: string;
|
|
||||||
readonly plot: any;
|
|
||||||
readonly config: O;
|
|
||||||
};
|
|
||||||
|
|
||||||
const plots = {
|
|
||||||
Line,
|
|
||||||
Area,
|
|
||||||
Column,
|
|
||||||
Bar,
|
|
||||||
Pie,
|
|
||||||
Rose,
|
|
||||||
WordCloud,
|
|
||||||
Scatter,
|
|
||||||
Radar,
|
|
||||||
DualAxes,
|
|
||||||
TinyLine,
|
|
||||||
TinyColumn,
|
|
||||||
TinyArea,
|
|
||||||
Histogram,
|
|
||||||
Progress,
|
|
||||||
RingProgress,
|
|
||||||
Heatmap,
|
|
||||||
Box,
|
|
||||||
Violin,
|
|
||||||
Venn,
|
|
||||||
Stock,
|
|
||||||
Funnel,
|
|
||||||
Liquid,
|
|
||||||
Bullet,
|
|
||||||
Sunburst,
|
|
||||||
Gauge,
|
|
||||||
Waterfall,
|
|
||||||
RadialBar,
|
|
||||||
BidirectionalBar,
|
|
||||||
Treemap,
|
|
||||||
Sankey,
|
|
||||||
Chord,
|
|
||||||
CirclePacking,
|
|
||||||
Mix,
|
|
||||||
Facet,
|
|
||||||
};
|
|
||||||
|
|
||||||
export const G2PlotRenderer = forwardRef(function <O = any>(props: ReactG2PlotProps<O>, ref: any) {
|
|
||||||
const { className, plot, config } = props;
|
|
||||||
const containerRef = useRef(undefined);
|
|
||||||
const plotRef = useRef(undefined);
|
|
||||||
|
|
||||||
function syncRef(source, target) {
|
|
||||||
if (typeof target === 'function') {
|
|
||||||
target(source.current);
|
|
||||||
} else if (target) {
|
|
||||||
target.current = source.current;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function renderPlot() {
|
|
||||||
if (plotRef.current) {
|
|
||||||
plotRef.current.update(config);
|
|
||||||
} else {
|
|
||||||
plotRef.current = new plot(containerRef.current, config);
|
|
||||||
plotRef?.current?.render();
|
|
||||||
}
|
|
||||||
|
|
||||||
syncRef(plotRef, ref);
|
|
||||||
}
|
|
||||||
|
|
||||||
function destoryPlot() {
|
|
||||||
if (plotRef.current) {
|
|
||||||
plotRef.current.destroy();
|
|
||||||
plotRef.current = undefined;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
renderPlot();
|
|
||||||
return () => destoryPlot();
|
|
||||||
}, [config, plot]);
|
|
||||||
|
|
||||||
return <div className={cls(['g2plot', className])} ref={containerRef} />;
|
|
||||||
});
|
|
||||||
G2PlotRenderer.displayName = 'G2PlotRenderer';
|
|
||||||
|
|
||||||
export const G2Plot: any = observer(
|
|
||||||
(props: any) => {
|
|
||||||
const { plot, config } = props;
|
|
||||||
const field = useField<Field>();
|
|
||||||
const { t } = useTranslation();
|
|
||||||
const api = useAPIClient();
|
|
||||||
useEffect(() => {
|
|
||||||
field.data = field.data || {};
|
|
||||||
field.data.loading = true;
|
|
||||||
const fn = config?.data;
|
|
||||||
if (typeof fn === 'function') {
|
|
||||||
const result = fn.bind({ api })();
|
|
||||||
if (result?.then) {
|
|
||||||
result
|
|
||||||
.then((data) => {
|
|
||||||
if (Array.isArray(data)) {
|
|
||||||
field.componentProps.config.data = data;
|
|
||||||
}
|
|
||||||
field.data.loading = false;
|
|
||||||
})
|
|
||||||
.catch(console.error);
|
|
||||||
} else {
|
|
||||||
field.data.loading = false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
field.data.loading = false;
|
|
||||||
}
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
if (!plot || !config) {
|
|
||||||
return <div style={{ opacity: 0.3 }}>{t('In configuration')}...</div>;
|
|
||||||
}
|
|
||||||
if (field?.data?.loading !== false) {
|
|
||||||
return <Spin />;
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
{field.title && <h2>{field.title}</h2>}
|
|
||||||
<G2PlotRenderer
|
|
||||||
plot={plots[plot]}
|
|
||||||
config={{
|
|
||||||
...config,
|
|
||||||
data: Array.isArray(config?.data) ? config.data : [],
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
{ displayName: 'G2Plot' },
|
|
||||||
);
|
|
||||||
|
|
||||||
G2Plot.Designer = G2PlotDesigner;
|
|
||||||
G2Plot.plots = plots;
|
|
@ -1,120 +0,0 @@
|
|||||||
import { ISchema, useField, useFieldSchema } from '@tachybase/schema';
|
|
||||||
import React from 'react';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
|
||||||
import { useAPIClient } from '../../../api-client';
|
|
||||||
import {
|
|
||||||
GeneralSchemaDesigner,
|
|
||||||
SchemaSettingsDivider,
|
|
||||||
SchemaSettingsModalItem,
|
|
||||||
SchemaSettingsRemove,
|
|
||||||
} from '../../../schema-settings';
|
|
||||||
import { useCompile, useDesignable } from '../../hooks';
|
|
||||||
import _ from 'lodash';
|
|
||||||
|
|
||||||
const validateJSON = {
|
|
||||||
validator: `{{(value, rule)=> {
|
|
||||||
if (!value) {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
const val = JSON.parse(value);
|
|
||||||
if(!isNaN(val)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
} catch(error) {
|
|
||||||
console.error(error);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}}}`,
|
|
||||||
message: '{{t("Invalid JSON format")}}',
|
|
||||||
};
|
|
||||||
|
|
||||||
export const G2PlotDesigner = () => {
|
|
||||||
const { t } = useTranslation();
|
|
||||||
const { dn } = useDesignable();
|
|
||||||
const fieldSchema = useFieldSchema();
|
|
||||||
const field = useField();
|
|
||||||
const compile = useCompile();
|
|
||||||
const api = useAPIClient();
|
|
||||||
return (
|
|
||||||
<GeneralSchemaDesigner>
|
|
||||||
<SchemaSettingsModalItem
|
|
||||||
title={t('Edit chart')}
|
|
||||||
schema={
|
|
||||||
{
|
|
||||||
type: 'object',
|
|
||||||
title: t('Edit chart'),
|
|
||||||
properties: {
|
|
||||||
title: {
|
|
||||||
title: t('Chart title'),
|
|
||||||
type: 'string',
|
|
||||||
default: fieldSchema.title,
|
|
||||||
'x-decorator': 'FormItem',
|
|
||||||
'x-component': 'Input',
|
|
||||||
},
|
|
||||||
plot: {
|
|
||||||
title: t('Chart type'),
|
|
||||||
type: 'string',
|
|
||||||
default: fieldSchema?.['x-component-props']?.plot,
|
|
||||||
'x-decorator': 'FormItem',
|
|
||||||
'x-component': 'Input',
|
|
||||||
'x-disabled': !!fieldSchema?.['x-component-props']?.plot,
|
|
||||||
},
|
|
||||||
config: {
|
|
||||||
title: t('Chart config'),
|
|
||||||
type: 'string',
|
|
||||||
default: JSON.stringify(fieldSchema?.['x-component-props']?.config, null, 2),
|
|
||||||
'x-decorator': 'FormItem',
|
|
||||||
'x-component': 'Input.TextArea',
|
|
||||||
'x-component-props': {
|
|
||||||
autoSize: { minRows: 8, maxRows: 16 },
|
|
||||||
},
|
|
||||||
'x-validator': validateJSON,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
} as ISchema
|
|
||||||
}
|
|
||||||
// {{ fetchData(api, { url: 'chartData:get' }) }}
|
|
||||||
onSubmit={async ({ plot, title, config }) => {
|
|
||||||
field.title = compile(title);
|
|
||||||
field.componentProps.plot = plot;
|
|
||||||
const conf = compile(JSON.parse(config));
|
|
||||||
const fn = conf?.data;
|
|
||||||
if (typeof fn === 'function') {
|
|
||||||
const result = fn.bind({ api })();
|
|
||||||
if (result?.then) {
|
|
||||||
result
|
|
||||||
.then((data) => {
|
|
||||||
if (Array.isArray(data)) {
|
|
||||||
field.componentProps.config.data = data;
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch(console.error);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
field.componentProps.config = conf;
|
|
||||||
}
|
|
||||||
_.set(fieldSchema, 'title', title);
|
|
||||||
_.set(fieldSchema, 'x-component-props.plot', plot);
|
|
||||||
_.set(fieldSchema, 'x-component-props.config', JSON.parse(config));
|
|
||||||
dn.emit('patch', {
|
|
||||||
schema: {
|
|
||||||
title,
|
|
||||||
'x-uid': fieldSchema['x-uid'],
|
|
||||||
'x-component-props': fieldSchema['x-component-props'],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
dn.refresh();
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<SchemaSettingsDivider />
|
|
||||||
<SchemaSettingsRemove
|
|
||||||
removeParentsIfNoChildren
|
|
||||||
breakRemoveOn={{
|
|
||||||
'x-component': 'Grid',
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</GeneralSchemaDesigner>
|
|
||||||
);
|
|
||||||
};
|
|
@ -1,15 +0,0 @@
|
|||||||
import { render, waitFor } from '@tachybase/test/client';
|
|
||||||
import React from 'react';
|
|
||||||
import App1 from '../demos/demo1';
|
|
||||||
|
|
||||||
// jsdom does not support canvas, so we need to skip this test
|
|
||||||
describe.skip('G2Plot', () => {
|
|
||||||
it('basic', async () => {
|
|
||||||
render(<App1 />);
|
|
||||||
|
|
||||||
await waitFor(() => {
|
|
||||||
const g2plot = document.querySelector('.g2plot') as HTMLDivElement;
|
|
||||||
expect(g2plot).toBeInTheDocument();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,91 +0,0 @@
|
|||||||
import {
|
|
||||||
APIClient,
|
|
||||||
APIClientProvider,
|
|
||||||
CardItem,
|
|
||||||
G2Plot,
|
|
||||||
SchemaComponent,
|
|
||||||
SchemaComponentProvider,
|
|
||||||
} from '@tachybase/client';
|
|
||||||
import React from 'react';
|
|
||||||
import { mockAPIClient } from '../../../../testUtils';
|
|
||||||
|
|
||||||
const { apiClient, mockRequest } = mockAPIClient();
|
|
||||||
|
|
||||||
mockRequest.onGet('/test').reply(200, {
|
|
||||||
data: [
|
|
||||||
{
|
|
||||||
Date: '2010-01',
|
|
||||||
scales: 1998,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Date: '2010-02',
|
|
||||||
scales: 1850,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Date: '2010-03',
|
|
||||||
scales: 1720,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Date: '2010-04',
|
|
||||||
scales: 1818,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Date: '2010-05',
|
|
||||||
scales: 1920,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Date: '2010-06',
|
|
||||||
scales: 1802,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Date: '2010-07',
|
|
||||||
scales: 1945,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Date: '2010-08',
|
|
||||||
scales: 1856,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Date: '2010-09',
|
|
||||||
scales: 2107,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
});
|
|
||||||
|
|
||||||
const requestChartData = (options) => {
|
|
||||||
return async function (this: { api: APIClient }) {
|
|
||||||
const response = await this.api.request(options);
|
|
||||||
return response?.data?.data;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const schema = {
|
|
||||||
type: 'void',
|
|
||||||
name: 'line',
|
|
||||||
'x-designer': 'G2Plot.Designer',
|
|
||||||
'x-decorator': 'CardItem',
|
|
||||||
'x-component': 'G2Plot',
|
|
||||||
'x-component-props': {
|
|
||||||
plot: 'Line',
|
|
||||||
config: {
|
|
||||||
data: '{{ requestChartData({ url: "/test" }) }}',
|
|
||||||
padding: 'auto',
|
|
||||||
xField: 'Date',
|
|
||||||
yField: 'scales',
|
|
||||||
xAxis: {
|
|
||||||
// type: 'timeCat',
|
|
||||||
tickCount: 5,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
export default () => {
|
|
||||||
return (
|
|
||||||
<APIClientProvider apiClient={apiClient}>
|
|
||||||
<SchemaComponentProvider components={{ G2Plot, CardItem }} scope={{ requestChartData }}>
|
|
||||||
<SchemaComponent schema={schema} />
|
|
||||||
</SchemaComponentProvider>
|
|
||||||
</APIClientProvider>
|
|
||||||
);
|
|
||||||
};
|
|
@ -1,9 +0,0 @@
|
|||||||
---
|
|
||||||
group:
|
|
||||||
title: Schema Components
|
|
||||||
order: 3
|
|
||||||
---
|
|
||||||
|
|
||||||
# G2Plot
|
|
||||||
|
|
||||||
<code src="./demos/demo1.tsx"></code>
|
|
@ -1 +0,0 @@
|
|||||||
export * from './G2Plot';
|
|
@ -1,12 +0,0 @@
|
|||||||
import { APIClient } from '../../../api-client';
|
|
||||||
|
|
||||||
export const requestChartData = (options) => {
|
|
||||||
return async function (this: { api: APIClient }) {
|
|
||||||
try {
|
|
||||||
const response = await this.api.request(options);
|
|
||||||
return response?.data?.data;
|
|
||||||
} catch (error) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
@ -23,7 +23,6 @@ export * from './form';
|
|||||||
export * from './form-dialog';
|
export * from './form-dialog';
|
||||||
export * from './form-item';
|
export * from './form-item';
|
||||||
export * from './form-v2';
|
export * from './form-v2';
|
||||||
export * from './g2plot';
|
|
||||||
export * from './grid';
|
export * from './grid';
|
||||||
export * from './grid-card';
|
export * from './grid-card';
|
||||||
export * from './icon-picker';
|
export * from './icon-picker';
|
||||||
|
Loading…
Reference in New Issue
Block a user