Merge pull request 'merge_from_upstream_2' (#401) from merge_from_upstream_2 into @hera/dev

Reviewed-on: daoyoucloud/tachycode#401
This commit is contained in:
sealday 2024-03-17 23:29:52 +08:00
commit d072b32b17
10 changed files with 738 additions and 55 deletions

View File

@ -151,7 +151,7 @@ const useAllowedActions = () => {
const useResourceName = () => { const useResourceName = () => {
const service = useResourceActionContext(); const service = useResourceActionContext();
const result = useBlockRequestContext() || { service }; const result = useBlockRequestContext() || { service };
return result?.props?.resource || result?.service?.defaultRequest?.resource; return result?.props?.resource || result?.props?.collection || result?.service?.defaultRequest?.resource;
}; };
export function useACLRoleContext() { export function useACLRoleContext() {

View File

@ -193,7 +193,7 @@ export class InheritanceCollectionMixin extends Collection {
}; };
this.allCollectionsInheritChain = getInheritChain(this.name); this.allCollectionsInheritChain = getInheritChain(this.name);
return this.allCollectionsInheritChain; return this.allCollectionsInheritChain || [];
} }
getInheritCollectionsChain() { getInheritCollectionsChain() {

View File

@ -449,8 +449,7 @@ Grid.Col = observer(
} }
return { width }; return { width };
}, [cols?.length, schema?.['x-component-props']?.['width']]); }, [cols?.length, schema?.['x-component-props']?.['width']]);
const { isOver, setNodeRef } = useDroppable({
const { setNodeRef } = useDroppable({
id: field.address.toString(), id: field.address.toString(),
data: { data: {
insertAdjacent: 'beforeEnd', insertAdjacent: 'beforeEnd',
@ -458,9 +457,41 @@ Grid.Col = observer(
wrapSchema: (s) => s, wrapSchema: (s) => s,
}, },
}); });
const [active, setActive] = useState(false);
const droppableStyle = useMemo(() => {
if (!isOver)
return {
height: '100%',
};
return {
background: `linear-gradient(to top, ${new TinyColor(token.colorSettings)
.setAlpha(0.1)
.toHex8String()} 20%, transparent 20%)`,
borderTopRightRadius: '10px',
borderTopLeftRadius: '10px',
height: '100%',
};
}, [active, isOver]);
useDndMonitor({
onDragStart(event) {
setActive(true);
},
onDragMove(event) {},
onDragOver(event) {},
onDragEnd(event) {
setActive(false);
},
onDragCancel(event) {
setActive(false);
},
});
return ( return (
<GridColContext.Provider value={{ cols, schema }}> <GridColContext.Provider value={{ cols, schema }}>
<div ref={setNodeRef} style={style} className={cls('nb-grid-col')}> <div ref={setNodeRef} style={{ ...style, ...droppableStyle }} className={cls('nb-grid-col')}>
{props.children} {props.children}
</div> </div>
</GridColContext.Provider> </GridColContext.Provider>

View File

@ -26,7 +26,7 @@ export const useCollectionState = (currentCollectionName: string) => {
const templateField: any = useField(); const templateField: any = useField();
function getCollectionList() { function getCollectionList() {
const collections = getAllCollectionsInheritChain(currentCollectionName); const collections = getAllCollectionsInheritChain(currentCollectionName) || [];
return collections.map((name) => ({ label: getCollection(name)?.title, value: name })); return collections.map((name) => ({ label: getCollection(name)?.title, value: name }));
} }

View File

@ -3,7 +3,10 @@ import Application from '../application';
const REPL = require('repl'); const REPL = require('repl');
export default (app: Application) => { export default (app: Application) => {
app.command('console').action(async () => { app
.command('console')
.preload()
.action(async () => {
await app.start(); await app.start();
const repl = (REPL.start('nocobase > ').context.app = app); const repl = (REPL.start('nocobase > ').context.app = app);
repl.on('exit', async function (err) { repl.on('exit', async function (err) {

View File

@ -11,9 +11,9 @@ import restart from './restart';
import start from './start'; import start from './start';
import stop from './stop'; import stop from './stop';
import upgrade from './upgrade'; import upgrade from './upgrade';
import consoleCommand from './console';
export function registerCli(app: Application) { export function registerCli(app: Application) {
// console(app); consoleCommand(app);
dbAuth(app); dbAuth(app);
createMigration(app); createMigration(app);
dbClean(app); dbClean(app);

View File

@ -1,5 +1,5 @@
import { expect, test } from '@nocobase/test/e2e'; import { expect, test } from '@nocobase/test/e2e';
import { oneTableBlock } from './utils'; import { oneTableBlock, newTableBlock } from './utils';
test.describe('view', () => { test.describe('view', () => {
test('general permission', async ({ page, mockPage, mockRole, updateRole }) => { test('general permission', async ({ page, mockPage, mockRole, updateRole }) => {
@ -23,8 +23,9 @@ test.describe('view', () => {
await page.reload(); await page.reload();
await expect(page.getByLabel('block-item-CardItem-general-table')).toBeVisible(); await expect(page.getByLabel('block-item-CardItem-general-table')).toBeVisible();
}); });
test('individual collection permission', async ({ page, mockPage, mockRole, updateRole }) => { test('individual collection permission', async ({ page, mockPage, mockRole, mockRecord, updateRole }) => {
await mockPage(oneTableBlock).goto(); await mockPage(oneTableBlock).goto();
await mockRecord('general');
//新建角色并切换到新角色 //新建角色并切换到新角色
const roleData = await mockRole({ const roleData = await mockRole({
allowNewMenu: true, allowNewMenu: true,
@ -56,6 +57,7 @@ test.describe('view', () => {
}); });
await page.reload(); await page.reload();
await expect(page.getByLabel('block-item-CardItem-general-table')).toBeVisible(); await expect(page.getByLabel('block-item-CardItem-general-table')).toBeVisible();
await expect(page.getByLabel('action-Action.Link-View')).toBeVisible();
await expect(page.getByRole('button', { name: 'singleLineText' })).not.toBeVisible(); await expect(page.getByRole('button', { name: 'singleLineText' })).not.toBeVisible();
await expect(page.getByRole('button', { name: 'phone' })).not.toBeVisible(); await expect(page.getByRole('button', { name: 'phone' })).not.toBeVisible();
}); });
@ -258,6 +260,54 @@ test.describe('update', () => {
await page.reload(); await page.reload();
await expect(page.getByLabel('action-Action.Link-Edit')).toBeVisible(); await expect(page.getByLabel('action-Action.Link-Edit')).toBeVisible();
}); });
test('individual collection permission support new data block', async ({
page,
mockPage,
mockRole,
mockRecord,
updateRole,
}) => {
await mockPage(newTableBlock).goto();
await mockRecord('general');
//新建角色并切换到新角色
const roleData = await mockRole({
allowNewMenu: true,
strategy: {
actions: ['update'],
},
resources: [
{
usingActionsConfig: true,
name: 'general',
actions: [{ name: 'view' }],
},
],
});
await page.evaluate((roleData) => {
window.localStorage.setItem('NOCOBASE_ROLE', roleData.name);
}, roleData);
await page.reload();
await mockPage(newTableBlock).goto();
await expect(page.getByLabel('block-item-CardItem-general-table')).toBeVisible();
await expect(page.getByLabel('action-Action.Link-Edit')).not.toBeVisible();
await updateRole({
name: roleData.name,
resources: [
{
usingActionsConfig: true,
name: 'general',
actions: [
{
name: 'view',
},
{ name: 'update' },
],
},
],
});
await page.reload();
await expect(page.getByLabel('action-Action.Link-Edit')).toBeVisible();
});
test('individual collection permission with fields', async ({ page, mockPage, mockRole, mockRecord }) => { test('individual collection permission with fields', async ({ page, mockPage, mockRole, mockRecord }) => {
await mockPage(oneTableBlock).goto(); await mockPage(oneTableBlock).goto();
await mockRecord('general'); await mockRecord('general');
@ -311,7 +361,7 @@ test.describe('destroy', () => {
await page.reload(); await page.reload();
await expect(page.getByLabel('action-Action-Delete-destroy-general-table')).toBeVisible(); await expect(page.getByLabel('action-Action-Delete-destroy-general-table')).toBeVisible();
}); });
test('individual collection permission', async ({ page, mockPage, mockRole, updateRole }) => { test('individual collection permission', async ({ page, mockPage, mockRole, mockRecord, updateRole }) => {
await mockPage().goto(); await mockPage().goto();
//新建角色并切换到新角色 //新建角色并切换到新角色
const roleData = await mockRole({ const roleData = await mockRole({
@ -332,8 +382,11 @@ test.describe('destroy', () => {
}, roleData); }, roleData);
await page.reload(); await page.reload();
await mockPage(oneTableBlock).goto(); await mockPage(oneTableBlock).goto();
await mockRecord('general');
await expect(page.getByLabel('block-item-CardItem-general-table')).toBeVisible(); await expect(page.getByLabel('block-item-CardItem-general-table')).toBeVisible();
await expect(page.getByLabel('action-Action-Delete-destroy-general-table')).not.toBeVisible(); await expect(page.getByLabel('action-Action-Delete-destroy-general-table')).not.toBeVisible();
await expect(page.getByLabel('action-Action.Link-Delete')).not.toBeVisible();
await updateRole({ await updateRole({
name: roleData.name, name: roleData.name,
resources: [ resources: [
@ -351,6 +404,57 @@ test.describe('destroy', () => {
}); });
await page.reload(); await page.reload();
await expect(page.getByLabel('action-Action-Delete-destroy-general-table')).toBeVisible(); await expect(page.getByLabel('action-Action-Delete-destroy-general-table')).toBeVisible();
await expect(page.getByLabel('action-Action.Link-Delete')).toBeVisible();
});
test('individual collection permission support new data block', async ({
page,
mockPage,
mockRole,
mockRecord,
updateRole,
}) => {
await mockPage().goto();
//新建角色并切换到新角色
const roleData = await mockRole({
allowNewMenu: true,
strategy: {
actions: ['destroy'],
},
resources: [
{
usingActionsConfig: true,
name: 'general',
actions: [{ name: 'view' }],
},
],
});
await page.evaluate((roleData) => {
window.localStorage.setItem('NOCOBASE_ROLE', roleData.name);
}, roleData);
await page.reload();
await mockPage(newTableBlock).goto();
await mockRecord('general');
await expect(page.getByLabel('block-item-CardItem-general-table')).toBeVisible();
await expect(page.getByLabel('action-Action-Delete-destroy-general-table')).not.toBeVisible();
await expect(page.getByLabel('action-Action.Link-Delete-')).not.toBeVisible();
await updateRole({
name: roleData.name,
resources: [
{
usingActionsConfig: true,
name: 'general',
actions: [
{
name: 'view',
},
{ name: 'destroy' },
],
},
],
});
await page.reload();
await expect(page.getByLabel('action-Action-Delete-destroy-general-table')).toBeVisible();
await expect(page.getByLabel('action-Action.Link-Delete-')).toBeVisible();
}); });
}); });

View File

@ -2182,6 +2182,34 @@ export const oneTableBlock: PageConfig = {
'x-async': false, 'x-async': false,
'x-index': 4, 'x-index': 4,
}, },
k4602nzuf6r: {
_isJSONSchemaObject: true,
version: '2.0',
title: '{{ t("Delete") }}',
'x-action': 'destroy',
'x-component': 'Action.Link',
'x-toolbar': 'ActionSchemaToolbar',
'x-settings': 'actionSettings:delete',
'x-component-props': {
icon: 'DeleteOutlined',
confirm: {
title: "{{t('Delete record')}}",
content: "{{t('Are you sure you want to delete it?')}}",
},
useProps: '{{ useDestroyActionProps }}',
},
'x-action-settings': {
triggerWorkflows: [],
},
'x-decorator': 'ACLActionProvider',
'x-designer-props': {
linkageAction: true,
},
type: 'void',
'x-uid': 'a6mt7vf9g67',
'x-async': false,
'x-index': 5,
},
}, },
'x-uid': 'mi05lvz5sj2', 'x-uid': 'mi05lvz5sj2',
'x-async': false, 'x-async': false,
@ -2548,3 +2576,545 @@ export const oneTableBlock: PageConfig = {
'x-index': 1, 'x-index': 1,
}, },
}; };
export const newTableBlock: PageConfig = {
collections: general,
pageSchema: {
_isJSONSchemaObject: true,
version: '2.0',
type: 'void',
'x-component': 'Page',
properties: {
'46txyuq0grs': {
_isJSONSchemaObject: true,
version: '2.0',
type: 'void',
'x-component': 'Grid',
'x-initializer': 'page:addBlock',
properties: {
zahcrjgcnp9: {
_isJSONSchemaObject: true,
version: '2.0',
type: 'void',
'x-component': 'Grid.Row',
properties: {
au2rt1euteu: {
_isJSONSchemaObject: true,
version: '2.0',
type: 'void',
'x-component': 'Grid.Col',
properties: {
ml4odxr7n6g: {
_isJSONSchemaObject: true,
version: '2.0',
type: 'void',
'x-decorator': 'TableBlockProvider',
'x-acl-action': 'general:list',
'x-decorator-props': {
collection: 'general',
dataSource: 'main',
action: 'list',
params: {
pageSize: 20,
},
rowKey: 'id',
showIndex: true,
dragSort: false,
disableTemplate: false,
},
'x-toolbar': 'BlockSchemaToolbar',
'x-settings': 'blockSettings:table',
'x-component': 'CardItem',
'x-filter-targets': [],
properties: {
actions: {
_isJSONSchemaObject: true,
version: '2.0',
type: 'void',
'x-initializer': 'table:configureActions',
'x-component': 'ActionBar',
'x-component-props': {
style: {
marginBottom: 'var(--nb-spacing)',
},
},
properties: {
slrfnm3niyj: {
_isJSONSchemaObject: true,
version: '2.0',
type: 'void',
title: '{{ t("Bulk update") }}',
'x-component': 'Action',
'x-align': 'right',
'x-acl-action': 'update',
'x-decorator': 'ACLActionProvider',
'x-acl-action-props': {
skipScopeCheck: true,
},
'x-action': 'customize:bulkUpdate',
'x-toolbar': 'ActionSchemaToolbar',
'x-settings': 'actionSettings:bulkUpdate',
'x-action-settings': {
assignedValues: {},
updateMode: 'selected',
onSuccess: {
manualClose: true,
redirecting: false,
successMessage: '{{t("Updated successfully")}}',
},
},
'x-component-props': {
icon: 'EditOutlined',
useProps: '{{ useCustomizeBulkUpdateActionProps }}',
},
'x-uid': 'n1qxijc21mx',
'x-async': false,
'x-index': 1,
},
'2zkhhoww1fr': {
_isJSONSchemaObject: true,
version: '2.0',
type: 'void',
title: '{{t("Bulk edit")}}',
'x-component': 'Action',
'x-action': 'customize:bulkEdit',
'x-action-settings': {
updateMode: 'selected',
},
'x-component-props': {
openMode: 'drawer',
icon: 'EditOutlined',
},
'x-align': 'right',
'x-decorator': 'ACLActionProvider',
'x-toolbar': 'ActionSchemaToolbar',
'x-settings': 'actionSettings:bulkEdit',
'x-acl-action': 'update',
'x-acl-action-props': {
skipScopeCheck: true,
},
properties: {
drawer: {
_isJSONSchemaObject: true,
version: '2.0',
type: 'void',
title: '{{t("Bulk edit")}}',
'x-component': 'Action.Container',
'x-component-props': {
className: 'nb-action-popup',
},
properties: {
tabs: {
_isJSONSchemaObject: true,
version: '2.0',
type: 'void',
'x-component': 'Tabs',
'x-component-props': {},
'x-initializer': 'TabPaneInitializersForBulkEditFormBlock',
properties: {
tab1: {
_isJSONSchemaObject: true,
version: '2.0',
type: 'void',
title: '{{t("Bulk edit")}}',
'x-component': 'Tabs.TabPane',
'x-designer': 'Tabs.Designer',
'x-component-props': {},
properties: {
grid: {
_isJSONSchemaObject: true,
version: '2.0',
type: 'void',
'x-component': 'Grid',
'x-initializer': 'popup:bulkEdit:addBlock',
'x-uid': '8nuffbe34bb',
'x-async': false,
'x-index': 1,
},
},
'x-uid': '4oldm9wc10s',
'x-async': false,
'x-index': 1,
},
},
'x-uid': '194thgnvcpy',
'x-async': false,
'x-index': 1,
},
},
'x-uid': '1x3ly7atx00',
'x-async': false,
'x-index': 1,
},
},
'x-uid': '75x1gquc69a',
'x-async': false,
'x-index': 2,
},
huteob4p7ua: {
_isJSONSchemaObject: true,
version: '2.0',
type: 'void',
'x-action': 'create',
'x-acl-action': 'create',
title: "{{t('Add new')}}",
'x-toolbar': 'ActionSchemaToolbar',
'x-settings': 'actionSettings:addNew',
'x-component': 'Action',
'x-decorator': 'ACLActionProvider',
'x-component-props': {
openMode: 'drawer',
type: 'primary',
component: 'CreateRecordAction',
icon: 'PlusOutlined',
},
'x-align': 'right',
'x-acl-action-props': {
skipScopeCheck: true,
},
properties: {
drawer: {
_isJSONSchemaObject: true,
version: '2.0',
type: 'void',
title: '{{ t("Add record") }}',
'x-component': 'Action.Container',
'x-component-props': {
className: 'nb-action-popup',
},
properties: {
tabs: {
_isJSONSchemaObject: true,
version: '2.0',
type: 'void',
'x-component': 'Tabs',
'x-component-props': {},
'x-initializer': 'TabPaneInitializersForCreateFormBlock',
properties: {
tab1: {
_isJSONSchemaObject: true,
version: '2.0',
type: 'void',
title: '{{t("Add new")}}',
'x-component': 'Tabs.TabPane',
'x-designer': 'Tabs.Designer',
'x-component-props': {},
properties: {
grid: {
_isJSONSchemaObject: true,
version: '2.0',
type: 'void',
'x-component': 'Grid',
'x-initializer': 'popup:addNew:addBlock',
'x-uid': 'yjj9tl588o1',
'x-async': false,
'x-index': 1,
},
},
'x-uid': '0zjlqupqrd0',
'x-async': false,
'x-index': 1,
},
},
'x-uid': 'sjmso5vq3bc',
'x-async': false,
'x-index': 1,
},
},
'x-uid': '131b76phmyr',
'x-async': false,
'x-index': 1,
},
},
'x-uid': '4ekiy4xn5ip',
'x-async': false,
'x-index': 3,
},
xi969uyvexr: {
_isJSONSchemaObject: true,
version: '2.0',
title: '{{ t("Delete") }}',
'x-action': 'destroy',
'x-component': 'Action',
'x-toolbar': 'ActionSchemaToolbar',
'x-settings': 'actionSettings:bulkDelete',
'x-decorator': 'ACLActionProvider',
'x-acl-action-props': {
skipScopeCheck: true,
},
'x-component-props': {
icon: 'DeleteOutlined',
confirm: {
title: "{{t('Delete record')}}",
content: "{{t('Are you sure you want to delete it?')}}",
},
useProps: '{{ useBulkDestroyActionProps }}',
},
'x-action-settings': {
triggerWorkflows: [],
},
'x-acl-action': 'general:destroy',
'x-align': 'right',
type: 'void',
'x-uid': 'x5nhm8j5prk',
'x-async': false,
'x-index': 4,
},
},
'x-uid': 's99upcj5h12',
'x-async': false,
'x-index': 1,
},
'1pflm3akx4z': {
_isJSONSchemaObject: true,
version: '2.0',
type: 'array',
'x-initializer': 'table:configureColumns',
'x-component': 'TableV2',
'x-component-props': {
rowKey: 'id',
rowSelection: {
type: 'checkbox',
},
useProps: '{{ useTableBlockProps }}',
},
properties: {
actions: {
_isJSONSchemaObject: true,
version: '2.0',
type: 'void',
title: '{{ t("Actions") }}',
'x-action-column': 'actions',
'x-decorator': 'TableV2.Column.ActionBar',
'x-component': 'TableV2.Column',
'x-designer': 'TableV2.ActionColumnDesigner',
'x-initializer': 'table:configureItemActions',
properties: {
'0vgecinvudu': {
_isJSONSchemaObject: true,
version: '2.0',
type: 'void',
'x-decorator': 'DndContext',
'x-component': 'Space',
'x-component-props': {
split: '|',
},
properties: {
kieddfdng7p: {
_isJSONSchemaObject: true,
version: '2.0',
type: 'void',
title: '{{ t("View") }}',
'x-action': 'view',
'x-toolbar': 'ActionSchemaToolbar',
'x-settings': 'actionSettings:view',
'x-component': 'Action.Link',
'x-component-props': {
openMode: 'drawer',
},
'x-decorator': 'ACLActionProvider',
'x-designer-props': {
linkageAction: true,
},
properties: {
drawer: {
_isJSONSchemaObject: true,
version: '2.0',
type: 'void',
title: '{{ t("View record") }}',
'x-component': 'Action.Container',
'x-component-props': {
className: 'nb-action-popup',
},
properties: {
tabs: {
_isJSONSchemaObject: true,
version: '2.0',
type: 'void',
'x-component': 'Tabs',
'x-component-props': {},
'x-initializer': 'TabPaneInitializers',
properties: {
tab1: {
_isJSONSchemaObject: true,
version: '2.0',
type: 'void',
title: '{{t("Details")}}',
'x-component': 'Tabs.TabPane',
'x-designer': 'Tabs.Designer',
'x-component-props': {},
properties: {
grid: {
_isJSONSchemaObject: true,
version: '2.0',
type: 'void',
'x-component': 'Grid',
'x-initializer': 'popup:common:addBlock',
'x-uid': '2k0540e57ol',
'x-async': false,
'x-index': 1,
},
},
'x-uid': 's7gi356fs70',
'x-async': false,
'x-index': 1,
},
},
'x-uid': '8grec6h6mtp',
'x-async': false,
'x-index': 1,
},
},
'x-uid': 'assiov38tvg',
'x-async': false,
'x-index': 1,
},
},
'x-uid': 'utm143emmhc',
'x-async': false,
'x-index': 1,
},
is523lf1al3: {
_isJSONSchemaObject: true,
version: '2.0',
type: 'void',
title: '{{ t("Edit") }}',
'x-action': 'update',
'x-toolbar': 'ActionSchemaToolbar',
'x-settings': 'actionSettings:edit',
'x-component': 'Action.Link',
'x-component-props': {
openMode: 'drawer',
icon: 'EditOutlined',
},
'x-decorator': 'ACLActionProvider',
'x-designer-props': {
linkageAction: true,
},
properties: {
drawer: {
_isJSONSchemaObject: true,
version: '2.0',
type: 'void',
title: '{{ t("Edit record") }}',
'x-component': 'Action.Container',
'x-component-props': {
className: 'nb-action-popup',
},
properties: {
tabs: {
_isJSONSchemaObject: true,
version: '2.0',
type: 'void',
'x-component': 'Tabs',
'x-component-props': {},
'x-initializer': 'TabPaneInitializers',
properties: {
tab1: {
_isJSONSchemaObject: true,
version: '2.0',
type: 'void',
title: '{{t("Edit")}}',
'x-component': 'Tabs.TabPane',
'x-designer': 'Tabs.Designer',
'x-component-props': {},
properties: {
grid: {
_isJSONSchemaObject: true,
version: '2.0',
type: 'void',
'x-component': 'Grid',
'x-initializer': 'popup:common:addBlock',
'x-uid': 'wsyp993s4e3',
'x-async': false,
'x-index': 1,
},
},
'x-uid': 'cffbmo4sb6k',
'x-async': false,
'x-index': 1,
},
},
'x-uid': '9dwrb18ntjm',
'x-async': false,
'x-index': 1,
},
},
'x-uid': 'rz924lz6i2u',
'x-async': false,
'x-index': 1,
},
},
'x-uid': 'nkrdjd1jz5j',
'x-async': false,
'x-index': 2,
},
k4602nzuf6r: {
_isJSONSchemaObject: true,
version: '2.0',
title: '{{ t("Delete") }}',
'x-action': 'destroy',
'x-component': 'Action.Link',
'x-toolbar': 'ActionSchemaToolbar',
'x-settings': 'actionSettings:delete',
'x-component-props': {
icon: 'DeleteOutlined',
confirm: {
title: "{{t('Delete record')}}",
content: "{{t('Are you sure you want to delete it?')}}",
},
useProps: '{{ useDestroyActionProps }}',
},
'x-action-settings': {
triggerWorkflows: [],
},
'x-decorator': 'ACLActionProvider',
'x-designer-props': {
linkageAction: true,
},
type: 'void',
'x-uid': 'a6mt7vf9g67',
'x-async': false,
'x-index': 3,
},
},
'x-uid': '7q9j7135hk4',
'x-async': false,
'x-index': 1,
},
},
'x-uid': 'c8iecn06wyp',
'x-async': false,
'x-index': 1,
},
},
'x-uid': 'm0blrbf9bzr',
'x-async': false,
'x-index': 2,
},
},
'x-uid': '63uhxny4lrn',
'x-async': false,
'x-index': 1,
},
},
'x-uid': 'tcne2atmx0n',
'x-async': false,
'x-index': 1,
},
},
'x-uid': 'bk1yx2i13k8',
'x-async': false,
'x-index': 1,
},
},
'x-uid': 'if4rb336r5q',
'x-async': false,
'x-index': 1,
},
},
'x-uid': '532o6vwg8bi',
'x-async': true,
'x-index': 1,
},
};

View File

@ -77,8 +77,7 @@ export class DualAxes extends G2PlotChart {
yField, yField,
colorField: () => { colorField: () => {
const props = fieldProps[yField]; const props = fieldProps[yField];
const transformer = props?.transformer; return props?.label || yField;
return props?.label || (transformer ? transformer(yField) : yField);
}, },
axis: { axis: {
y: { y: {

View File

@ -1,4 +1,3 @@
import { transform } from 'lodash';
import { Chart, ChartProps, ChartType, RenderProps } from '../chart'; import { Chart, ChartProps, ChartType, RenderProps } from '../chart';
import configs from './configs'; import configs from './configs';
@ -25,31 +24,17 @@ export class G2PlotChart extends Chart {
}; };
getProps({ data, general, advanced, fieldProps }: RenderProps) { getProps({ data, general, advanced, fieldProps }: RenderProps) {
const meta = {};
// Some charts render wrong when the field name contains a dot in G2Plot
const replace = (key: string) => key.replace(/\./g, '_');
general = Object.entries(general).reduce((obj, [key, value]) => {
obj[key] = value;
if (key.includes('Field')) {
if (Array.isArray(value)) {
obj[key] = value.map((v) => (v?.includes('.') ? replace(v) : v));
} else if (typeof value === 'string' && value.includes('.')) {
obj[key] = replace(value);
}
}
return obj;
}, {});
const config = { const config = {
legend: { legend: {
color: { color: {
itemLabelText: (datnum) => { itemLabelText: (datnum: { label: string }) => {
const props = fieldProps[datnum.label]; const props = fieldProps[general.seriesField];
const transformer = props?.transformer; const transformer = props?.transformer;
return props?.label || (transformer ? transformer(datnum.label) : datnum.label); return transformer ? transformer(datnum.label) : datnum.label;
}, },
}, },
}, },
tooltip: (d, index, data, column) => { tooltip: (d, index: number, data, column: any) => {
const field = column.y.field; const field = column.y.field;
const props = fieldProps[field]; const props = fieldProps[field];
const name = props?.label || field; const name = props?.label || field;
@ -59,30 +44,21 @@ export class G2PlotChart extends Chart {
}, },
axis: { axis: {
x: { x: {
labelFormatter: (datnum) => { labelFormatter: (datnum: any) => {
const props = fieldProps[general.xField]; const props = fieldProps[general.xField];
const transformer = props?.transformer; const transformer = props?.transformer;
return transformer ? transformer(datnum) : datnum; return transformer ? transformer(datnum) : datnum;
}, },
}, },
y: { y: {
labelFormatter: (datnum) => { labelFormatter: (datnum: any) => {
const props = fieldProps[general.yField]; const props = fieldProps[general.yField];
const transformer = props?.transformer; const transformer = props?.transformer;
return transformer ? transformer(datnum) : datnum; return transformer ? transformer(datnum) : datnum;
}, },
}, },
}, },
data: data.map((item) => { data,
const obj = {};
Object.entries(item).forEach(([key, value]) => {
if (key.includes('.')) {
key = replace(key);
}
obj[key] = value;
});
return obj;
}),
theme: 'classic', theme: 'classic',
animate: { animate: {
enter: { enter: {