mirror of
https://gitee.com/baidu/amis.git
synced 2024-11-29 18:48:45 +08:00
chore: 修复 ts 报错,并加入 pr 检测 (#6785)
* chore: 修复 ts 报错,并加入 pr 检测 * 把类型检测放在前面 * 调整一下顺序 * 类型调整 * 设置 build 编译顺序 * 设置 build 编译顺序
This commit is contained in:
parent
a9e36b3eaf
commit
d6461ced11
18
.github/workflows/pr-test.yml
vendored
18
.github/workflows/pr-test.yml
vendored
@ -22,12 +22,26 @@ jobs:
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: test
|
||||
- name: npm install
|
||||
env:
|
||||
NODE_OPTIONS: '--max-old-space-size=8192'
|
||||
run: |
|
||||
npm i --legacy-peer-deps
|
||||
cd packages/ooxml-viewer
|
||||
npm i --legacy-peer-deps
|
||||
cd ../../
|
||||
npm run build --workspaces
|
||||
npm run build --workspace amis-formula
|
||||
npm run build --workspace amis-core
|
||||
npm run build --workspace amis-ui
|
||||
npm run build --workspace amis
|
||||
npm run build --workspace amis-editor-core
|
||||
npm run build --workspace amis-editor
|
||||
- name: typescript check
|
||||
env:
|
||||
NODE_OPTIONS: '--max-old-space-size=8192'
|
||||
run: |
|
||||
npm run typecheck
|
||||
- name: test
|
||||
run: |
|
||||
npm test --workspaces
|
||||
sh deploy-gh-pages.sh
|
||||
|
@ -49,11 +49,11 @@ const LazyComponent = lazyData(
|
||||
},
|
||||
{
|
||||
title: 'X 轴',
|
||||
body: Axis('x')
|
||||
body: (Axis as any)('x')
|
||||
},
|
||||
{
|
||||
title: 'Y 轴',
|
||||
body: Axis('y')
|
||||
body: (Axis as any)('y')
|
||||
},
|
||||
{
|
||||
title: '极标',
|
||||
|
@ -33,8 +33,8 @@
|
||||
};
|
||||
|
||||
Object.keys(mapping).forEach(key => {
|
||||
amis.require.aliasMapping[key] = mapping[key];
|
||||
(window as any).amis.require.aliasMapping[key] = mapping[key];
|
||||
});
|
||||
|
||||
(window as any).amisRequire = amis.require;
|
||||
(window as any).amisRequire = (window as any).amis.require;
|
||||
})();
|
||||
|
@ -14,7 +14,9 @@ import 'core-js/es/map';
|
||||
import 'core-js/es/set';
|
||||
import 'core-js/es/symbol';
|
||||
|
||||
// @ts-ignore
|
||||
import './cloest';
|
||||
// @ts-ignore
|
||||
import './classList';
|
||||
|
||||
// ios 没有这个会报错
|
||||
|
@ -1,6 +1,7 @@
|
||||
// cfc 入口。
|
||||
exports.handler = (event, context, callback) => {
|
||||
try {
|
||||
// @ts-ignore
|
||||
const entry = require('./mock/index');
|
||||
entry(mockRequest(event, context), mockResponse(event, context, callback));
|
||||
} catch (e) {
|
||||
|
@ -2,6 +2,7 @@
|
||||
* @file 用于模拟 cfc 接口
|
||||
*/
|
||||
|
||||
// @ts-ignore
|
||||
const cfcHandler = require('./cfc/index').handler;
|
||||
|
||||
module.exports = function (req, res) {
|
||||
|
@ -24,7 +24,8 @@
|
||||
"release": "npm run build --workspaces && lerna publish from-package --registry=https://registry.npmjs.org --ignore-scripts",
|
||||
"revision": "ts-node ./scripts/generate-revision.ts",
|
||||
"publish-to-internal": "sh ./publish-to-internal.sh",
|
||||
"stylelint": "npx stylelint 'packages/**/*.scss'"
|
||||
"stylelint": "npx stylelint 'packages/**/*.scss'",
|
||||
"typecheck": "tsc --noEmit"
|
||||
},
|
||||
"husky": {
|
||||
"hooks": {
|
||||
|
@ -181,9 +181,12 @@ interface OverlayProps {
|
||||
shouldUpdatePosition?: boolean;
|
||||
rootClose?: boolean;
|
||||
onHide?(props: any, ...args: any[]): any;
|
||||
container?: HTMLElement | (() => HTMLElement | null | undefined);
|
||||
container?:
|
||||
| HTMLElement
|
||||
| React.ReactNode
|
||||
| (() => HTMLElement | React.ReactNode | null | undefined);
|
||||
containerSelector?: string;
|
||||
target?: React.ReactNode | Function;
|
||||
target?: React.ReactNode | HTMLElement | Function;
|
||||
watchTargetSizeChange?: boolean;
|
||||
offset?: [number, number];
|
||||
onEnter?(node: HTMLElement): any;
|
||||
|
@ -625,6 +625,13 @@ export interface BaseSchemaWithoutType {
|
||||
*/
|
||||
staticInputClassName?: SchemaClassName;
|
||||
staticSchema?: any;
|
||||
|
||||
/**
|
||||
* 组件样式
|
||||
*/
|
||||
style?: {
|
||||
[propName: string]: any;
|
||||
};
|
||||
}
|
||||
|
||||
export type OperatorType =
|
||||
|
@ -12,8 +12,8 @@ import {
|
||||
} from './DSBuilder';
|
||||
import cloneDeep from 'lodash/cloneDeep';
|
||||
import {getEnv} from 'mobx-state-tree';
|
||||
import type {ButtonSchema} from 'amis/lib/renderers/Action';
|
||||
import type {FormSchema, SchemaCollection, SchemaObject} from 'amis/lib/Schema';
|
||||
import type {ButtonSchema} from 'amis';
|
||||
import type {FormSchema, SchemaCollection, SchemaObject} from 'amis';
|
||||
|
||||
import type {DSSourceSettingFormConfig} from './DSBuilder';
|
||||
import {getSchemaTpl, tipedLabel} from '../tpl';
|
||||
|
@ -2,9 +2,9 @@
|
||||
* 数据源构造器,可用于对接当前amis中的扩展数据源
|
||||
*/
|
||||
|
||||
import type {ButtonSchema} from 'amis/lib/renderers/Action';
|
||||
import type {CRUD2Schema} from 'amis/lib/renderers/CRUD2';
|
||||
import type {FormSchema, SchemaCollection, SchemaObject} from 'amis/lib/Schema';
|
||||
import type {ButtonSchema} from 'amis';
|
||||
import type {CRUD2Schema} from 'amis';
|
||||
import type {FormSchema, SchemaCollection, SchemaObject} from 'amis';
|
||||
import {EditorNodeType} from '../store/node';
|
||||
|
||||
/**
|
||||
|
@ -3,7 +3,7 @@ import cx from 'classnames';
|
||||
import Preview from './Preview';
|
||||
import {autobind} from '../util';
|
||||
import {MainStore, EditorStoreType} from '../store/editor';
|
||||
import type {SchemaObject} from 'amis/lib/Schema';
|
||||
import type {SchemaObject} from 'amis';
|
||||
import {EditorManager, EditorManagerConfig, PluginClass} from '../manager';
|
||||
import {reaction} from 'mobx';
|
||||
import {RenderOptions, toast} from 'amis';
|
||||
|
@ -66,7 +66,7 @@ import findIndex from 'lodash/findIndex';
|
||||
import {EditorDNDManager} from './dnd';
|
||||
import {VariableManager} from './variable';
|
||||
import {IScopedContext} from 'amis';
|
||||
import type {SchemaObject, SchemaCollection} from 'amis/lib/Schema';
|
||||
import type {SchemaObject, SchemaCollection} from 'amis';
|
||||
import type {RendererConfig} from 'amis-core';
|
||||
import isPlainObject from 'lodash/isPlainObject';
|
||||
import {omit} from 'lodash';
|
||||
@ -132,7 +132,9 @@ export function registerEditorPlugin(klass: PluginClass) {
|
||||
*/
|
||||
export function getEditorPlugins(options: any = {}) {
|
||||
const {scene = 'global'} = options;
|
||||
return builtInPlugins.filter(item => item.scene?.includes(scene));
|
||||
return builtInPlugins.filter(item =>
|
||||
(Array.isArray(item) ? item[0] : item).scene?.includes(scene)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -327,9 +329,18 @@ export class EditorManager {
|
||||
);
|
||||
}
|
||||
|
||||
normalizeScene(plugins?: Array<PluginClass>) {
|
||||
normalizeScene(
|
||||
plugins?: Array<
|
||||
| PluginClass
|
||||
| [PluginClass, Record<string, any> | (() => Record<string, any>)]
|
||||
>
|
||||
) {
|
||||
return (
|
||||
plugins?.map((klass: PluginClass) => {
|
||||
plugins?.map(klass => {
|
||||
if (Array.isArray(klass)) {
|
||||
klass = klass[0];
|
||||
}
|
||||
|
||||
// 处理插件身上的场景信息
|
||||
const scene = Array.from(
|
||||
new Set(['global'].concat(klass.scene || 'global'))
|
||||
|
@ -1,4 +1,4 @@
|
||||
import type {SchemaObject} from 'amis/lib/Schema';
|
||||
import type {SchemaObject} from 'amis';
|
||||
|
||||
/**
|
||||
* @file amis schema 配置模板,主要很多地方都要全部配置的化,
|
||||
|
@ -8,7 +8,7 @@ import DeepDiff, {Diff} from 'deep-diff';
|
||||
import isPlainObject from 'lodash/isPlainObject';
|
||||
import isNumber from 'lodash/isNumber';
|
||||
import type {Schema} from 'amis';
|
||||
import type {SchemaObject} from 'amis/lib/Schema';
|
||||
import type {SchemaObject} from 'amis';
|
||||
import {assign, cloneDeep} from 'lodash';
|
||||
import {getGlobalData} from 'amis-theme-editor-helper';
|
||||
|
||||
|
@ -5,11 +5,7 @@
|
||||
import React from 'react';
|
||||
import isEqual from 'lodash/isEqual';
|
||||
import {toast} from 'amis';
|
||||
import {
|
||||
TableViewSchema,
|
||||
TdObject,
|
||||
TrObject
|
||||
} from 'amis/lib/renderers/TableView';
|
||||
import {TableViewSchema, TrObject} from 'amis';
|
||||
import {EditorManager} from 'amis-editor-core';
|
||||
import {autobind, JSONGetById, EditorStoreType} from 'amis-editor-core';
|
||||
|
||||
|
@ -2,7 +2,7 @@ import React from 'react';
|
||||
import {registerEditorPlugin} from 'amis-editor-core';
|
||||
import {BaseEventContext, BasePlugin} from 'amis-editor-core';
|
||||
import {getSchemaTpl} from 'amis-editor-core';
|
||||
import type {SchemaObject} from 'amis/lib/Schema';
|
||||
import type {SchemaObject} from 'amis';
|
||||
|
||||
export class AlertPlugin extends BasePlugin {
|
||||
static scene = ['layout'];
|
||||
|
@ -11,7 +11,7 @@ import {defaultValue, getSchemaTpl} from 'amis-editor-core';
|
||||
import {BUTTON_DEFAULT_ACTION} from '../component/BaseControl';
|
||||
import {getEventControlConfig} from '../renderer/event-control/helper';
|
||||
import {RendererPluginAction, RendererPluginEvent} from 'amis-editor-core';
|
||||
import type {SchemaObject} from 'amis/lib/Schema';
|
||||
import type {SchemaObject} from 'amis';
|
||||
import {getOldActionSchema} from '../renderer/event-control/helper';
|
||||
|
||||
export class ButtonPlugin extends BasePlugin {
|
||||
|
@ -24,8 +24,8 @@ import {
|
||||
import {defaultValue, getSchemaTpl} from 'amis-editor-core';
|
||||
import {isObject, JSONPipeIn} from 'amis-editor-core';
|
||||
import {setVariable} from 'amis-core';
|
||||
import {ActionSchema} from 'amis/lib/renderers/Action';
|
||||
import {CRUDCommonSchema} from 'amis/lib/renderers/CRUD';
|
||||
import type {ActionSchema} from 'amis';
|
||||
import type {CRUDCommonSchema} from 'amis';
|
||||
import {getEnv} from 'mobx-state-tree';
|
||||
import {EditorNodeType, RendererPluginAction} from 'amis-editor-core';
|
||||
import {normalizeApi} from 'amis-core';
|
||||
|
@ -24,10 +24,10 @@ import {
|
||||
RendererPluginEvent
|
||||
} from 'amis-editor-core';
|
||||
import {flattenDeep, fromPairs, isObject, remove} from 'lodash';
|
||||
import type {ButtonSchema} from 'amis/lib/renderers/Action';
|
||||
import type {FormSchema, SchemaObject} from 'amis/lib/Schema';
|
||||
import type {ButtonSchema} from 'amis';
|
||||
import type {FormSchema, SchemaObject} from 'amis';
|
||||
import {findTree} from 'amis';
|
||||
import type {CRUD2Schema} from 'amis/lib/renderers/CRUD2';
|
||||
import type {CRUD2Schema} from 'amis';
|
||||
import {FeatureOption} from '../renderer/FeatureControl';
|
||||
import {getArgsWrapper} from '../renderer/event-control/helper';
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import {availableLanguages} from 'amis/lib/renderers/Form/Editor';
|
||||
import {EditorAvailableLanguages as availableLanguages} from 'amis';
|
||||
import {defaultValue, getSchemaTpl, undefinedPipeOut} from 'amis-editor-core';
|
||||
import {registerEditorPlugin} from 'amis-editor-core';
|
||||
import {BasePlugin} from 'amis-editor-core';
|
||||
|
@ -1,4 +1,4 @@
|
||||
import {availableLanguages} from 'amis/lib/renderers/Form/Editor';
|
||||
import {EditorAvailableLanguages as availableLanguages} from 'amis';
|
||||
import {
|
||||
defaultValue,
|
||||
getSchemaTpl,
|
||||
|
@ -1,5 +1,5 @@
|
||||
import {Button} from 'amis';
|
||||
import type {SchemaCollection} from 'amis/lib/Schema';
|
||||
import type {SchemaCollection} from 'amis';
|
||||
import React from 'react';
|
||||
import {
|
||||
BaseEventContext,
|
||||
|
@ -1,16 +1,7 @@
|
||||
import {relativeValueRe} from 'amis';
|
||||
import {RendererPluginAction, RendererPluginEvent} from 'amis-editor-core';
|
||||
import {availableLanguages} from 'amis/lib/renderers/Form/Editor';
|
||||
import {defaultValue, getSchemaTpl, valuePipeOut} from 'amis-editor-core';
|
||||
import {getSchemaTpl} from 'amis-editor-core';
|
||||
import {registerEditorPlugin} from 'amis-editor-core';
|
||||
import {
|
||||
BasePlugin,
|
||||
BasicSubRenderInfo,
|
||||
RendererEventContext,
|
||||
SubRendererInfo,
|
||||
BaseEventContext,
|
||||
tipedLabel
|
||||
} from 'amis-editor-core';
|
||||
import {BasePlugin, BaseEventContext, tipedLabel} from 'amis-editor-core';
|
||||
import {ValidatorTag} from '../../validator';
|
||||
import {getEventControlConfig} from '../../renderer/event-control/helper';
|
||||
|
||||
|
@ -10,7 +10,7 @@ import {
|
||||
} from 'amis-editor-core';
|
||||
import {defaultValue, getSchemaTpl} from 'amis-editor-core';
|
||||
import {diff} from 'amis-editor-core';
|
||||
import type {SchemaCollection} from 'amis/lib/Schema';
|
||||
import type {SchemaCollection} from 'amis';
|
||||
|
||||
export class ActionPlugin extends BasePlugin {
|
||||
panelTitle = '按钮';
|
||||
|
@ -8,7 +8,7 @@ import {
|
||||
} from 'amis-editor-core';
|
||||
import {getEventControlConfig} from '../renderer/event-control/helper';
|
||||
import {RendererPluginAction, RendererPluginEvent} from 'amis-editor-core';
|
||||
import type {SchemaObject} from 'amis/lib/Schema';
|
||||
import type {SchemaObject} from 'amis';
|
||||
import {tipedLabel} from 'amis-editor-core';
|
||||
import {jsonToJsonSchema, EditorNodeType} from 'amis-editor-core';
|
||||
|
||||
|
@ -8,7 +8,7 @@ import {
|
||||
import {getSchemaTpl} from 'amis-editor-core';
|
||||
import {getEventControlConfig} from '../renderer/event-control/helper';
|
||||
|
||||
import type {SchemaObject} from 'amis/lib/Schema';
|
||||
import type {Schema} from 'amis-core';
|
||||
|
||||
export class SearchBoxPlugin extends BasePlugin {
|
||||
// 关联渲染器名字
|
||||
@ -25,7 +25,7 @@ export class SearchBoxPlugin extends BasePlugin {
|
||||
pluginIcon = 'search-box-plugin';
|
||||
tags = ['表单项'];
|
||||
|
||||
scaffold: SchemaObject = {
|
||||
scaffold: Schema = {
|
||||
type: 'search-box',
|
||||
body: {
|
||||
type: 'tpl',
|
||||
|
@ -22,7 +22,7 @@ import {
|
||||
import {defaultValue, getSchemaTpl, tipedLabel} from 'amis-editor-core';
|
||||
import {mockValue} from 'amis-editor-core';
|
||||
import {EditorNodeType} from 'amis-editor-core';
|
||||
import type {SchemaObject} from 'amis/lib/Schema';
|
||||
import type {SchemaObject} from 'amis';
|
||||
import {
|
||||
getEventControlConfig,
|
||||
getArgsWrapper
|
||||
|
@ -25,7 +25,7 @@ import {
|
||||
getEventControlConfig,
|
||||
getArgsWrapper
|
||||
} from '../renderer/event-control/helper';
|
||||
import type {SchemaObject} from 'amis/lib/Schema';
|
||||
import type {SchemaObject} from 'amis';
|
||||
|
||||
export class Table2Plugin extends BasePlugin {
|
||||
// 关联渲染器名字
|
||||
|
@ -16,8 +16,8 @@ import {
|
||||
} from 'amis-editor-core';
|
||||
import type {DSField} from 'amis-editor-core';
|
||||
import {fromPairs} from 'lodash';
|
||||
import type {TabsSchema} from 'amis/lib/renderers/Tabs';
|
||||
import type {SchemaObject} from 'amis/lib/Schema';
|
||||
import type {TabsSchema} from 'amis';
|
||||
import type {SchemaObject} from 'amis';
|
||||
import {remarkTpl} from '../component/BaseControl';
|
||||
|
||||
export class TableCell2Plugin extends BasePlugin {
|
||||
|
@ -16,7 +16,7 @@ import {
|
||||
} from 'amis-editor-core';
|
||||
import {defaultValue, getSchemaTpl} from 'amis-editor-core';
|
||||
import {VRenderer} from 'amis-editor-core';
|
||||
import type {TableViewSchema} from 'amis/lib/renderers/TableView';
|
||||
import type {TableViewSchema} from 'amis';
|
||||
import {JSONGetById} from 'amis-editor-core';
|
||||
import {TableViewEditor} from '../component/TableViewEditor';
|
||||
|
||||
|
@ -53,7 +53,6 @@ export default class APIAdaptorControl extends React.Component<
|
||||
APIAdaptorControlProps,
|
||||
APIAdaptorControlState
|
||||
> {
|
||||
|
||||
static defaultProps: Pick<APIAdaptorControlProps, 'params'> = {
|
||||
params: []
|
||||
};
|
||||
@ -89,13 +88,12 @@ export default class APIAdaptorControl extends React.Component<
|
||||
...(typeof content === 'string'
|
||||
? {content}
|
||||
: {
|
||||
content: ' ', // amis缺陷,必须有这个字段,否则显示不出来
|
||||
children: () => content
|
||||
}
|
||||
),
|
||||
...this.props.tooltipProps || {},
|
||||
...othersProps || {}
|
||||
}
|
||||
content: ' ', // amis缺陷,必须有这个字段,否则显示不出来
|
||||
children: () => content
|
||||
}),
|
||||
...(this.props.tooltipProps || {}),
|
||||
...(othersProps || {})
|
||||
};
|
||||
}
|
||||
|
||||
renderEditor() {
|
||||
@ -114,8 +112,8 @@ export default class APIAdaptorControl extends React.Component<
|
||||
mergeParams
|
||||
} = this.props;
|
||||
|
||||
const lastParams = typeof mergeParams === 'function'
|
||||
? mergeParams(params) : params;
|
||||
const lastParams =
|
||||
typeof mergeParams === 'function' ? mergeParams(params) : params;
|
||||
|
||||
return render('api-adaptor-control-editor', [
|
||||
{
|
||||
@ -124,20 +122,22 @@ export default class APIAdaptorControl extends React.Component<
|
||||
body: [
|
||||
'<span class="mtk6">function </span>',
|
||||
'<span class="mtk1 bracket-highlighting-0">(</span>',
|
||||
...lastParams.map(({label, tip}, index) => {
|
||||
return [
|
||||
{
|
||||
type: 'button',
|
||||
level: 'link',
|
||||
label,
|
||||
className: 'ae-AdaptorControl-func-arg',
|
||||
...tip ? {tooltip: this.genTooltipProps(tip)} : {}
|
||||
},
|
||||
...(index === lastParams.length - 1
|
||||
? [] : ['<span class="mtk1">, </span>']
|
||||
)
|
||||
]
|
||||
}).flat(),
|
||||
...lastParams
|
||||
.map(({label, tip}, index) => {
|
||||
return [
|
||||
{
|
||||
type: 'button',
|
||||
level: 'link',
|
||||
label,
|
||||
className: 'ae-AdaptorControl-func-arg',
|
||||
...(tip ? {tooltip: this.genTooltipProps(tip)} : {})
|
||||
},
|
||||
...(index === lastParams.length - 1
|
||||
? []
|
||||
: ['<span class="mtk1">, </span>'])
|
||||
];
|
||||
})
|
||||
.flat(),
|
||||
'<span class="mtk1 bracket-highlighting-0">) {</span>'
|
||||
]
|
||||
},
|
||||
@ -190,20 +190,20 @@ export default class APIAdaptorControl extends React.Component<
|
||||
});
|
||||
}
|
||||
},
|
||||
...switchTip ? [
|
||||
<TooltipWrapper
|
||||
key="TooltipWrapper"
|
||||
tooltip={this.genTooltipProps(switchTip, {
|
||||
placement: 'right'
|
||||
})}
|
||||
>
|
||||
<Icon
|
||||
icon="editor-help"
|
||||
className="icon"
|
||||
color="#84868c"
|
||||
/>
|
||||
</TooltipWrapper>
|
||||
] : []
|
||||
...(switchTip
|
||||
? [
|
||||
<TooltipWrapper
|
||||
key="TooltipWrapper"
|
||||
tooltip={
|
||||
this.genTooltipProps(switchTip, {
|
||||
placement: 'right'
|
||||
}) as any
|
||||
}
|
||||
>
|
||||
<Icon icon="editor-help" className="icon" color="#84868c" />
|
||||
</TooltipWrapper>
|
||||
]
|
||||
: [])
|
||||
]
|
||||
});
|
||||
}
|
||||
@ -216,7 +216,7 @@ export default class APIAdaptorControl extends React.Component<
|
||||
{this.renderSwitch()}
|
||||
{this.renderEditor()}
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
@FormItem({
|
||||
@ -232,11 +232,14 @@ export class APIAdaptorControlRenderer extends APIAdaptorControl {}
|
||||
*/
|
||||
const genCodeSchema = (code: string, size?: string[]) => ({
|
||||
type: 'container',
|
||||
...!size ? {}
|
||||
: {style: {
|
||||
width: size[0],
|
||||
height: size[1]
|
||||
}},
|
||||
...(!size
|
||||
? {}
|
||||
: {
|
||||
style: {
|
||||
width: size[0],
|
||||
height: size[1]
|
||||
}
|
||||
}),
|
||||
body: {
|
||||
type: 'code',
|
||||
language: 'typescript',
|
||||
@ -246,8 +249,7 @@ const genCodeSchema = (code: string, size?: string[]) => ({
|
||||
});
|
||||
|
||||
// 请求适配器 示例代码
|
||||
export const requestAdaptorDefaultCode =
|
||||
`api.data.count = api.data.count + 1;
|
||||
export const requestAdaptorDefaultCode = `api.data.count = api.data.count + 1;
|
||||
return api;`;
|
||||
|
||||
// 适配器 适配器 api 参数说明
|
||||
@ -259,9 +261,9 @@ export const adaptorApiStruct = `{
|
||||
...
|
||||
}`;
|
||||
|
||||
export const adaptorApiStructTooltip =
|
||||
render(genCodeSchema(adaptorApiStruct, ['350px', '128px']))
|
||||
;
|
||||
export const adaptorApiStructTooltip = render(
|
||||
genCodeSchema(adaptorApiStruct, ['350px', '128px'])
|
||||
);
|
||||
|
||||
// 适配器 response 参数说明
|
||||
export const adaptorResponseStruct = `{
|
||||
@ -273,13 +275,12 @@ export const adaptorResponseStruct = `{
|
||||
...
|
||||
}`;
|
||||
|
||||
export const adaptorResponseStructTooltip =
|
||||
render(genCodeSchema(adaptorResponseStruct, ['345px', '144px']))
|
||||
;
|
||||
export const adaptorResponseStructTooltip = render(
|
||||
genCodeSchema(adaptorResponseStruct, ['345px', '144px'])
|
||||
);
|
||||
|
||||
// 接收适配器 示例代码
|
||||
export const adaptorDefaultCode =
|
||||
`// API响应或自定义处理后需要符合以下格式
|
||||
export const adaptorDefaultCode = `// API响应或自定义处理后需要符合以下格式
|
||||
return {
|
||||
status: 0, // 0 表示请求成功,否则按错误处理
|
||||
msg: '请求成功',
|
||||
@ -291,8 +292,7 @@ return {
|
||||
}
|
||||
}`;
|
||||
|
||||
export const validateApiAdaptorDefaultCode =
|
||||
`// 校验成功
|
||||
export const validateApiAdaptorDefaultCode = `// 校验成功
|
||||
return {
|
||||
status: 0
|
||||
};
|
||||
|
@ -17,10 +17,10 @@ import {
|
||||
getSchemaTpl
|
||||
} from 'amis-editor-core';
|
||||
|
||||
import type {SchemaObject, SchemaCollection, SchemaApi} from 'amis/lib/Schema';
|
||||
import type {SchemaObject, SchemaCollection, SchemaApi} from 'amis';
|
||||
import type {Api} from 'amis';
|
||||
import type {FormControlProps} from 'amis-core';
|
||||
import type {ActionSchema} from 'amis/lib/renderers/Action';
|
||||
import type {ActionSchema} from 'amis';
|
||||
|
||||
export type ApiObject = Api & {
|
||||
messages?: Record<
|
||||
@ -913,9 +913,7 @@ export default class APIControl extends React.Component<
|
||||
]
|
||||
},
|
||||
getSchemaTpl(
|
||||
name === 'validateApi'
|
||||
? 'validateApiAdaptor'
|
||||
: 'apiAdaptor'
|
||||
name === 'validateApi' ? 'validateApiAdaptor' : 'apiAdaptor'
|
||||
)
|
||||
]
|
||||
},
|
||||
|
@ -8,13 +8,19 @@ import {PickerContainer} from 'amis-ui';
|
||||
import {getEnv} from 'mobx-state-tree';
|
||||
import {normalizeApi, isEffectiveApi, isApiOutdated} from 'amis-core';
|
||||
|
||||
import {autobind, isObject, anyChanged, createObject, getSchemaTpl} from 'amis-editor-core';
|
||||
import {
|
||||
autobind,
|
||||
isObject,
|
||||
anyChanged,
|
||||
createObject,
|
||||
getSchemaTpl
|
||||
} from 'amis-editor-core';
|
||||
import {tipedLabel} from 'amis-editor-core';
|
||||
|
||||
import type {SchemaObject, SchemaCollection, SchemaApi} from 'amis/lib/Schema';
|
||||
import type {SchemaObject, SchemaCollection, SchemaApi} from 'amis';
|
||||
import type {Api} from 'amis';
|
||||
import type {FormControlProps} from 'amis-core';
|
||||
import type {ActionSchema} from 'amis/lib/renderers/Action';
|
||||
import type {ActionSchema} from 'amis';
|
||||
|
||||
export interface APIControlProps extends FormControlProps {
|
||||
name?: string;
|
||||
@ -754,7 +760,7 @@ export default class APIControl extends React.Component<
|
||||
]
|
||||
},
|
||||
getSchemaTpl('apiRequestAdaptor'),
|
||||
getSchemaTpl('apiAdaptor'),
|
||||
getSchemaTpl('apiAdaptor')
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -18,7 +18,7 @@ import {
|
||||
import {defaultValue, tipedLabel} from 'amis-editor-core';
|
||||
|
||||
import type {FormControlProps} from 'amis-core';
|
||||
import type {SchemaExpression} from 'amis/lib/Schema';
|
||||
import type {SchemaExpression} from 'amis';
|
||||
|
||||
export interface BadgeControlProps extends FormControlProps {
|
||||
/**
|
||||
|
@ -21,7 +21,7 @@ import React from 'react';
|
||||
import {EditorManager, EditorNodeType, autobind} from 'amis-editor-core';
|
||||
import type {DSField, DSFieldGroup} from 'amis-editor-core';
|
||||
import {matchSorter} from 'match-sorter';
|
||||
import type {SchemaCollection} from 'amis/lib/Schema';
|
||||
import type {SchemaCollection} from 'amis';
|
||||
import {default as cx} from 'classnames';
|
||||
|
||||
export interface DataBindingProps extends FormControlProps {
|
||||
|
@ -7,7 +7,7 @@ import cx from 'classnames';
|
||||
import {FormItem} from 'amis';
|
||||
import {autobind, getSchemaTpl, tipedLabel} from 'amis-editor-core';
|
||||
import {FormControlProps, isObject} from 'amis-core';
|
||||
import type {SchemaApi} from 'amis/lib/Schema';
|
||||
import type {SchemaApi} from 'amis';
|
||||
import debounce from 'lodash/debounce';
|
||||
|
||||
enum MapType {
|
||||
|
@ -16,7 +16,7 @@ import {
|
||||
import {defaultValue, tipedLabel, getSchemaTpl} from 'amis-editor-core';
|
||||
|
||||
import type {FormControlProps} from 'amis-core';
|
||||
import type {SchemaExpression} from 'amis/lib/Schema';
|
||||
import type {SchemaExpression} from 'amis';
|
||||
|
||||
export interface BadgeControlProps extends FormControlProps {
|
||||
/**
|
||||
@ -325,7 +325,7 @@ export default class BadgeControl extends React.Component<
|
||||
name: 'checked',
|
||||
mode: 'horizontal',
|
||||
value: checked,
|
||||
onChange: checked => this.handleSwitchChange(checked)
|
||||
onChange: (checked: boolean) => this.handleSwitchChange(checked)
|
||||
})
|
||||
)}
|
||||
{checked ? this.renderBody() : null}
|
||||
|
@ -22,7 +22,7 @@ export default class NavDefaultActiveControl extends React.Component<
|
||||
super(props);
|
||||
}
|
||||
|
||||
deleteActive(data) {
|
||||
deleteActive(data: any) {
|
||||
for (let item of data) {
|
||||
if (item.active) {
|
||||
delete item.active;
|
||||
@ -33,7 +33,7 @@ export default class NavDefaultActiveControl extends React.Component<
|
||||
}
|
||||
}
|
||||
|
||||
findActiveKey(data, index?: string) {
|
||||
findActiveKey(data: any, index?: string) {
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
const item = data[i];
|
||||
if (item.active) {
|
||||
|
@ -12,7 +12,7 @@ import {FormItem, Button, InputBox, Switch, Radios} from 'amis';
|
||||
import {autobind} from 'amis-editor-core';
|
||||
import {getSchemaTpl} from 'amis-editor-core';
|
||||
import type {FormControlProps} from 'amis-core';
|
||||
import type {SchemaApi} from 'amis/lib/Schema';
|
||||
import type {SchemaApi} from 'amis';
|
||||
|
||||
export type valueType = 'text' | 'boolean' | 'number';
|
||||
|
||||
@ -402,7 +402,7 @@ export default class NavSourceControl extends React.Component<
|
||||
</div>
|
||||
{children && children.length ? (
|
||||
<>
|
||||
{children.map((item, id: number) => {
|
||||
{children.map((item: any, id: number) => {
|
||||
return this.renderOption({...item, index: `${index}_${id}`});
|
||||
})}
|
||||
<Button onClick={() => this.handleAddChildren(index, true)}>
|
||||
|
@ -25,9 +25,8 @@ import {tipedLabel} from 'amis-editor-core';
|
||||
|
||||
import type {Option} from 'amis';
|
||||
import {createObject, FormControlProps} from 'amis-core';
|
||||
import type {TextControlSchema} from 'amis/lib/renderers/Form/inputText';
|
||||
import type {OptionValue} from 'amis-core';
|
||||
import type {SchemaApi} from 'amis/lib/Schema';
|
||||
import type {SchemaApi} from 'amis';
|
||||
|
||||
export type valueType = 'text' | 'boolean' | 'number';
|
||||
|
||||
|
@ -10,8 +10,8 @@ import {autobind, getSchemaTpl} from 'amis-editor-core';
|
||||
import {BaseLabelMark} from '../component/BaseControl';
|
||||
|
||||
import type {FormControlProps} from 'amis-core';
|
||||
import type {SchemaCollection} from 'amis/lib/Schema';
|
||||
import type {FormSchema} from 'amis/lib/schema';
|
||||
import type {SchemaCollection} from 'amis';
|
||||
import type {FormSchema} from '../../../amis/src/Schema';
|
||||
|
||||
export interface StatusControlProps extends FormControlProps {
|
||||
name: string;
|
||||
@ -52,7 +52,14 @@ export class StatusControl extends React.Component<
|
||||
}
|
||||
|
||||
initState() {
|
||||
const {data = {}, noBulkChange, noBulkChangeData, expressionName, name, trueValue} = this.props;
|
||||
const {
|
||||
data = {},
|
||||
noBulkChange,
|
||||
noBulkChangeData,
|
||||
expressionName,
|
||||
name,
|
||||
trueValue
|
||||
} = this.props;
|
||||
|
||||
const formData: StatusFormData = {
|
||||
statusType: 1,
|
||||
@ -62,7 +69,7 @@ export class StatusControl extends React.Component<
|
||||
let ctx = data;
|
||||
|
||||
if (noBulkChange && noBulkChangeData) {
|
||||
ctx = noBulkChangeData
|
||||
ctx = noBulkChangeData;
|
||||
}
|
||||
|
||||
if (ctx[expressionName] || ctx[expressionName] === '') {
|
||||
@ -87,7 +94,8 @@ export class StatusControl extends React.Component<
|
||||
handleSwitch(value: boolean) {
|
||||
const {trueValue, falseValue} = this.props;
|
||||
this.setState({checked: value == trueValue ? true : false}, () => {
|
||||
const {onBulkChange, noBulkChange, onDataChange, expressionName, name} = this.props;
|
||||
const {onBulkChange, noBulkChange, onDataChange, expressionName, name} =
|
||||
this.props;
|
||||
const newData = {
|
||||
[name]: value == trueValue ? trueValue : falseValue,
|
||||
[expressionName]: undefined
|
||||
@ -99,7 +107,8 @@ export class StatusControl extends React.Component<
|
||||
|
||||
@autobind
|
||||
handleFormSubmit(values: StatusFormData) {
|
||||
const {onBulkChange, noBulkChange, onDataChange, name, expressionName} = this.props;
|
||||
const {onBulkChange, noBulkChange, onDataChange, name, expressionName} =
|
||||
this.props;
|
||||
const data: Record<string, any> = {
|
||||
[name]: undefined,
|
||||
[expressionName]: undefined
|
||||
|
@ -12,9 +12,9 @@ import {FormItem, Button, Overlay, PopOver, Icon, Switch} from 'amis';
|
||||
import {isObject, autobind} from 'amis-editor-core';
|
||||
|
||||
import type {Action} from 'amis';
|
||||
import type {SchemaCollection} from 'amis/lib/Schema';
|
||||
import type {SchemaCollection} from 'amis';
|
||||
import type {IScopedContext} from 'amis-core';
|
||||
import type {FormSchema} from 'amis/lib/schema';
|
||||
import type {FormSchema} from 'amis';
|
||||
import type {FormControlProps} from 'amis-core';
|
||||
import {fromPairs, some} from 'lodash';
|
||||
|
||||
@ -33,7 +33,7 @@ export interface SwitchMoreProps extends FormControlProps {
|
||||
// offset?: ((clip: object, offset: object) => Offset) | Offset;
|
||||
// style?: object;
|
||||
overlay?: boolean;
|
||||
container?: HTMLElement | (() => HTMLElement) | Function;
|
||||
container?: HTMLElement | (() => HTMLElement);
|
||||
target?: React.ReactNode | Function;
|
||||
trueValue?: any; // 开关开启时匹配的 value, 默认 true
|
||||
falseValue?: any; // 开关关闭时匹配的 value, 默认 flase
|
||||
|
@ -6,13 +6,12 @@ import {findDOMNode} from 'react-dom';
|
||||
import cx from 'classnames';
|
||||
import uniqBy from 'lodash/uniqBy';
|
||||
import Sortable from 'sortablejs';
|
||||
import {render as amisRender, FormItem, Icon, InputBox} from 'amis';
|
||||
import {getI18nEnabled, tipedLabel} from 'amis-editor-core';
|
||||
import {render as amisRender, FormItem, Icon} from 'amis';
|
||||
import {getI18nEnabled} from 'amis-editor-core';
|
||||
import {autobind} from 'amis-editor-core';
|
||||
import {getSchemaTpl} from 'amis-editor-core';
|
||||
import type {FormControlProps} from 'amis-core';
|
||||
import type {SchemaApi} from 'amis/lib/Schema';
|
||||
import {isObject} from 'lodash';
|
||||
import type {SchemaApi} from 'amis';
|
||||
|
||||
type TimelineItem = {
|
||||
title: string;
|
||||
|
@ -4,8 +4,7 @@
|
||||
|
||||
import React from 'react';
|
||||
import {render as amisRender, FormItem} from 'amis';
|
||||
import {omit} from 'lodash';
|
||||
import type {SchemaApi} from 'amis/lib/Schema';
|
||||
import type {SchemaApi} from 'amis';
|
||||
import {autobind, getSchemaTpl} from 'amis-editor-core';
|
||||
import cx from 'classnames';
|
||||
import {tipedLabel} from 'amis-editor-core';
|
||||
|
@ -23,7 +23,7 @@ import {getSchemaTpl, tipedLabel} from 'amis-editor-core';
|
||||
|
||||
import type {Option} from 'amis';
|
||||
import type {FormControlProps} from 'amis-core';
|
||||
import type {SchemaApi, SchemaObject} from 'amis/lib/Schema';
|
||||
import type {SchemaApi} from 'amis';
|
||||
|
||||
export type OptionControlItem = Option & {checked?: boolean; _key?: string};
|
||||
|
||||
@ -233,9 +233,9 @@ export default class TreeOptionControl extends React.Component<
|
||||
options.splice(index, 1);
|
||||
} else {
|
||||
const {parentPath} = this.getNodePath(pathStr);
|
||||
const parentNode = get(options, parentPath, {});
|
||||
const parentNode: OptionControlItem = get(options, parentPath, {});
|
||||
parentNode?.children?.splice(index, 1);
|
||||
if (!parentNode?.children.length) {
|
||||
if (parentNode?.children?.length === 0) {
|
||||
// 去除僵尸子节点
|
||||
delete parentNode.children;
|
||||
}
|
||||
@ -269,7 +269,7 @@ export default class TreeOptionControl extends React.Component<
|
||||
} else {
|
||||
const index = path[path.length - 1];
|
||||
const {parentPath} = this.getNodePath(pathStr);
|
||||
const parentNode = get(options, parentPath, {});
|
||||
const parentNode: OptionControlItem = get(options, parentPath, {});
|
||||
parentNode.children?.splice(+index + 1, 0, {...defaultOption});
|
||||
set(options, parentPath, parentNode);
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ import {render, Button, Switch} from 'amis';
|
||||
import {autobind, getI18nEnabled} from 'amis-editor-core';
|
||||
import {Validator} from '../validator';
|
||||
import {tipedLabel} from 'amis-editor-core';
|
||||
import type {SchemaCollection} from 'amis/lib/Schema';
|
||||
import type {SchemaCollection} from 'amis';
|
||||
|
||||
export type ValidatorData = {
|
||||
name: string;
|
||||
|
@ -4,6 +4,7 @@
|
||||
import React, {useEffect, useRef, useState} from 'react';
|
||||
import {Button, Editor, Overlay, PopOver} from 'amis-ui';
|
||||
import {FormControlProps, FormItem, styleMap} from 'amis-core';
|
||||
// @ts-ignore
|
||||
import {parse as cssParse} from 'amis-postcss';
|
||||
import {PlainObject} from './types';
|
||||
import {debounce, isEmpty} from 'lodash';
|
||||
@ -107,14 +108,14 @@ function AmisThemeCssCodeEditor(props: FormControlProps) {
|
||||
nodeTabs.forEach(tab => {
|
||||
tab.children.forEach(node => {
|
||||
const nodes = cssParse(node.value)
|
||||
.nodes.map(node => {
|
||||
.nodes.map((node: any) => {
|
||||
const {prop, value} = node;
|
||||
return {
|
||||
prop,
|
||||
value
|
||||
};
|
||||
})
|
||||
.filter(n => n.value);
|
||||
.filter((n: any) => n.value);
|
||||
const selector = node.selector;
|
||||
const nameEtr = /\.(.*)\-/.exec(selector);
|
||||
const cssCode: PlainObject = {};
|
||||
@ -125,7 +126,7 @@ function AmisThemeCssCodeEditor(props: FormControlProps) {
|
||||
} else if (!!~selector.indexOf(':hover')) {
|
||||
state = 'hover';
|
||||
}
|
||||
nodes.forEach(item => {
|
||||
nodes.forEach((item: any) => {
|
||||
const prop = item.prop;
|
||||
const cssValue = item.value;
|
||||
if (!!~prop.indexOf('radius')) {
|
||||
@ -298,7 +299,7 @@ function AmisStyleCodeEditor(props: FormControlProps) {
|
||||
const newStyle: PlainObject = {};
|
||||
try {
|
||||
const style = cssParse(value);
|
||||
style.nodes.forEach(node => {
|
||||
style.nodes.forEach((node: any) => {
|
||||
const {prop, value} = node;
|
||||
if (value) {
|
||||
if (prop === 'border-radius') {
|
||||
@ -364,7 +365,7 @@ function ThemeCssCode(props: FormControlProps) {
|
||||
<Overlay
|
||||
container={document.body}
|
||||
placement="left"
|
||||
target={ref.current}
|
||||
target={ref.current as any}
|
||||
show={showEditor}
|
||||
rootClose={false}
|
||||
>
|
||||
|
@ -7,7 +7,7 @@ import {
|
||||
EditorManager
|
||||
} from 'amis-editor-core';
|
||||
import type {DSField} from 'amis-editor-core';
|
||||
import type {SchemaObject} from 'amis/lib/Schema';
|
||||
import type {SchemaObject} from 'amis';
|
||||
import flatten from 'lodash/flatten';
|
||||
import _ from 'lodash';
|
||||
import {InputComponentName} from '../component/InputComponentName';
|
||||
|
@ -5,11 +5,10 @@ import {
|
||||
getI18nEnabled
|
||||
} from 'amis-editor-core';
|
||||
import {tipedLabel} from 'amis-editor-core';
|
||||
import type {SchemaObject} from 'amis/lib/Schema';
|
||||
import type {SchemaObject} from 'amis';
|
||||
import assign from 'lodash/assign';
|
||||
import cloneDeep from 'lodash/cloneDeep';
|
||||
import omit from 'lodash/omit';
|
||||
import get from 'lodash/get';
|
||||
|
||||
setSchemaTpl('options', () => {
|
||||
const i18nEnabled = getI18nEnabled();
|
||||
|
@ -1,5 +1,5 @@
|
||||
import {setSchemaTpl, getSchemaTpl, defaultValue} from 'amis-editor-core';
|
||||
import type {SchemaCollection} from 'amis/lib/Schema';
|
||||
import type {SchemaCollection} from 'amis';
|
||||
import kebabCase from 'lodash/kebabCase';
|
||||
|
||||
setSchemaTpl('style:formItem', ({renderer, schema}: any) => {
|
||||
@ -430,8 +430,7 @@ setSchemaTpl(
|
||||
'theme:cssCode',
|
||||
({
|
||||
themeClass = [],
|
||||
isFormItem,
|
||||
isLayout
|
||||
isFormItem
|
||||
}: {
|
||||
themeClass?: any[];
|
||||
isFormItem?: boolean;
|
||||
|
@ -49,6 +49,7 @@ export interface FroalaEditorComponentProps {
|
||||
config: any;
|
||||
model: string;
|
||||
onModelChange: (value: string) => void;
|
||||
children?: React.ReactNode;
|
||||
}
|
||||
|
||||
// 代码来源于:https://github.com/froala/react-froala-wysiwyg/blob/master/lib/FroalaEditorFunctionality.jsx
|
||||
|
4
packages/amis-ui/src/custom.d.ts
vendored
4
packages/amis-ui/src/custom.d.ts
vendored
@ -12,3 +12,7 @@ declare module '*.scss' {
|
||||
const content: any;
|
||||
export default content;
|
||||
}
|
||||
|
||||
declare global {
|
||||
var amis: any;
|
||||
}
|
||||
|
@ -154,8 +154,38 @@ import './renderers/OfficeViewer';
|
||||
|
||||
import './compat';
|
||||
import './schemaExtend';
|
||||
import type {BaseSchema, SchemaCollection} from './Schema';
|
||||
import type {
|
||||
BaseSchema,
|
||||
FormSchema,
|
||||
SchemaApi,
|
||||
SchemaCollection,
|
||||
SchemaExpression,
|
||||
SchemaObject
|
||||
} from './Schema';
|
||||
import type {TableViewSchema, TrObject} from './renderers/TableView';
|
||||
import type {ActionSchema, ButtonSchema} from './renderers/Action';
|
||||
import type {CRUDCommonSchema} from './renderers/CRUD';
|
||||
import type {CRUD2Schema} from './renderers/CRUD2';
|
||||
import type {TabsSchema} from './renderers/Tabs';
|
||||
import {availableLanguages as EditorAvailableLanguages} from './renderers/Form/Editor';
|
||||
import type {Action} from './types';
|
||||
export * from './renderers/Form/IconPickerIcons';
|
||||
export * from './renderers/Form/IconSelectStore';
|
||||
|
||||
export {BaseSchema, SchemaCollection};
|
||||
export {
|
||||
BaseSchema,
|
||||
SchemaCollection,
|
||||
FormSchema,
|
||||
SchemaApi,
|
||||
SchemaObject,
|
||||
TableViewSchema,
|
||||
TrObject,
|
||||
ActionSchema,
|
||||
CRUDCommonSchema,
|
||||
ButtonSchema,
|
||||
CRUD2Schema,
|
||||
TabsSchema,
|
||||
SchemaExpression,
|
||||
Action,
|
||||
EditorAvailableLanguages
|
||||
};
|
||||
|
@ -60,7 +60,7 @@ export default function mockApiPlugin(options: {} = {}): Plugin {
|
||||
);
|
||||
|
||||
if (!fs.existsSync(filepath)) {
|
||||
res.json({
|
||||
(res as any).json({
|
||||
$schema: 'http://json-schema.org/draft-07/schema#',
|
||||
type: 'object',
|
||||
description:
|
||||
@ -69,7 +69,7 @@ export default function mockApiPlugin(options: {} = {}): Plugin {
|
||||
return;
|
||||
}
|
||||
|
||||
res.sendFile(filepath);
|
||||
(res as any).sendFile(filepath);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -20,6 +20,7 @@
|
||||
"skipLibCheck": true,
|
||||
"downlevelIteration": true,
|
||||
"composite": true,
|
||||
"allowJs": true,
|
||||
"baseUrl": "./",
|
||||
"paths": {
|
||||
"amis-core": ["./packages/amis-core/src/index.tsx"],
|
||||
@ -47,6 +48,8 @@
|
||||
"scripts/fis3plugin.ts",
|
||||
"scripts/markdownPlugin.ts",
|
||||
"scripts/mockApiPlugin.ts",
|
||||
"packages/amis-ui/src/custom.d.ts"
|
||||
"packages/amis-ui/src/custom.d.ts",
|
||||
"examples/polyfills/cloest.js",
|
||||
"examples/polyfills/classList.js"
|
||||
]
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user