mirror of
https://gitee.com/baidu/amis.git
synced 2024-12-02 03:58:07 +08:00
Merge branch 'master' into fix-service
This commit is contained in:
commit
a0a1f971f4
@ -98,7 +98,13 @@ import Overlay from './components/Overlay';
|
|||||||
import PopOver from './components/PopOver';
|
import PopOver from './components/PopOver';
|
||||||
import {FormRenderer} from './renderers/Form';
|
import {FormRenderer} from './renderers/Form';
|
||||||
import type {FormHorizontal, FormSchemaBase} from './renderers/Form';
|
import type {FormHorizontal, FormSchemaBase} from './renderers/Form';
|
||||||
import {enableDebug, promisify, replaceText, wrapFetcher} from './utils/index';
|
import {
|
||||||
|
enableDebug,
|
||||||
|
disableDebug,
|
||||||
|
promisify,
|
||||||
|
replaceText,
|
||||||
|
wrapFetcher
|
||||||
|
} from './utils/index';
|
||||||
import type {OnEventProps} from './utils/index';
|
import type {OnEventProps} from './utils/index';
|
||||||
import {valueMap as styleMap} from './utils/style-helper';
|
import {valueMap as styleMap} from './utils/style-helper';
|
||||||
import {RENDERER_TRANSMISSION_OMIT_PROPS} from './SchemaRenderer';
|
import {RENDERER_TRANSMISSION_OMIT_PROPS} from './SchemaRenderer';
|
||||||
@ -195,7 +201,9 @@ export {
|
|||||||
OnEventProps,
|
OnEventProps,
|
||||||
FormSchemaBase,
|
FormSchemaBase,
|
||||||
filterTarget,
|
filterTarget,
|
||||||
CustomStyle
|
CustomStyle,
|
||||||
|
enableDebug,
|
||||||
|
disableDebug
|
||||||
};
|
};
|
||||||
|
|
||||||
export function render(
|
export function render(
|
||||||
@ -257,13 +265,6 @@ function AMISRenderer({
|
|||||||
translate
|
translate
|
||||||
} as any;
|
} as any;
|
||||||
|
|
||||||
if (options.enableAMISDebug) {
|
|
||||||
// 因为里面还有 render
|
|
||||||
setTimeout(() => {
|
|
||||||
enableDebug();
|
|
||||||
}, 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
store = RendererStore.create({}, options);
|
store = RendererStore.create({}, options);
|
||||||
stores[options.session || 'global'] = store;
|
stores[options.session || 'global'] = store;
|
||||||
} else {
|
} else {
|
||||||
@ -291,6 +292,11 @@ function AMISRenderer({
|
|||||||
}
|
}
|
||||||
env.theme = getTheme(theme);
|
env.theme = getTheme(theme);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
env.enableAMISDebug ? enableDebug() : disableDebug();
|
||||||
|
return () => env.enableAMISDebug || disableDebug();
|
||||||
|
}, [env.enableAMISDebug]);
|
||||||
|
|
||||||
if (props.locale !== undefined) {
|
if (props.locale !== undefined) {
|
||||||
env.translate = translate;
|
env.translate = translate;
|
||||||
env.locale = locale;
|
env.locale = locale;
|
||||||
|
@ -223,7 +223,10 @@ export interface ApiObject extends BaseApiObject {
|
|||||||
api: ApiObject,
|
api: ApiObject,
|
||||||
context: any
|
context: any
|
||||||
) => any;
|
) => any;
|
||||||
requestAdaptor?: (api: ApiObject, context: any) => ApiObject;
|
requestAdaptor?: (
|
||||||
|
api: ApiObject,
|
||||||
|
context: any
|
||||||
|
) => ApiObject | Promise<ApiObject>;
|
||||||
/** 是否过滤为空字符串的 query 参数 */
|
/** 是否过滤为空字符串的 query 参数 */
|
||||||
filterEmptyQuery?: boolean;
|
filterEmptyQuery?: boolean;
|
||||||
}
|
}
|
||||||
|
@ -76,7 +76,7 @@ export function buildApi(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (api.requestAdaptor && typeof api.requestAdaptor === 'string') {
|
if (api.requestAdaptor && typeof api.requestAdaptor === 'string') {
|
||||||
api.requestAdaptor = str2function(
|
api.requestAdaptor = str2AsyncFunction(
|
||||||
api.requestAdaptor,
|
api.requestAdaptor,
|
||||||
'api',
|
'api',
|
||||||
'context'
|
'context'
|
||||||
@ -84,7 +84,7 @@ export function buildApi(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (api.adaptor && typeof api.adaptor === 'string') {
|
if (api.adaptor && typeof api.adaptor === 'string') {
|
||||||
api.adaptor = str2function(
|
api.adaptor = str2AsyncFunction(
|
||||||
api.adaptor,
|
api.adaptor,
|
||||||
'payload',
|
'payload',
|
||||||
'response',
|
'response',
|
||||||
@ -464,12 +464,16 @@ export function wrapFetcher(
|
|||||||
return fn as any;
|
return fn as any;
|
||||||
}
|
}
|
||||||
|
|
||||||
const wrappedFetcher = function (api: Api, data: object, options?: object) {
|
const wrappedFetcher = async function (
|
||||||
|
api: Api,
|
||||||
|
data: object,
|
||||||
|
options?: object
|
||||||
|
) {
|
||||||
api = buildApi(api, data, options) as ApiObject;
|
api = buildApi(api, data, options) as ApiObject;
|
||||||
|
|
||||||
if (api.requestAdaptor) {
|
if (api.requestAdaptor) {
|
||||||
debug('api', 'before requestAdaptor', api);
|
debug('api', 'before requestAdaptor', api);
|
||||||
api = api.requestAdaptor(api, data) || api;
|
api = (await api.requestAdaptor(api, data)) || api;
|
||||||
debug('api', 'after requestAdaptor', api);
|
debug('api', 'after requestAdaptor', api);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,9 +2,10 @@
|
|||||||
* amis 运行时调试功能,为了避免循环引用,这个组件不要依赖 amis 里的组件
|
* amis 运行时调试功能,为了避免循环引用,这个组件不要依赖 amis 里的组件
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React, {Component, useEffect, useRef, useState} from 'react';
|
import React, {Component, useEffect, useRef, useState, version} from 'react';
|
||||||
import cx from 'classnames';
|
import cx from 'classnames';
|
||||||
import {findDOMNode, render} from 'react-dom';
|
import {findDOMNode, render, unmountComponentAtNode} from 'react-dom';
|
||||||
|
import {createRoot} from 'react-dom/client';
|
||||||
import {autorun, observable} from 'mobx';
|
import {autorun, observable} from 'mobx';
|
||||||
import {observer} from 'mobx-react';
|
import {observer} from 'mobx-react';
|
||||||
import {uuidv4} from './helper';
|
import {uuidv4} from './helper';
|
||||||
@ -84,16 +85,18 @@ const LogView = observer(({store}: {store: AMISDebugStore}) => {
|
|||||||
[{log.cat}] {log.msg}
|
[{log.cat}] {log.msg}
|
||||||
</div>
|
</div>
|
||||||
{log.ext ? (
|
{log.ext ? (
|
||||||
<JsonView
|
<React.Suspense fallback={<div>Loading...</div>}>
|
||||||
name={null}
|
<JsonView
|
||||||
theme="monokai"
|
name={null}
|
||||||
src={JSON.parse(log.ext)}
|
theme="monokai"
|
||||||
collapsed={true}
|
src={JSON.parse(log.ext)}
|
||||||
enableClipboard={false}
|
collapsed={true}
|
||||||
displayDataTypes={false}
|
enableClipboard={false}
|
||||||
collapseStringsAfterLength={ellipsisThreshold}
|
displayDataTypes={false}
|
||||||
iconStyle="square"
|
collapseStringsAfterLength={ellipsisThreshold}
|
||||||
/>
|
iconStyle="square"
|
||||||
|
/>
|
||||||
|
</React.Suspense>
|
||||||
) : null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@ -126,16 +129,18 @@ const AMISDebug = observer(({store}: {store: AMISDebugStore}) => {
|
|||||||
stackDataView.push(
|
stackDataView.push(
|
||||||
<div key={`data-${level}`}>
|
<div key={`data-${level}`}>
|
||||||
<h3>Data Level-{level}</h3>
|
<h3>Data Level-{level}</h3>
|
||||||
<JsonView
|
<React.Suspense fallback={<div>Loading...</div>}>
|
||||||
key={`dataview-${stack}`}
|
<JsonView
|
||||||
name={null}
|
key={`dataview-${stack}`}
|
||||||
theme="monokai"
|
name={null}
|
||||||
src={stack}
|
theme="monokai"
|
||||||
collapsed={level === 0 ? false : true}
|
src={stack}
|
||||||
enableClipboard={false}
|
collapsed={level === 0 ? false : true}
|
||||||
displayDataTypes={false}
|
enableClipboard={false}
|
||||||
iconStyle="square"
|
displayDataTypes={false}
|
||||||
/>
|
iconStyle="square"
|
||||||
|
/>
|
||||||
|
</React.Suspense>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
level += 1;
|
level += 1;
|
||||||
@ -319,7 +324,7 @@ function handleMouseclick(e: MouseEvent) {
|
|||||||
}
|
}
|
||||||
const dom = e.target as HTMLElement;
|
const dom = e.target as HTMLElement;
|
||||||
const target = dom.closest(`[data-debug-id]`);
|
const target = dom.closest(`[data-debug-id]`);
|
||||||
if (target) {
|
if (target && !target.closest('.AMISDebug')) {
|
||||||
store.activeId = target.getAttribute('data-debug-id')!;
|
store.activeId = target.getAttribute('data-debug-id')!;
|
||||||
store.tab = 'inspect';
|
store.tab = 'inspect';
|
||||||
}
|
}
|
||||||
@ -366,6 +371,7 @@ autorun(() => {
|
|||||||
|
|
||||||
// 页面中只能有一个实例
|
// 页面中只能有一个实例
|
||||||
let isEnabled = false;
|
let isEnabled = false;
|
||||||
|
let unmount: () => void;
|
||||||
|
|
||||||
export function enableDebug() {
|
export function enableDebug() {
|
||||||
if (isEnabled) {
|
if (isEnabled) {
|
||||||
@ -376,7 +382,21 @@ export function enableDebug() {
|
|||||||
const amisDebugElement = document.createElement('div');
|
const amisDebugElement = document.createElement('div');
|
||||||
document.body.appendChild(amisDebugElement);
|
document.body.appendChild(amisDebugElement);
|
||||||
const element = <AMISDebug store={store} />;
|
const element = <AMISDebug store={store} />;
|
||||||
render(element, amisDebugElement);
|
|
||||||
|
if (parseInt(version.split('.')[0], 10) >= 18) {
|
||||||
|
const root = createRoot(amisDebugElement);
|
||||||
|
root.render(element);
|
||||||
|
unmount = () => {
|
||||||
|
root.unmount();
|
||||||
|
document.body.removeChild(amisDebugElement);
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
render(element, amisDebugElement);
|
||||||
|
unmount = () => {
|
||||||
|
unmountComponentAtNode(amisDebugElement);
|
||||||
|
document.body.removeChild(amisDebugElement);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
document.body.appendChild(amisHoverBox);
|
document.body.appendChild(amisHoverBox);
|
||||||
document.body.appendChild(amisActiveBox);
|
document.body.appendChild(amisActiveBox);
|
||||||
@ -384,6 +404,18 @@ export function enableDebug() {
|
|||||||
document.addEventListener('click', handleMouseclick);
|
document.addEventListener('click', handleMouseclick);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function disableDebug() {
|
||||||
|
if (!isEnabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
isEnabled = false;
|
||||||
|
unmount?.();
|
||||||
|
document.body.removeChild(amisHoverBox);
|
||||||
|
document.body.removeChild(amisActiveBox);
|
||||||
|
document.removeEventListener('mousemove', handleMouseMove);
|
||||||
|
document.removeEventListener('click', handleMouseclick);
|
||||||
|
}
|
||||||
|
|
||||||
interface DebugWrapperProps {
|
interface DebugWrapperProps {
|
||||||
renderer: any;
|
renderer: any;
|
||||||
children?: React.ReactNode;
|
children?: React.ReactNode;
|
||||||
|
@ -40,6 +40,7 @@
|
|||||||
|
|
||||||
&-tab {
|
&-tab {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
border-bottom: 1px solid #3d3d3d;
|
||||||
}
|
}
|
||||||
|
|
||||||
&-tab > button {
|
&-tab > button {
|
||||||
@ -90,6 +91,7 @@
|
|||||||
&-content {
|
&-content {
|
||||||
pointer-events: all;
|
pointer-events: all;
|
||||||
display: none;
|
display: none;
|
||||||
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
&-resize {
|
&-resize {
|
||||||
@ -122,7 +124,7 @@
|
|||||||
|
|
||||||
&.is-expanded {
|
&.is-expanded {
|
||||||
width: 420px;
|
width: 420px;
|
||||||
overflow: auto;
|
|
||||||
background: #272821;
|
background: #272821;
|
||||||
color: #cccccc;
|
color: #cccccc;
|
||||||
box-shadow: rgba(0, 0, 0, 0.24) 0px 3px 8px;
|
box-shadow: rgba(0, 0, 0, 0.24) 0px 3px 8px;
|
||||||
@ -168,6 +170,37 @@
|
|||||||
padding: var(--gap-sm);
|
padding: var(--gap-sm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&-log,
|
||||||
|
&-inspect {
|
||||||
|
height: 100%;
|
||||||
|
overflow: auto;
|
||||||
|
|
||||||
|
// 火狐浏览器
|
||||||
|
scrollbar-width: thin;
|
||||||
|
scrollbar-color: #6b6b6b #2b2b2b;
|
||||||
|
&::-webkit-scrollbar {
|
||||||
|
position: relative;
|
||||||
|
z-index: 10;
|
||||||
|
background-color: #2c2c2c;
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
border-left: 1px solid #3d3d3d;
|
||||||
|
// border-top: 1px solid #3d3d3d;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::-webkit-scrollbar-thumb {
|
||||||
|
background: #6b6b6b;
|
||||||
|
background-clip: content-box;
|
||||||
|
border: 4px solid transparent;
|
||||||
|
border-radius: 500px;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: #939393;
|
||||||
|
background-clip: content-box;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&-logLine {
|
&-logLine {
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
}
|
}
|
||||||
|
@ -89,11 +89,20 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&-body {
|
&-body {
|
||||||
padding: var(--drawer-content-paddingTop) var(--drawer-content-paddingRight)
|
padding: 0 var(--drawer-content-paddingRight)
|
||||||
var(--drawer-content-paddingBottom) var(--drawer-content-paddingLeft);
|
var(--drawer-content-paddingBottom) var(--drawer-content-paddingLeft);
|
||||||
flex-basis: 0;
|
flex-basis: 0;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
|
|
||||||
|
// 因为如果成员里面有 position:sticky 的内容
|
||||||
|
// 用 padding 会导致位置不正确
|
||||||
|
// 所以改成这种写法
|
||||||
|
&:before {
|
||||||
|
content: '';
|
||||||
|
display: block;
|
||||||
|
height: var(--drawer-content-paddingTop);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&-footer {
|
&-footer {
|
||||||
|
@ -350,6 +350,7 @@
|
|||||||
|
|
||||||
&-submenu-title {
|
&-submenu-title {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
|
||||||
.#{$ns}Nav-Menu-item-wrap {
|
.#{$ns}Nav-Menu-item-wrap {
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
* @author fex
|
* @author fex
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React, {version} from 'react';
|
||||||
import {render} from 'react-dom';
|
import {render} from 'react-dom';
|
||||||
import Modal from './Modal';
|
import Modal from './Modal';
|
||||||
import Button from './Button';
|
import Button from './Button';
|
||||||
@ -11,6 +11,7 @@ import {ClassNamesFn, themeable, ThemeProps} from 'amis-core';
|
|||||||
import {LocaleProps, localeable} from 'amis-core';
|
import {LocaleProps, localeable} from 'amis-core';
|
||||||
import Html from './Html';
|
import Html from './Html';
|
||||||
import type {PlainObject} from 'amis-core';
|
import type {PlainObject} from 'amis-core';
|
||||||
|
import {createRoot} from 'react-dom/client';
|
||||||
export interface AlertProps extends ThemeProps, LocaleProps {
|
export interface AlertProps extends ThemeProps, LocaleProps {
|
||||||
container?: any;
|
container?: any;
|
||||||
confirmText?: string;
|
confirmText?: string;
|
||||||
@ -52,13 +53,21 @@ export interface AlertState {
|
|||||||
|
|
||||||
export class Alert extends React.Component<AlertProps, AlertState> {
|
export class Alert extends React.Component<AlertProps, AlertState> {
|
||||||
static instance: any = null;
|
static instance: any = null;
|
||||||
static getInstance() {
|
static async getInstance() {
|
||||||
if (!Alert.instance) {
|
if (!Alert.instance) {
|
||||||
console.warn('Alert 组件应该没有被渲染,所以隐性的渲染到 body 了');
|
console.warn('Alert 组件应该没有被渲染,所以隐性的渲染到 body 了');
|
||||||
const container = document.body;
|
const container = document.body;
|
||||||
const div = document.createElement('div');
|
const div = document.createElement('div');
|
||||||
container.appendChild(div);
|
container.appendChild(div);
|
||||||
render(<FinnalAlert />, div);
|
|
||||||
|
if (parseInt(version.split('.')[0], 10) >= 18) {
|
||||||
|
const root = createRoot(div);
|
||||||
|
await new Promise<void>(resolve =>
|
||||||
|
root.render(<FinnalAlert ref={() => resolve()} />)
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
render(<FinnalAlert />, div);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Alert.instance;
|
return Alert.instance;
|
||||||
@ -346,23 +355,35 @@ function renderForm(
|
|||||||
return renderSchemaFn?.(controls, value, callback, scopeRef, theme);
|
return renderSchemaFn?.(controls, value, callback, scopeRef, theme);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const alert: (content: string, title?: string) => void = (
|
export const alert: (content: string, title?: string) => Promise<void> = async (
|
||||||
content,
|
content,
|
||||||
title
|
title
|
||||||
) => Alert.getInstance().alert(content, title);
|
) => {
|
||||||
|
const instance = await Alert.getInstance();
|
||||||
|
return instance.alert(content, title);
|
||||||
|
};
|
||||||
export const confirm: (
|
export const confirm: (
|
||||||
content: string | React.ReactNode,
|
content: string | React.ReactNode,
|
||||||
title?: string,
|
title?: string,
|
||||||
optionsOrCofnrimText?: string | ConfirmOptions,
|
optionsOrCofnrimText?: string | ConfirmOptions,
|
||||||
cancelText?: string
|
cancelText?: string
|
||||||
) => Promise<any> = (content, title, optionsOrCofnrimText, cancelText) =>
|
) => Promise<any> = async (
|
||||||
Alert.getInstance().confirm(content, title, optionsOrCofnrimText, cancelText);
|
content,
|
||||||
|
title,
|
||||||
|
optionsOrCofnrimText,
|
||||||
|
cancelText
|
||||||
|
) => {
|
||||||
|
const instance = await Alert.getInstance();
|
||||||
|
return instance.confirm(content, title, optionsOrCofnrimText, cancelText);
|
||||||
|
};
|
||||||
export const prompt: (
|
export const prompt: (
|
||||||
controls: any,
|
controls: any,
|
||||||
defaultvalue?: any,
|
defaultvalue?: any,
|
||||||
title?: string,
|
title?: string,
|
||||||
confirmText?: string
|
confirmText?: string
|
||||||
) => Promise<any> = (controls, defaultvalue, title, confirmText) =>
|
) => Promise<any> = async (controls, defaultvalue, title, confirmText) => {
|
||||||
Alert.getInstance().prompt(controls, defaultvalue, title, confirmText);
|
const instance = await Alert.getInstance();
|
||||||
|
return instance.prompt(controls, defaultvalue, title, confirmText);
|
||||||
|
};
|
||||||
export const FinnalAlert = themeable(localeable(Alert));
|
export const FinnalAlert = themeable(localeable(Alert));
|
||||||
export default FinnalAlert;
|
export default FinnalAlert;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import {ClassNamesFn, themeable} from 'amis-core';
|
import {ClassNamesFn, themeable} from 'amis-core';
|
||||||
import React from 'react';
|
import React, {version} from 'react';
|
||||||
import {render} from 'react-dom';
|
import {render} from 'react-dom';
|
||||||
import {autobind, calculatePosition} from 'amis-core';
|
import {autobind, calculatePosition} from 'amis-core';
|
||||||
import Transition, {
|
import Transition, {
|
||||||
@ -7,6 +7,7 @@ import Transition, {
|
|||||||
ENTERING,
|
ENTERING,
|
||||||
EXITING
|
EXITING
|
||||||
} from 'react-transition-group/Transition';
|
} from 'react-transition-group/Transition';
|
||||||
|
import {createRoot} from 'react-dom/client';
|
||||||
const fadeStyles: {
|
const fadeStyles: {
|
||||||
[propName: string]: string;
|
[propName: string]: string;
|
||||||
} = {
|
} = {
|
||||||
@ -49,12 +50,20 @@ export class ContextMenu extends React.Component<
|
|||||||
ContextMenuState
|
ContextMenuState
|
||||||
> {
|
> {
|
||||||
static instance: any = null;
|
static instance: any = null;
|
||||||
static getInstance() {
|
static async getInstance() {
|
||||||
if (!ContextMenu.instance) {
|
if (!ContextMenu.instance) {
|
||||||
const container = document.body;
|
const container = document.body;
|
||||||
const div = document.createElement('div');
|
const div = document.createElement('div');
|
||||||
container.appendChild(div);
|
container.appendChild(div);
|
||||||
render(<ThemedContextMenu />, div);
|
|
||||||
|
if (parseInt(version.split('.')[0], 10) >= 18) {
|
||||||
|
const root = createRoot(div);
|
||||||
|
await new Promise<void>(resolve =>
|
||||||
|
root.render(<ThemedContextMenu ref={() => resolve()} />)
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
render(<ThemedContextMenu />, div);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ContextMenu.instance;
|
return ContextMenu.instance;
|
||||||
@ -309,5 +318,7 @@ export function openContextMenus(
|
|||||||
menus: Array<MenuItem | MenuDivider>,
|
menus: Array<MenuItem | MenuDivider>,
|
||||||
onClose?: () => void
|
onClose?: () => void
|
||||||
) {
|
) {
|
||||||
return ContextMenu.getInstance().openContextMenus(info, menus, onClose);
|
return ContextMenu.getInstance().then(instance =>
|
||||||
|
instance.openContextMenus(info, menus, onClose)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
@ -75,7 +75,7 @@ exports[`doAction:service reload 1`] = `
|
|||||||
placeholder=""
|
placeholder=""
|
||||||
size="10"
|
size="10"
|
||||||
type="text"
|
type="text"
|
||||||
value="Amis Renderer"
|
value="amis"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -321,7 +321,7 @@ exports[`doAction:service reload 2`] = `
|
|||||||
placeholder=""
|
placeholder=""
|
||||||
size="10"
|
size="10"
|
||||||
type="text"
|
type="text"
|
||||||
value="Amis Renderer"
|
value="amis"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -342,7 +342,7 @@ test('Renderers:Action tooltip', async () => {
|
|||||||
// });
|
// });
|
||||||
|
|
||||||
// 14. confirmText
|
// 14. confirmText
|
||||||
test('Renderers:Action with confirmText & actionType ajax', () => {
|
test('Renderers:Action with confirmText & actionType ajax', async () => {
|
||||||
const fetcher = jest.fn().mockImplementation(() =>
|
const fetcher = jest.fn().mockImplementation(() =>
|
||||||
Promise.resolve({
|
Promise.resolve({
|
||||||
data: {
|
data: {
|
||||||
@ -372,7 +372,7 @@ test('Renderers:Action with confirmText & actionType ajax', () => {
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
fireEvent.click(container.querySelector('.cxd-Button'));
|
fireEvent.click(container.querySelector('.cxd-Button'));
|
||||||
wait(500);
|
await wait(500);
|
||||||
expect(baseElement).toMatchSnapshot();
|
expect(baseElement).toMatchSnapshot();
|
||||||
|
|
||||||
expect(baseElement.querySelector('.cxd-Modal-content')!).toHaveTextContent(
|
expect(baseElement.querySelector('.cxd-Modal-content')!).toHaveTextContent(
|
||||||
@ -380,14 +380,16 @@ test('Renderers:Action with confirmText & actionType ajax', () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
fireEvent.click(getByText('取消'));
|
fireEvent.click(getByText('取消'));
|
||||||
wait(500);
|
await wait(500);
|
||||||
expect(fetcher).not.toBeCalled();
|
expect(fetcher).not.toBeCalled();
|
||||||
|
|
||||||
// fireEvent.click(container.querySelector('.cxd-Button'));
|
fireEvent.click(container.querySelector('.cxd-Button'));
|
||||||
// wait(500);
|
await wait(500);
|
||||||
// fireEvent.click(getByText('确认'));
|
fireEvent.click(getByText('确认'));
|
||||||
// fetcher 不生效
|
|
||||||
// expect(fetcher).toBeCalled();
|
await wait(200);
|
||||||
|
// fetcher 该被执行了
|
||||||
|
expect(fetcher).toBeCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
// 15.Action 作为容器组件
|
// 15.Action 作为容器组件
|
||||||
|
@ -136,13 +136,15 @@ test('Renderer: input-table with default value column', async () => {
|
|||||||
await wait(200);
|
await wait(200);
|
||||||
|
|
||||||
expect(onSubmitCallbackFn).toHaveBeenCalledTimes(1);
|
expect(onSubmitCallbackFn).toHaveBeenCalledTimes(1);
|
||||||
expect(onSubmitCallbackFn.mock.calls[0][0]).toEqual({
|
expect(onSubmitCallbackFn.mock.calls[0][0]).toEqual(
|
||||||
table: [
|
expect.objectContaining({
|
||||||
{a: 'a1', b: 'b1', c: 'a1'},
|
table: [
|
||||||
{a: 'a2', b: 'b2', c: 'a2'},
|
{a: 'a1', b: 'b1', c: 'a1'},
|
||||||
{a: 'a3', b: 'b3', c: 'a3'}
|
{a: 'a2', b: 'b2', c: 'a2'},
|
||||||
]
|
{a: 'a3', b: 'b3', c: 'a3'}
|
||||||
});
|
]
|
||||||
|
})
|
||||||
|
);
|
||||||
}, 10000);
|
}, 10000);
|
||||||
|
|
||||||
test('Renderer:input table add', async () => {
|
test('Renderer:input table add', async () => {
|
||||||
|
@ -517,3 +517,181 @@ test('Renderer:Nav with itemActions', async () => {
|
|||||||
expect(container).toMatchSnapshot();
|
expect(container).toMatchSnapshot();
|
||||||
expect(getByText('编辑')).toBeInTheDocument();
|
expect(getByText('编辑')).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 8.各种图标展示
|
||||||
|
test('Renderer:Nav with icons', async () => {
|
||||||
|
const {container} = render(
|
||||||
|
amisRender(
|
||||||
|
{
|
||||||
|
type: 'page',
|
||||||
|
body: {
|
||||||
|
type: 'nav',
|
||||||
|
stacked: true,
|
||||||
|
links: [
|
||||||
|
{
|
||||||
|
label: 'Nav 1',
|
||||||
|
to: '?cat=1',
|
||||||
|
value: '1',
|
||||||
|
icon: 'fa fa-user',
|
||||||
|
__id: 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Nav 2',
|
||||||
|
__id: 2,
|
||||||
|
unfolded: true,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
__id: 2.1,
|
||||||
|
label: 'Nav 2-1',
|
||||||
|
icon: [
|
||||||
|
{
|
||||||
|
icon: 'star',
|
||||||
|
position: 'before'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: 'search',
|
||||||
|
position: 'before'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: 'https://suda.cdn.bcebos.com/images%2F2021-01%2Fdiamond.svg',
|
||||||
|
position: 'after'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
label: 'Nav 2-1-1',
|
||||||
|
to: '?cat=2-1',
|
||||||
|
value: '2-1',
|
||||||
|
__id: 2.11
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{},
|
||||||
|
makeEnv({})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
expect(container).toMatchSnapshot();
|
||||||
|
expect(container.querySelectorAll('.fa-user').length).toBe(1);
|
||||||
|
expect(container.querySelectorAll('[icon=search]').length).toBe(1);
|
||||||
|
expect(container.querySelectorAll('img').length).toBe(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
// 9.Nav在Dialog里
|
||||||
|
test('Renderer:Nav with Dialog', async () => {
|
||||||
|
const {container, getByText} = render(
|
||||||
|
amisRender(
|
||||||
|
{
|
||||||
|
type: 'page',
|
||||||
|
body: {
|
||||||
|
type: 'button',
|
||||||
|
label: '点击弹框',
|
||||||
|
actionType: 'dialog',
|
||||||
|
dialog: {
|
||||||
|
title: '弹框',
|
||||||
|
body: [
|
||||||
|
{
|
||||||
|
type: 'nav',
|
||||||
|
stacked: true,
|
||||||
|
className: 'w-md',
|
||||||
|
draggable: true,
|
||||||
|
saveOrderApi: '/api/options/nav',
|
||||||
|
source: '/api/options/nav?parentId=${value}',
|
||||||
|
itemActions: [
|
||||||
|
{
|
||||||
|
type: 'icon',
|
||||||
|
icon: 'cloud',
|
||||||
|
visibleOn: "this.to === '?cat=1'"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'dropdown-button',
|
||||||
|
level: 'link',
|
||||||
|
icon: 'fa fa-ellipsis-h',
|
||||||
|
hideCaret: true,
|
||||||
|
buttons: [
|
||||||
|
{
|
||||||
|
type: 'button',
|
||||||
|
label: '编辑'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'button',
|
||||||
|
label: '删除'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
links: [
|
||||||
|
{
|
||||||
|
label: 'Nav 1',
|
||||||
|
to: '?cat=1',
|
||||||
|
value: '1',
|
||||||
|
icon: 'fa fa-user',
|
||||||
|
__id: 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Nav 2',
|
||||||
|
__id: 2,
|
||||||
|
unfolded: true,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
__id: 2.1,
|
||||||
|
label: 'Nav 2-1',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
label: 'Nav 2-1-1',
|
||||||
|
to: '?cat=2-1',
|
||||||
|
value: '2-1',
|
||||||
|
__id: 2.11
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Nav 2-2',
|
||||||
|
to: '?cat=2-2',
|
||||||
|
value: '2-2',
|
||||||
|
__id: 2.2
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: 'Nav 3',
|
||||||
|
to: '?cat=3',
|
||||||
|
value: '3',
|
||||||
|
defer: true,
|
||||||
|
__id: 3
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{},
|
||||||
|
makeEnv({
|
||||||
|
getModalContainer: () => container
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
expect(container).toMatchSnapshot();
|
||||||
|
|
||||||
|
fireEvent.click(getByText('点击弹框'));
|
||||||
|
await waitFor(() => {
|
||||||
|
expect(container.querySelector('[role="dialog"]')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
fireEvent.click(
|
||||||
|
container.querySelector(
|
||||||
|
'[role="dialog"] .cxd-Nav-Menu-item-extra .cxd-Button'
|
||||||
|
)!
|
||||||
|
);
|
||||||
|
|
||||||
|
await waitFor(() => {
|
||||||
|
expect(
|
||||||
|
container.querySelector('[role="dialog"] .cxd-PopOver')
|
||||||
|
).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
@ -208,6 +208,228 @@ exports[`Renderer:Nav 1`] = `
|
|||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`Renderer:Nav with Dialog 1`] = `
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
class="cxd-Page"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="cxd-Page-content"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="cxd-Page-main"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="cxd-Page-body"
|
||||||
|
role="page-body"
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
class="cxd-Button cxd-Button--default cxd-Button--size-default"
|
||||||
|
type="button"
|
||||||
|
>
|
||||||
|
<span>
|
||||||
|
点击弹框
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`Renderer:Nav with icons 1`] = `
|
||||||
|
<div>
|
||||||
|
<div
|
||||||
|
class="cxd-Page"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="cxd-Page-content"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="cxd-Page-main"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="cxd-Page-body"
|
||||||
|
role="page-body"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="cxd-Nav"
|
||||||
|
>
|
||||||
|
<ul
|
||||||
|
class="cxd-Nav-Menu cxd-Nav-Menu-root cxd-Nav-Menu-inline cxd-Nav-Menu-ltr cxd-Nav-Menu-light cxd-Nav-Menu-expand-before"
|
||||||
|
data-menu-list="true"
|
||||||
|
dir="ltr"
|
||||||
|
role="menu"
|
||||||
|
tabindex="0"
|
||||||
|
>
|
||||||
|
<ul
|
||||||
|
class="cxd-Nav-Menu-item-tooltip-wrap"
|
||||||
|
style="order: 0;"
|
||||||
|
>
|
||||||
|
<li
|
||||||
|
aria-disabled="false"
|
||||||
|
class="cxd-Nav-Menu-item"
|
||||||
|
data-menu-id="rc-menu-uuid-test-1"
|
||||||
|
role="menuitem"
|
||||||
|
style="padding-left: 16px;"
|
||||||
|
tabindex="-1"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="cxd-Nav-Menu-item-wrap"
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
class="cxd-Nav-Menu-item-link"
|
||||||
|
data-depth="1"
|
||||||
|
data-id="1"
|
||||||
|
title="Nav 1"
|
||||||
|
>
|
||||||
|
<i
|
||||||
|
class="cxd-Nav-Menu-item-icon"
|
||||||
|
>
|
||||||
|
<i
|
||||||
|
class="fa fa-user fa fa-user"
|
||||||
|
/>
|
||||||
|
</i>
|
||||||
|
<span
|
||||||
|
class="cxd-Nav-Menu-item-label"
|
||||||
|
title="Nav 1"
|
||||||
|
>
|
||||||
|
Nav 1
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<li
|
||||||
|
class="cxd-Nav-Menu-submenu cxd-Nav-Menu-submenu-inline cxd-Nav-Menu-submenu cxd-Nav-Menu-submenu-open"
|
||||||
|
role="none"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
aria-controls="rc-menu-uuid-test-2-popup"
|
||||||
|
aria-expanded="true"
|
||||||
|
aria-haspopup="true"
|
||||||
|
class="cxd-Nav-Menu-submenu-title"
|
||||||
|
data-menu-id="rc-menu-uuid-test-2"
|
||||||
|
role="menuitem"
|
||||||
|
style="padding-left: 16px;"
|
||||||
|
tabindex="-1"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="cxd-Nav-Menu-item-wrap"
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
class="cxd-Nav-Menu-item-link"
|
||||||
|
data-depth="1"
|
||||||
|
data-id="2"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="cxd-Nav-Menu-item-label cxd-Nav-Menu-item-label-subTitle"
|
||||||
|
title="Nav 2"
|
||||||
|
>
|
||||||
|
Nav 2
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<span
|
||||||
|
class="cxd-Nav-Menu-submenu-arrow"
|
||||||
|
>
|
||||||
|
<icon-mock
|
||||||
|
classname="icon icon-right-arrow-bold"
|
||||||
|
icon="right-arrow-bold"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<ul
|
||||||
|
class="cxd-Nav-Menu cxd-Nav-Menu-sub cxd-Nav-Menu-inline"
|
||||||
|
data-menu-list="true"
|
||||||
|
id="rc-menu-uuid-test-2-popup"
|
||||||
|
role="menu"
|
||||||
|
>
|
||||||
|
<li
|
||||||
|
class="cxd-Nav-Menu-submenu cxd-Nav-Menu-submenu-inline cxd-Nav-Menu-submenu"
|
||||||
|
role="none"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
aria-controls="rc-menu-uuid-test-3-popup"
|
||||||
|
aria-expanded="false"
|
||||||
|
aria-haspopup="true"
|
||||||
|
class="cxd-Nav-Menu-submenu-title"
|
||||||
|
data-menu-id="rc-menu-uuid-test-3"
|
||||||
|
role="menuitem"
|
||||||
|
style="padding-left: 32px;"
|
||||||
|
tabindex="-1"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="cxd-Nav-Menu-item-wrap"
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
class="cxd-Nav-Menu-item-link"
|
||||||
|
data-depth="2"
|
||||||
|
data-id="2.1"
|
||||||
|
>
|
||||||
|
<i
|
||||||
|
class="cxd-Nav-Menu-item-icon"
|
||||||
|
>
|
||||||
|
<icon-mock
|
||||||
|
classname="icon-star"
|
||||||
|
icon="star"
|
||||||
|
/>
|
||||||
|
<icon-mock
|
||||||
|
classname="icon-search"
|
||||||
|
icon="search"
|
||||||
|
/>
|
||||||
|
</i>
|
||||||
|
<span
|
||||||
|
class="cxd-Nav-Menu-item-label cxd-Nav-Menu-item-label-subTitle"
|
||||||
|
title="Nav 2-1"
|
||||||
|
>
|
||||||
|
Nav 2-1
|
||||||
|
</span>
|
||||||
|
<i
|
||||||
|
class="cxd-Nav-Menu-item-icon-after"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
class="cxd-Icon"
|
||||||
|
src="https://suda.cdn.bcebos.com/images%2F2021-01%2Fdiamond.svg"
|
||||||
|
/>
|
||||||
|
</i>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<span
|
||||||
|
class="cxd-Nav-Menu-submenu-arrow"
|
||||||
|
>
|
||||||
|
<icon-mock
|
||||||
|
classname="icon icon-right-arrow-bold"
|
||||||
|
icon="right-arrow-bold"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<div
|
||||||
|
aria-hidden="true"
|
||||||
|
style="display: none;"
|
||||||
|
>
|
||||||
|
<ul
|
||||||
|
class="cxd-Nav-Menu-item-tooltip-wrap"
|
||||||
|
style="order: 0;"
|
||||||
|
/>
|
||||||
|
<ul
|
||||||
|
class="cxd-Nav-Menu-item-tooltip-wrap"
|
||||||
|
style="order: 0;"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`Renderer:Nav with itemActions 1`] = `
|
exports[`Renderer:Nav with itemActions 1`] = `
|
||||||
<div>
|
<div>
|
||||||
<div
|
<div
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import {render as amisRender} from '../../src';
|
import {render as amisRender} from '../../src';
|
||||||
import {wait, makeEnv} from '../helper';
|
import {wait, makeEnv} from '../helper';
|
||||||
import {render, fireEvent, cleanup} from '@testing-library/react';
|
import {render, fireEvent, cleanup, waitFor} from '@testing-library/react';
|
||||||
import {buildApi, isApiOutdated, isValidApi} from 'amis-core';
|
import {buildApi, isApiOutdated, isValidApi} from 'amis-core';
|
||||||
|
|
||||||
test('api:buildApi', () => {
|
test('api:buildApi', () => {
|
||||||
@ -358,3 +358,74 @@ test('api:isvalidapi', () => {
|
|||||||
)
|
)
|
||||||
).toBeTruthy();
|
).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('api:requestAdaptor', async () => {
|
||||||
|
const notify = jest.fn();
|
||||||
|
const fetcher = jest.fn().mockImplementation(() =>
|
||||||
|
Promise.resolve({
|
||||||
|
data: {
|
||||||
|
status: 0,
|
||||||
|
msg: 'ok',
|
||||||
|
data: {
|
||||||
|
id: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
const requestAdaptor = jest.fn().mockImplementation(api => {
|
||||||
|
return Promise.resolve({
|
||||||
|
...api,
|
||||||
|
data: {
|
||||||
|
...api.data,
|
||||||
|
email: 'appended@test.com'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
const {container, getByText} = render(
|
||||||
|
amisRender(
|
||||||
|
{
|
||||||
|
type: 'page',
|
||||||
|
body: [
|
||||||
|
{
|
||||||
|
type: 'form',
|
||||||
|
id: 'form_submit',
|
||||||
|
submitText: '提交表单',
|
||||||
|
api: {
|
||||||
|
method: 'post',
|
||||||
|
url: '/api/mock2/form/saveForm',
|
||||||
|
requestAdaptor: requestAdaptor
|
||||||
|
},
|
||||||
|
body: [
|
||||||
|
{
|
||||||
|
type: 'input-text',
|
||||||
|
name: 'name',
|
||||||
|
label: '姓名:',
|
||||||
|
value: 'fex'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{},
|
||||||
|
makeEnv({
|
||||||
|
notify,
|
||||||
|
fetcher
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
await waitFor(() => {
|
||||||
|
expect(getByText('提交表单')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
fireEvent.click(getByText(/提交表单/));
|
||||||
|
await wait(300);
|
||||||
|
|
||||||
|
expect(requestAdaptor).toHaveBeenCalled();
|
||||||
|
expect(fetcher).toHaveBeenCalled();
|
||||||
|
expect(fetcher.mock.calls[0][0].data).toMatchObject({
|
||||||
|
name: 'fex',
|
||||||
|
email: 'appended@test.com'
|
||||||
|
});
|
||||||
|
});
|
||||||
|
@ -465,6 +465,10 @@ export default class Dialog extends React.Component<DialogProps> {
|
|||||||
syncLocation: false // 弹框中的 crud 一般不需要同步地址栏
|
syncLocation: false // 弹框中的 crud 一般不需要同步地址栏
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (this.props.size === 'full') {
|
||||||
|
subProps.affixOffsetTop = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (!(body as Schema).type) {
|
if (!(body as Schema).type) {
|
||||||
return render(`body${key ? `/${key}` : ''}`, body, subProps);
|
return render(`body${key ? `/${key}` : ''}`, body, subProps);
|
||||||
}
|
}
|
||||||
|
@ -465,7 +465,8 @@ export default class Drawer extends React.Component<DrawerProps> {
|
|||||||
onInit: this.handleFormInit,
|
onInit: this.handleFormInit,
|
||||||
onSaved: this.handleFormSaved,
|
onSaved: this.handleFormSaved,
|
||||||
onActionSensor: this.handleActionSensor,
|
onActionSensor: this.handleActionSensor,
|
||||||
syncLocation: false
|
syncLocation: false,
|
||||||
|
affixOffsetTop: 0
|
||||||
};
|
};
|
||||||
|
|
||||||
if (schema.type === 'form') {
|
if (schema.type === 'form') {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {findDOMNode} from 'react-dom';
|
import {findDOMNode} from 'react-dom';
|
||||||
import isEqual from 'lodash/isEqual';
|
import isEqual from 'lodash/isEqual';
|
||||||
|
import isString from 'lodash/isString';
|
||||||
import {
|
import {
|
||||||
Renderer,
|
Renderer,
|
||||||
RendererEnv,
|
RendererEnv,
|
||||||
@ -27,7 +28,7 @@ import {
|
|||||||
} from 'amis-core';
|
} from 'amis-core';
|
||||||
import {isEffectiveApi} from 'amis-core';
|
import {isEffectiveApi} from 'amis-core';
|
||||||
import {themeable, ThemeProps} from 'amis-core';
|
import {themeable, ThemeProps} from 'amis-core';
|
||||||
import {Icon, getIcon, SpinnerExtraProps} from 'amis-ui';
|
import {Icon, SpinnerExtraProps} from 'amis-ui';
|
||||||
import {BadgeObject} from 'amis-ui';
|
import {BadgeObject} from 'amis-ui';
|
||||||
import {RemoteOptionsProps, withRemoteConfig} from 'amis-ui';
|
import {RemoteOptionsProps, withRemoteConfig} from 'amis-ui';
|
||||||
import {Spinner, Menu} from 'amis-ui';
|
import {Spinner, Menu} from 'amis-ui';
|
||||||
@ -143,11 +144,6 @@ export interface NavOverflow {
|
|||||||
* 自定义样式
|
* 自定义样式
|
||||||
*/
|
*/
|
||||||
style?: React.CSSProperties;
|
style?: React.CSSProperties;
|
||||||
|
|
||||||
/**
|
|
||||||
* 菜单DOM挂载点
|
|
||||||
*/
|
|
||||||
popOverContainer?: any;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -319,6 +315,10 @@ export interface NavigationProps
|
|||||||
data: Object;
|
data: Object;
|
||||||
reload?: any;
|
reload?: any;
|
||||||
overflow?: NavOverflow;
|
overflow?: NavOverflow;
|
||||||
|
/**
|
||||||
|
* 菜单DOM挂载点
|
||||||
|
*/
|
||||||
|
popOverContainer?: () => HTMLElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IDropInfo {
|
export interface IDropInfo {
|
||||||
@ -550,6 +550,8 @@ export class Navigation extends React.Component<
|
|||||||
mode,
|
mode,
|
||||||
itemActions,
|
itemActions,
|
||||||
render,
|
render,
|
||||||
|
popOverContainer,
|
||||||
|
env,
|
||||||
classnames: cx,
|
classnames: cx,
|
||||||
data
|
data
|
||||||
} = this.props;
|
} = this.props;
|
||||||
@ -562,32 +564,28 @@ export class Navigation extends React.Component<
|
|||||||
}
|
}
|
||||||
|
|
||||||
return links.map((link: Link) => {
|
return links.map((link: Link) => {
|
||||||
let beforeIcon = null;
|
const beforeIcon: Array<any> = [];
|
||||||
let afterIcon = null;
|
const afterIcon: Array<any> = [];
|
||||||
if (Array.isArray(link.icon)) {
|
|
||||||
beforeIcon = link.icon
|
link.icon &&
|
||||||
.filter(item => item.position === 'before')
|
(Array.isArray(link.icon) ? link.icon : [link.icon]).forEach(
|
||||||
.map(item => {
|
(item, i) => {
|
||||||
if (React.isValidElement(item)) {
|
if (React.isValidElement(item)) {
|
||||||
return item;
|
beforeIcon.push(item);
|
||||||
|
} else if (isString(item)) {
|
||||||
|
beforeIcon.push(<Icon key={`icon-${i}`} cx={cx} icon={item} />);
|
||||||
|
} else if (item && isObject(item)) {
|
||||||
|
const icon = (
|
||||||
|
<Icon key={`icon-${i}`} cx={cx} icon={item['icon']} />
|
||||||
|
);
|
||||||
|
if (item['position'] === 'after') {
|
||||||
|
afterIcon.push(icon);
|
||||||
|
} else {
|
||||||
|
beforeIcon.push(icon);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return <Icon cx={cx} icon={link.icon} />;
|
}
|
||||||
});
|
);
|
||||||
afterIcon = link.icon
|
|
||||||
.filter(item => item.position === 'after')
|
|
||||||
.map(item => {
|
|
||||||
if (React.isValidElement(item)) {
|
|
||||||
return item;
|
|
||||||
}
|
|
||||||
return <Icon cx={cx} icon={item.icon} />;
|
|
||||||
});
|
|
||||||
} else if (link.icon) {
|
|
||||||
if (React.isValidElement(link.icon)) {
|
|
||||||
beforeIcon = link.icon;
|
|
||||||
} else {
|
|
||||||
beforeIcon = <Icon cx={cx} icon={link.icon} />;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const label =
|
const label =
|
||||||
typeof link.label === 'string'
|
typeof link.label === 'string'
|
||||||
@ -642,10 +640,10 @@ export class Navigation extends React.Component<
|
|||||||
return {
|
return {
|
||||||
link,
|
link,
|
||||||
label,
|
label,
|
||||||
labelExtra: afterIcon ? (
|
labelExtra: afterIcon.length ? (
|
||||||
<i className={cx('Nav-Menu-item-icon-after')}>{afterIcon}</i>
|
<i className={cx('Nav-Menu-item-icon-after')}>{afterIcon}</i>
|
||||||
) : null,
|
) : null,
|
||||||
icon: beforeIcon ? <i>{beforeIcon}</i> : null,
|
icon: beforeIcon.length ? <i>{beforeIcon}</i> : null,
|
||||||
children: children
|
children: children
|
||||||
? this.normalizeNavigations(children, depth + 1)
|
? this.normalizeNavigations(children, depth + 1)
|
||||||
: [],
|
: [],
|
||||||
@ -654,7 +652,11 @@ export class Navigation extends React.Component<
|
|||||||
extra: itemActions
|
extra: itemActions
|
||||||
? render('inline', itemActions, {
|
? render('inline', itemActions, {
|
||||||
data: createObject(data, link),
|
data: createObject(data, link),
|
||||||
popOverContainer: () => document.body,
|
popOverContainer: popOverContainer
|
||||||
|
? popOverContainer
|
||||||
|
: env.getModalContainer
|
||||||
|
? env.getModalContainer
|
||||||
|
: () => document.body,
|
||||||
// 点击操作之后 就关闭 因为close方法里执行了preventDefault
|
// 点击操作之后 就关闭 因为close方法里执行了preventDefault
|
||||||
closeOnClick: true
|
closeOnClick: true
|
||||||
})
|
})
|
||||||
@ -693,7 +695,9 @@ export class Navigation extends React.Component<
|
|||||||
popupClassName,
|
popupClassName,
|
||||||
disabled,
|
disabled,
|
||||||
id,
|
id,
|
||||||
render
|
render,
|
||||||
|
popOverContainer,
|
||||||
|
env
|
||||||
} = this.props;
|
} = this.props;
|
||||||
const {dropIndicator} = this.state;
|
const {dropIndicator} = this.state;
|
||||||
|
|
||||||
@ -796,6 +800,13 @@ export class Navigation extends React.Component<
|
|||||||
data={data}
|
data={data}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
onDragStart={this.handleDragStart}
|
onDragStart={this.handleDragStart}
|
||||||
|
popOverContainer={
|
||||||
|
popOverContainer
|
||||||
|
? popOverContainer
|
||||||
|
: env.getModalContainer
|
||||||
|
? env.getModalContainer
|
||||||
|
: () => document.body
|
||||||
|
}
|
||||||
></Menu>
|
></Menu>
|
||||||
) : null}
|
) : null}
|
||||||
<Spinner show={!!loading} overlay loadingConfig={loadingConfig} />
|
<Spinner show={!!loading} overlay loadingConfig={loadingConfig} />
|
||||||
|
@ -272,7 +272,7 @@ export class TableBody extends React.Component<TableBodyProps> {
|
|||||||
return (
|
return (
|
||||||
<Com
|
<Com
|
||||||
key={index}
|
key={index}
|
||||||
colSpan={item.colSpan}
|
colSpan={item.colSpan == 1 ? undefined : item.colSpan}
|
||||||
className={item.cellClassName}
|
className={item.cellClassName}
|
||||||
>
|
>
|
||||||
{render(`summary-row/${index}`, item, {
|
{render(`summary-row/${index}`, item, {
|
||||||
|
Loading…
Reference in New Issue
Block a user