mirror of
https://github.com/nocobase/nocobase
synced 2024-11-15 03:46:08 +00:00
Merge branch 'main' into next
This commit is contained in:
commit
f6db64af30
@ -7,7 +7,6 @@
|
||||
* For more information, please refer to: https://www.nocobase.com/agreement.
|
||||
*/
|
||||
|
||||
import _ from 'lodash';
|
||||
import React, { createContext, useCallback, useMemo } from 'react';
|
||||
import { AssociationSelect } from './AssociationSelect';
|
||||
import { InternalFileManager } from './FileManager';
|
||||
@ -29,7 +28,7 @@ export enum AssociationFieldMode {
|
||||
}
|
||||
|
||||
interface AssociationFieldModeProviderProps {
|
||||
modeToComponent: Partial<Record<AssociationFieldMode, React.FC | ((originalCom: React.FC) => React.FC)>>;
|
||||
modeToComponent: Partial<Record<AssociationFieldMode, React.FC>>;
|
||||
}
|
||||
|
||||
const defaultModeToComponent = {
|
||||
@ -45,11 +44,15 @@ const defaultModeToComponent = {
|
||||
const AssociationFieldModeContext = createContext<{
|
||||
modeToComponent: AssociationFieldModeProviderProps['modeToComponent'];
|
||||
getComponent: (mode: AssociationFieldMode) => React.FC;
|
||||
getDefaultComponent: (mode: AssociationFieldMode) => React.FC;
|
||||
}>({
|
||||
modeToComponent: defaultModeToComponent,
|
||||
getComponent: (mode: AssociationFieldMode) => {
|
||||
return defaultModeToComponent[mode];
|
||||
},
|
||||
getDefaultComponent: (mode: AssociationFieldMode) => {
|
||||
return defaultModeToComponent[mode];
|
||||
},
|
||||
});
|
||||
|
||||
export const AssociationFieldModeProvider: React.FC<AssociationFieldModeProviderProps> = (props) => {
|
||||
@ -61,18 +64,19 @@ export const AssociationFieldModeProvider: React.FC<AssociationFieldModeProvider
|
||||
|
||||
const getComponent = useCallback(
|
||||
(mode: AssociationFieldMode) => {
|
||||
const component = modeToComponent[mode];
|
||||
|
||||
if (_.isFunction(component)) {
|
||||
return component(defaultModeToComponent[mode]) as React.FC;
|
||||
}
|
||||
|
||||
return component || defaultModeToComponent[mode];
|
||||
return modeToComponent[mode] || defaultModeToComponent[mode];
|
||||
},
|
||||
[modeToComponent],
|
||||
);
|
||||
|
||||
const value = useMemo(() => ({ modeToComponent, getComponent }), [getComponent, modeToComponent]);
|
||||
const getDefaultComponent = useCallback((mode: AssociationFieldMode) => {
|
||||
return defaultModeToComponent[mode];
|
||||
}, []);
|
||||
|
||||
const value = useMemo(
|
||||
() => ({ modeToComponent, getComponent, getDefaultComponent }),
|
||||
[getComponent, modeToComponent, getDefaultComponent],
|
||||
);
|
||||
return <AssociationFieldModeContext.Provider value={value}>{props.children}</AssociationFieldModeContext.Provider>;
|
||||
};
|
||||
|
||||
|
@ -0,0 +1,92 @@
|
||||
/**
|
||||
* This file is part of the NocoBase (R) project.
|
||||
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
||||
* Authors: NocoBase Team.
|
||||
*
|
||||
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
||||
* For more information, please refer to: https://www.nocobase.com/agreement.
|
||||
*/
|
||||
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
import { describe, expect, it, vi } from 'vitest';
|
||||
import {
|
||||
AssociationFieldMode,
|
||||
AssociationFieldModeProvider,
|
||||
useAssociationFieldModeContext,
|
||||
} from '../AssociationFieldModeProvider';
|
||||
|
||||
vi.mock('../AssociationSelect', () => ({
|
||||
AssociationSelect: () => <div>Association Select</div>,
|
||||
}));
|
||||
|
||||
vi.mock('../InternalPicker', () => ({
|
||||
InternalPicker: () => <div>Internal Picker</div>,
|
||||
}));
|
||||
|
||||
describe('AssociationFieldModeProvider', () => {
|
||||
it('should correctly provide the default modeToComponent mapping', () => {
|
||||
const TestComponent = () => {
|
||||
const { modeToComponent } = useAssociationFieldModeContext();
|
||||
return <div>{Object.keys(modeToComponent).join(',')} </div>;
|
||||
};
|
||||
|
||||
render(
|
||||
<AssociationFieldModeProvider modeToComponent={{}}>
|
||||
<TestComponent />
|
||||
</AssociationFieldModeProvider>,
|
||||
);
|
||||
|
||||
expect(screen.getByText('Picker,Nester,PopoverNester,Select,SubTable,FileManager,CascadeSelect')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should allow overriding the default modeToComponent mapping', () => {
|
||||
const CustomComponent = () => <div>Custom Component</div>;
|
||||
const TestComponent = () => {
|
||||
const { getComponent } = useAssociationFieldModeContext();
|
||||
const Component = getComponent(AssociationFieldMode.Picker);
|
||||
return <Component />;
|
||||
};
|
||||
|
||||
render(
|
||||
<AssociationFieldModeProvider modeToComponent={{ [AssociationFieldMode.Picker]: CustomComponent }}>
|
||||
<TestComponent />
|
||||
</AssociationFieldModeProvider>,
|
||||
);
|
||||
|
||||
expect(screen.getByText('Custom Component')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('getComponent should return the default component if no custom component is found', () => {
|
||||
const TestComponent = () => {
|
||||
const { getComponent } = useAssociationFieldModeContext();
|
||||
const Component = getComponent(AssociationFieldMode.Select);
|
||||
return <Component />;
|
||||
};
|
||||
|
||||
render(
|
||||
<AssociationFieldModeProvider modeToComponent={{}}>
|
||||
<TestComponent />
|
||||
</AssociationFieldModeProvider>,
|
||||
);
|
||||
|
||||
expect(screen.getByText('Association Select')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('getDefaultComponent should always return the default component', () => {
|
||||
const CustomComponent = () => <div>Custom Component</div>;
|
||||
const TestComponent = () => {
|
||||
const { getDefaultComponent } = useAssociationFieldModeContext();
|
||||
const Component = getDefaultComponent(AssociationFieldMode.Picker);
|
||||
return <Component />;
|
||||
};
|
||||
|
||||
render(
|
||||
<AssociationFieldModeProvider modeToComponent={{ [AssociationFieldMode.Picker]: CustomComponent }}>
|
||||
<TestComponent />
|
||||
</AssociationFieldModeProvider>,
|
||||
);
|
||||
|
||||
expect(screen.getByText('Internal Picker')).toBeTruthy();
|
||||
});
|
||||
});
|
@ -15,7 +15,11 @@ import { Nester } from './Nester';
|
||||
import { ReadPretty } from './ReadPretty';
|
||||
import { SubTable } from './SubTable';
|
||||
|
||||
export { AssociationFieldModeProvider } from './AssociationFieldModeProvider';
|
||||
export {
|
||||
AssociationFieldMode,
|
||||
AssociationFieldModeProvider,
|
||||
useAssociationFieldModeContext,
|
||||
} from './AssociationFieldModeProvider';
|
||||
export const AssociationField: any = connect(Editable, mapReadPretty(ReadPretty));
|
||||
|
||||
AssociationField.SubTable = SubTable;
|
||||
|
@ -11,16 +11,17 @@ import {
|
||||
Action,
|
||||
AdminProvider,
|
||||
AntdAppProvider,
|
||||
AssociationFieldMode,
|
||||
AssociationFieldModeProvider,
|
||||
BlockTemplateProvider,
|
||||
GlobalThemeProvider,
|
||||
OpenModeProvider,
|
||||
useAssociationFieldModeContext,
|
||||
usePlugin,
|
||||
} from '@nocobase/client';
|
||||
import React from 'react';
|
||||
import { isDesktop } from 'react-device-detect';
|
||||
|
||||
import _ from 'lodash';
|
||||
import { ActionDrawerUsedInMobile, useToAdaptActionDrawerToMobile } from '../adaptor-of-desktop/ActionDrawer';
|
||||
import { BasicZIndexProvider } from '../adaptor-of-desktop/BasicZIndexProvider';
|
||||
import { useToAdaptFilterActionToMobile } from '../adaptor-of-desktop/FilterAction';
|
||||
@ -67,9 +68,11 @@ export const Mobile = () => {
|
||||
const DesktopComponent = mobilePlugin.desktopMode === false ? React.Fragment : DesktopMode;
|
||||
const modeToComponent = React.useMemo(() => {
|
||||
return {
|
||||
PopoverNester: _.memoize((OriginComponent) => (props) => (
|
||||
<InternalPopoverNesterUsedInMobile {...props} OriginComponent={OriginComponent} />
|
||||
)),
|
||||
PopoverNester: (props) => {
|
||||
const { getDefaultComponent } = useAssociationFieldModeContext();
|
||||
const OriginComponent = getDefaultComponent(AssociationFieldMode.PopoverNester);
|
||||
return <InternalPopoverNesterUsedInMobile {...props} OriginComponent={OriginComponent} />;
|
||||
},
|
||||
};
|
||||
}, []);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user