feat: support i18n (#99)
* feat: i18next * multi language data * feat(client): locale support * en-US for collections * us-EN for routes * en-US for routes * en-US for attachments * feat: partial translations * translation * add AntdConfigProvider * translation * translation * feat: translation * feat: add translation * fix: improve translation * feat: improve translation * fix: SyntaxError: Unexpected token ) in JSON at position * typo * feat: improve translation * feat: improve translation * feat: language settings can be saved on the server * feat: lang option of init cli * demo translation * typo * change address field to textarea * address data * feat: chart translation * feat: chart translation * improve translation * signin,signup,signout... Co-authored-by: Zhou <zhou.working@gmail.com>
This commit is contained in:
parent
29184740bf
commit
479f64f197
@ -69,7 +69,8 @@ Installation
|
||||
|
||||
#### Quickstart
|
||||
~~~shell
|
||||
yarn create nocobase-app my-nocobase-app --quickstart
|
||||
# `--lang=en-US` Language settings support `--lang=en-US` and `--lang=zh-CN`
|
||||
yarn create nocobase-app my-nocobase-app --quickstart --lang=en-US # or zh-CN
|
||||
~~~
|
||||
|
||||
#### Step by step
|
||||
@ -81,7 +82,9 @@ yarn create nocobase-app my-nocobase-app
|
||||
cd my-nocobase-app
|
||||
|
||||
# 3. create initialization data
|
||||
yarn nocobase init --import-demo
|
||||
# `--import-demo` Importing demo data
|
||||
# `--lang=en-US` Language settings support `--lang=en-US` and `--lang=zh-CN`
|
||||
yarn nocobase init --import-demo --lang=en-US
|
||||
|
||||
# 4. start project
|
||||
yarn start
|
||||
|
@ -75,7 +75,8 @@ Database:
|
||||
|
||||
#### 快速启动
|
||||
~~~shell
|
||||
yarn create nocobase-app my-nocobase-app --quickstart
|
||||
yarn create nocobase-app my-nocobase-app --quickstart --lang=zh-CN
|
||||
# `--lang=en-US` 语言设置,支持 `--lang=en-US` 和 `--lang=zh-CN`
|
||||
~~~
|
||||
|
||||
#### 分步骤执行
|
||||
@ -87,7 +88,9 @@ yarn create nocobase-app my-nocobase-app
|
||||
cd my-nocobase-app
|
||||
|
||||
# 3. 初始化数据
|
||||
yarn nocobase init --import-demo
|
||||
yarn nocobase init --import-demo --lang=zh-CN
|
||||
# `--import-demo` 导入演示数据
|
||||
# `--lang=en-US` 语言设置,支持 `--lang=en-US` 和 `--lang=zh-CN`
|
||||
|
||||
# 4. 启动项目
|
||||
yarn start
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { useRequest } from 'ahooks';
|
||||
import { Spin } from 'antd';
|
||||
import React, { useMemo } from 'react';
|
||||
import { MemoryRouter as Router } from 'react-router-dom';
|
||||
import { HashRouter as Router } from 'react-router-dom';
|
||||
import {
|
||||
createRouteSwitch,
|
||||
RouteRedirectProps,
|
||||
@ -56,7 +56,7 @@ const App = () => {
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Router initialEntries={['/admin']}>
|
||||
<Router>
|
||||
<RouteSwitch routes={data} />
|
||||
</Router>
|
||||
</div>
|
||||
|
@ -31,7 +31,7 @@ With the environment ready, the next step is to install a NocoBase application.
|
||||
To make it easier for newcomers to install and start quickly, NocoBase provides a very simple command line.
|
||||
|
||||
```bash
|
||||
$ yarn create nocobase-app my-nocobase-app --quickstart
|
||||
$ yarn create nocobase-app my-nocobase-app --quickstart --lang=en-US
|
||||
```
|
||||
|
||||
The above command will help you quickly download, install and start the NocoBase application. If you prefer to perform step by step, you can also do this:
|
||||
@ -44,7 +44,7 @@ $ yarn create nocobase-app my-nocobase-app
|
||||
$ cd my-nocobase-app
|
||||
|
||||
# 3. 初始化数据
|
||||
$ yarn nocobase init --import-demo
|
||||
$ yarn nocobase init --import-demo --lang=en-US
|
||||
|
||||
# 4. 启动项目
|
||||
$ yarn start
|
||||
|
@ -37,7 +37,7 @@ $ yarn config set registry https://registry.npm.taobao.org/
|
||||
为了方便新人快速的安装并启动, NocoBase 提供了一行非常简单的命令:
|
||||
|
||||
```bash
|
||||
$ yarn create nocobase-app my-nocobase-app --quickstart
|
||||
$ yarn create nocobase-app my-nocobase-app --quickstart --lang=zh-CN
|
||||
```
|
||||
|
||||
上面这行命令会帮助你快速的下载、安装并启动 NocoBase 应用。如果你喜欢分步执行,也可以这样:
|
||||
@ -50,7 +50,7 @@ $ yarn create nocobase-app my-nocobase-app
|
||||
$ cd my-nocobase-app
|
||||
|
||||
# 3. 初始化数据
|
||||
$ yarn nocobase init --import-demo
|
||||
$ yarn nocobase init --import-demo --lang=zh-CN
|
||||
|
||||
# 4. 启动项目
|
||||
$ yarn start
|
||||
|
@ -53,6 +53,7 @@
|
||||
"eslint-plugin-promise": "^4.2.1",
|
||||
"eslint-plugin-react": "^7.23.2",
|
||||
"eslint-plugin-standard": "^4.0.1",
|
||||
"i18next": "^21.3.2",
|
||||
"jest": "^26.6.3",
|
||||
"koa-bodyparser": "^4.3.0",
|
||||
"lerna": "^3.22.0",
|
||||
@ -65,6 +66,7 @@
|
||||
"prettier": "^2.3.0",
|
||||
"react": "^17.0.1",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-i18next": "^11.12.0",
|
||||
"react-router-dom": "^5.2.0",
|
||||
"react-test-renderer": "^17.0.2",
|
||||
"rimraf": "^3.0.2",
|
||||
|
@ -23,7 +23,7 @@ export async function create(ctx: Context, next: Next) {
|
||||
resourceField,
|
||||
associatedName,
|
||||
resourceName,
|
||||
values: data,
|
||||
values: data = {},
|
||||
fields,
|
||||
} = ctx.action.params;
|
||||
const values = filterByFields(data, fields);
|
||||
|
@ -70,6 +70,7 @@ for (const plugin of plugins) {
|
||||
api.plugin(
|
||||
require(`@nocobase/plugin-client/${libDir}/server`).default, {
|
||||
dist: path.resolve(process.cwd(), './dist'),
|
||||
lang: process.env.APP_LANG,
|
||||
// importDemo: true,
|
||||
});
|
||||
|
||||
|
@ -37,6 +37,7 @@
|
||||
"monaco-editor": "^0.25.2",
|
||||
"react-big-calendar": "^0.33.6",
|
||||
"react-helmet": "^6.1.0",
|
||||
"react-i18next": "^11.12.0",
|
||||
"react-image-lightbox": "^5.1.4",
|
||||
"umi-request": "^1.3.5"
|
||||
}
|
||||
|
@ -1,15 +1,40 @@
|
||||
import React, { createContext } from 'react';
|
||||
// import { ConfigProvider as AntdConfigProvider } from 'antd';
|
||||
// import enUS from 'antd/lib/locale/en_US';
|
||||
// import zhCN from 'antd/lib/locale/zh_CN';
|
||||
import { ClientProvider } from './constate';
|
||||
// import moment from 'moment';
|
||||
// import 'moment/locale/zh-cn';
|
||||
// moment.locale('zh-cn');
|
||||
import { I18nextProvider, useTranslation } from 'react-i18next';
|
||||
import { i18n } from './i18n';
|
||||
import { ConfigProvider as AntdConfigProvider, Spin } from 'antd';
|
||||
import enUS from 'antd/lib/locale/en_US';
|
||||
import zhCN from 'antd/lib/locale/zh_CN';
|
||||
import { ClientProvider, useClient } from './constate';
|
||||
import useRequest from '@ahooksjs/use-request';
|
||||
|
||||
const ConfigContext = createContext<any>(null);
|
||||
function AntdProvider(props) {
|
||||
const { i18n } = useTranslation();
|
||||
const { client } = useClient();
|
||||
const { loading } = useRequest(() => client.request('app:getLang'), {
|
||||
onSuccess(data) {
|
||||
const locale = localStorage.getItem('locale');
|
||||
if (locale !== data.lang) {
|
||||
console.log('changeLanguage', data.lang);
|
||||
i18n.changeLanguage(data.lang);
|
||||
}
|
||||
},
|
||||
refreshDeps: [i18n.language],
|
||||
formatResult: (data) => data?.data,
|
||||
});
|
||||
if (loading) {
|
||||
return <Spin />;
|
||||
}
|
||||
console.log('i18n.language', i18n.language);
|
||||
return <AntdConfigProvider locale={i18n.language === 'zh-CN' ? zhCN : enUS}>{props.children}</AntdConfigProvider>;
|
||||
}
|
||||
|
||||
export function ConfigProvider(props: any) {
|
||||
const { client } = props;
|
||||
return <ClientProvider client={client}>{props.children}</ClientProvider>;
|
||||
return (
|
||||
<ClientProvider client={client}>
|
||||
<I18nextProvider i18n={i18n}>
|
||||
<AntdProvider>{props.children}</AntdProvider>
|
||||
</I18nextProvider>
|
||||
</ClientProvider>
|
||||
);
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { Menu, Switch } from 'antd';
|
||||
import { useCompile } from '../hooks/useCompile';
|
||||
|
||||
export interface SwitchMenuItemProps {
|
||||
onChange?: any;
|
||||
@ -9,6 +10,7 @@ export interface SwitchMenuItemProps {
|
||||
|
||||
export function SwitchMenuItem(props: SwitchMenuItemProps) {
|
||||
const { onChange } = props;
|
||||
const compile = useCompile();
|
||||
const [checked, setChecked] = useState(props.checked);
|
||||
useEffect(() => {
|
||||
setChecked(props.checked);
|
||||
@ -30,7 +32,7 @@ export function SwitchMenuItem(props: SwitchMenuItemProps) {
|
||||
justifyContent: 'space-between',
|
||||
}}
|
||||
>
|
||||
<span>{props.title}</span>
|
||||
<span>{compile(props.title)}</span>
|
||||
<Switch checked={checked} size={'small'} />
|
||||
</div>
|
||||
</Menu.Item>
|
||||
|
@ -26,7 +26,7 @@ export function AuthProvider(props) {
|
||||
const { pathname, search } = location;
|
||||
let redirect = `?redirect=${pathname}${search}`;
|
||||
if (service.error) {
|
||||
return <Redirect to={'/login' + redirect} />;
|
||||
return <Redirect to={'/signin' + redirect} />;
|
||||
}
|
||||
return (
|
||||
<AuthContext.Provider value={{ service, currentUser: service.data }}>
|
||||
|
@ -25,6 +25,8 @@ import {
|
||||
options,
|
||||
} from '../../../schemas/database-field/interfaces';
|
||||
import { useResourceRequest } from '../../../constate';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useCompile } from '../../../hooks/useCompile';
|
||||
|
||||
export const RoleContext = createContext(null);
|
||||
|
||||
@ -206,7 +208,7 @@ const collectionSchema: ISchema = {
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
name: 'action1',
|
||||
title: '删除',
|
||||
title: "{{t('Delete')}}",
|
||||
'x-align': 'right',
|
||||
'x-decorator': 'AddNew.Displayed',
|
||||
'x-decorator-props': {
|
||||
@ -216,15 +218,15 @@ const collectionSchema: ISchema = {
|
||||
'x-component-props': {
|
||||
icon: 'DeleteOutlined',
|
||||
confirm: {
|
||||
title: '删除数据',
|
||||
content: '删除后无法恢复,确定要删除吗?',
|
||||
title: "{{t('Delete record')}}",
|
||||
content: "{{t('Are you sure you want to delete it?')}}",
|
||||
},
|
||||
useAction: '{{ Table.useTableDestroyAction }}',
|
||||
},
|
||||
},
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
title: '添加',
|
||||
title: "{{t('Add new')}}",
|
||||
'x-align': 'right',
|
||||
'x-decorator': 'AddNew.Displayed',
|
||||
'x-decorator-props': {
|
||||
@ -240,7 +242,7 @@ const collectionSchema: ISchema = {
|
||||
},
|
||||
column1: {
|
||||
type: 'void',
|
||||
title: '字段名称',
|
||||
title: "{{t('Field display name')}}",
|
||||
'x-component': 'Table.Column',
|
||||
properties: {
|
||||
'uiSchema.title': {
|
||||
@ -252,7 +254,7 @@ const collectionSchema: ISchema = {
|
||||
},
|
||||
column2: {
|
||||
type: 'void',
|
||||
title: '字段标识',
|
||||
title: "{{t('Field name')}}",
|
||||
'x-component': 'Table.Column',
|
||||
properties: {
|
||||
name: {
|
||||
@ -264,7 +266,7 @@ const collectionSchema: ISchema = {
|
||||
},
|
||||
column3: {
|
||||
type: 'void',
|
||||
title: '字段类型',
|
||||
title: "{{t('Field type')}}",
|
||||
'x-component': 'Table.Column',
|
||||
properties: {
|
||||
interface: {
|
||||
@ -278,7 +280,7 @@ const collectionSchema: ISchema = {
|
||||
},
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
title: '操作',
|
||||
title: "{{t('Actions')}}",
|
||||
'x-component': 'Table.Column',
|
||||
'x-component-props': {
|
||||
width: 160,
|
||||
@ -293,7 +295,7 @@ const collectionSchema: ISchema = {
|
||||
properties: {
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
title: '编辑',
|
||||
title: "{{t('Edit')}}",
|
||||
'x-component': 'EditFieldButton',
|
||||
'x-component-props': {
|
||||
type: 'link',
|
||||
@ -309,7 +311,7 @@ const collectionSchema: ISchema = {
|
||||
},
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
title: '删除',
|
||||
title: "{{t('Delete')}}",
|
||||
'x-component': 'Action',
|
||||
'x-action-type': 'destroy',
|
||||
'x-component-props': {
|
||||
@ -330,7 +332,9 @@ const collectionSchema: ISchema = {
|
||||
|
||||
function FieldConfigTitle() {
|
||||
const ctx = useContext(TableRowContext);
|
||||
return <>{`配置「${ctx.record.title}」表字段`}</>;
|
||||
const { t } = useTranslation();
|
||||
const compile = useCompile();
|
||||
return <>{t('Configure fields of {{title}}', { title: compile(ctx.record.title) })}</>;
|
||||
}
|
||||
|
||||
function useCollectionResource({ onSuccess }) {
|
||||
@ -347,7 +351,7 @@ const schema: ISchema = {
|
||||
name: 'action',
|
||||
'x-component': 'Action',
|
||||
'x-component-props': {
|
||||
tooltip: '数据表配置',
|
||||
tooltip: "{{ t('Collections & Fields') }}",
|
||||
className: 'nb-database-config',
|
||||
icon: 'DatabaseOutlined',
|
||||
type: 'primary',
|
||||
@ -355,7 +359,7 @@ const schema: ISchema = {
|
||||
properties: {
|
||||
modal1: {
|
||||
type: 'void',
|
||||
title: '数据表配置',
|
||||
title: "{{t('Collections & Fields')}}",
|
||||
'x-component': 'Action.Drawer',
|
||||
properties: {
|
||||
table: {
|
||||
@ -382,7 +386,7 @@ const schema: ISchema = {
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
name: 'action1',
|
||||
title: '删除',
|
||||
title: "{{t('Delete')}}",
|
||||
'x-align': 'right',
|
||||
'x-decorator': 'AddNew.Displayed',
|
||||
'x-decorator-props': {
|
||||
@ -392,15 +396,15 @@ const schema: ISchema = {
|
||||
'x-component-props': {
|
||||
icon: 'DeleteOutlined',
|
||||
confirm: {
|
||||
title: '删除数据',
|
||||
content: '删除后无法恢复,确定要删除吗?',
|
||||
title: "{{t('Delete record')}}",
|
||||
content: "{{t('Are you sure you want to delete it?')}}",
|
||||
},
|
||||
useAction: '{{ Table.useTableDestroyAction }}',
|
||||
},
|
||||
},
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
title: '创建数据表',
|
||||
title: "{{t('Create collection')}}",
|
||||
'x-align': 'right',
|
||||
'x-decorator': 'AddNew.Displayed',
|
||||
'x-decorator-props': {
|
||||
@ -414,7 +418,7 @@ const schema: ISchema = {
|
||||
properties: {
|
||||
modal: {
|
||||
type: 'void',
|
||||
title: '创建数据表',
|
||||
title: "{{t('Create collection')}}",
|
||||
'x-decorator': 'Form',
|
||||
'x-decorator-props': {
|
||||
useResource: useCollectionResource,
|
||||
@ -426,17 +430,17 @@ const schema: ISchema = {
|
||||
properties: {
|
||||
title: {
|
||||
type: 'string',
|
||||
title: '数据表名称',
|
||||
title: "{{t('Collection display name')}}",
|
||||
'x-component': 'Input',
|
||||
'x-decorator': 'FormilyFormItem',
|
||||
},
|
||||
name: {
|
||||
type: 'string',
|
||||
title: '数据表标识',
|
||||
title: "{{t('Collection name')}}",
|
||||
'x-component': 'Input',
|
||||
'x-decorator': 'FormilyFormItem',
|
||||
description:
|
||||
'随机生成,可修改。支持英文、数字和下划线,必须以英文字母开头',
|
||||
"{{t('Randomly generated and can be modified. Support letters, numbers and underscores, must start with an letter.')}}",
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -446,7 +450,7 @@ const schema: ISchema = {
|
||||
},
|
||||
column1: {
|
||||
type: 'void',
|
||||
title: '数据表名称',
|
||||
title: "{{t('Collection display name')}}",
|
||||
'x-component': 'Table.Column',
|
||||
properties: {
|
||||
title: {
|
||||
@ -458,7 +462,7 @@ const schema: ISchema = {
|
||||
},
|
||||
column2: {
|
||||
type: 'void',
|
||||
title: '数据表标识',
|
||||
title: "{{t('Collection name')}}",
|
||||
'x-component': 'Table.Column',
|
||||
properties: {
|
||||
name: {
|
||||
@ -470,7 +474,7 @@ const schema: ISchema = {
|
||||
},
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
title: '操作',
|
||||
title: "{{t('Actions')}}",
|
||||
'x-component': 'Table.Column',
|
||||
'x-component-props': {
|
||||
width: 160,
|
||||
@ -485,7 +489,7 @@ const schema: ISchema = {
|
||||
properties: {
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
title: '配置字段',
|
||||
title: "{{t('Configure fields')}}",
|
||||
'x-component': 'Action',
|
||||
'x-component-props': {
|
||||
type: 'link',
|
||||
@ -506,7 +510,7 @@ const schema: ISchema = {
|
||||
},
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
title: '编辑',
|
||||
title: "{{t('Edit')}}",
|
||||
'x-component': 'Action',
|
||||
'x-component-props': {
|
||||
type: 'link',
|
||||
@ -515,7 +519,7 @@ const schema: ISchema = {
|
||||
properties: {
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
title: '编辑数据表',
|
||||
title: "{{t('Edit collection')}}",
|
||||
'x-decorator': 'Form',
|
||||
'x-decorator-props': {
|
||||
useResource: useDetailsResource,
|
||||
@ -527,7 +531,7 @@ const schema: ISchema = {
|
||||
properties: {
|
||||
title: {
|
||||
type: 'string',
|
||||
title: '数据表名称',
|
||||
title: "{{t('Collection display name')}}",
|
||||
'x-component': 'Input',
|
||||
'x-decorator': 'FormilyFormItem',
|
||||
},
|
||||
@ -537,14 +541,14 @@ const schema: ISchema = {
|
||||
},
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
title: '删除',
|
||||
title: "{{t('Delete')}}",
|
||||
'x-component': 'Action',
|
||||
'x-action-type': 'destroy',
|
||||
'x-component-props': {
|
||||
type: 'link',
|
||||
confirm: {
|
||||
title: '删除数据',
|
||||
content: '删除后无法恢复,确定要删除吗?',
|
||||
title: "{{t('Delete record')}}",
|
||||
content: "{{t('Are you sure you want to delete it?')}}",
|
||||
},
|
||||
useAction: '{{ Table.useTableDestroyAction }}',
|
||||
},
|
||||
@ -561,6 +565,8 @@ const schema: ISchema = {
|
||||
};
|
||||
|
||||
function CreateFieldButton() {
|
||||
const { t } = useTranslation();
|
||||
const compile = useCompile();
|
||||
const { refresh } = useCollectionsContext();
|
||||
const ctx = useContext(TableRowContext);
|
||||
const { service } = useTable();
|
||||
@ -612,14 +618,14 @@ function CreateFieldButton() {
|
||||
{options.map(
|
||||
(option, groupIndex) =>
|
||||
option.children.length > 0 && (
|
||||
<Menu.SubMenu key={groupIndex} title={option.label}>
|
||||
<Menu.SubMenu key={groupIndex} title={compile(option.label)}>
|
||||
{option.children.map((item) => (
|
||||
<Menu.Item
|
||||
disabled={item.disabled}
|
||||
style={{ minWidth: 120 }}
|
||||
key={item.name}
|
||||
>
|
||||
{item.title}
|
||||
{compile(item.title)}
|
||||
</Menu.Item>
|
||||
))}
|
||||
</Menu.SubMenu>
|
||||
@ -631,11 +637,11 @@ function CreateFieldButton() {
|
||||
<>
|
||||
<Dropdown overlay={menu} overlayClassName={'all-fields'}>
|
||||
<Button type={'primary'} icon={<PlusOutlined />}>
|
||||
添加 <DownOutlined />
|
||||
{t('Add new')} <DownOutlined />
|
||||
</Button>
|
||||
</Dropdown>
|
||||
<Drawer
|
||||
title={'添加字段'}
|
||||
title={t('Add field')}
|
||||
width={'50%'}
|
||||
visible={visible}
|
||||
onClose={() => {
|
||||
@ -650,7 +656,7 @@ function CreateFieldButton() {
|
||||
await form.reset();
|
||||
}}
|
||||
>
|
||||
取消
|
||||
{t('Cancel')}
|
||||
</Button>
|
||||
<Button
|
||||
type={'primary'}
|
||||
@ -662,7 +668,7 @@ function CreateFieldButton() {
|
||||
await refresh();
|
||||
}}
|
||||
>
|
||||
确定
|
||||
{t('Submit')}
|
||||
</Button>
|
||||
</Space>
|
||||
}
|
||||
@ -685,6 +691,7 @@ function CreateFieldButton() {
|
||||
}
|
||||
|
||||
function EditFieldButton() {
|
||||
const { t } = useTranslation();
|
||||
const { refresh, findCollection } = useCollectionsContext();
|
||||
const { service } = useTable();
|
||||
const ctx = useContext(TableRowContext);
|
||||
@ -729,10 +736,10 @@ function EditFieldButton() {
|
||||
form.setValues(clone(values || {}));
|
||||
}}
|
||||
>
|
||||
编辑
|
||||
{t('Edit')}
|
||||
</Button>
|
||||
<Drawer
|
||||
title={'编辑字段'}
|
||||
title={t('Edit field')}
|
||||
width={'50%'}
|
||||
visible={visible}
|
||||
onClose={() => setVisible(false)}
|
||||
@ -743,7 +750,7 @@ function EditFieldButton() {
|
||||
setVisible(false);
|
||||
}}
|
||||
>
|
||||
取消
|
||||
{t('Cancel')}
|
||||
</Button>
|
||||
<Button
|
||||
type={'primary'}
|
||||
@ -756,7 +763,7 @@ function EditFieldButton() {
|
||||
await refresh();
|
||||
}}
|
||||
>
|
||||
确定
|
||||
{t('Submit')}
|
||||
</Button>
|
||||
</Space>
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ import { useRequest } from 'ahooks';
|
||||
import { VisibleContext } from '../../context';
|
||||
import { ISchema } from '../../schemas';
|
||||
import { SystemSettingsContext } from './SiteTitle';
|
||||
import { i18n } from '../../i18n';
|
||||
|
||||
const useResource = ({ onSuccess }) => {
|
||||
const { service, resource } = useContext(SystemSettingsContext);
|
||||
@ -49,7 +50,7 @@ const schema: ISchema = {
|
||||
properties: {
|
||||
item1: {
|
||||
type: 'void',
|
||||
title: `系统配置`,
|
||||
title: i18n.t('System settings'),
|
||||
'x-component': 'Menu.Action',
|
||||
'x-component-props': {
|
||||
icon: 'SettingOutlined',
|
||||
@ -57,7 +58,7 @@ const schema: ISchema = {
|
||||
properties: {
|
||||
drawer1: {
|
||||
type: 'void',
|
||||
title: '系统配置',
|
||||
title: i18n.t('System settings'),
|
||||
'x-decorator': 'Form',
|
||||
'x-decorator-props': {
|
||||
useResource,
|
||||
@ -69,19 +70,29 @@ const schema: ISchema = {
|
||||
properties: {
|
||||
title: {
|
||||
type: 'string',
|
||||
title: '系统名称',
|
||||
title: i18n.t('System title'),
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input',
|
||||
},
|
||||
logo: {
|
||||
type: 'string',
|
||||
title: 'LOGO',
|
||||
title: i18n.t('Logo'),
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Upload.Attachment',
|
||||
'x-component-props': {
|
||||
// accept: 'jpg,png'
|
||||
},
|
||||
},
|
||||
appLang: {
|
||||
type: 'string',
|
||||
title: '{{t("Language")}}',
|
||||
'x-component': 'Select',
|
||||
'x-decorator': 'FormItem',
|
||||
enum: [
|
||||
{ label: 'English', value: 'en-US' },
|
||||
{ label: '简体中文', value: 'zh-CN' },
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -17,13 +17,15 @@ import { createContext } from 'react';
|
||||
import { RoleContext } from '.';
|
||||
import Checkbox from 'antd/lib/checkbox/Checkbox';
|
||||
import { useState } from 'react';
|
||||
import { useCompile } from '../../../hooks/useCompile';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const actionTypeMap = new Map(
|
||||
Object.entries({
|
||||
create: '添加',
|
||||
get: '查看',
|
||||
update: '编辑',
|
||||
destroy: '删除',
|
||||
create: '{{t("Insert")}}',
|
||||
get: '{{t("View")}}',
|
||||
update: '{{t("Update")}}',
|
||||
destroy: '{{t("Delete")}}',
|
||||
}),
|
||||
);
|
||||
|
||||
@ -44,6 +46,8 @@ const useActionDataSource = () => {
|
||||
};
|
||||
|
||||
const useFieldPermissions = () => {
|
||||
const { t } = useTranslation();
|
||||
const compile = useCompile();
|
||||
const role = useContext(RoleContext);
|
||||
const ctx = useContext(TableRowContext);
|
||||
const field = useField<Formily.Core.Models.ArrayField>();
|
||||
@ -163,7 +167,7 @@ const useFieldPermissions = () => {
|
||||
}
|
||||
}}
|
||||
/>{' '}
|
||||
{actionTypeMap.get(actionName)}
|
||||
{compile(actionTypeMap.get(actionName))}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@ -173,13 +177,16 @@ const useFieldPermissions = () => {
|
||||
render: (value, record) => renderCell(actionName, value, record),
|
||||
}));
|
||||
columns.unshift({
|
||||
title: '字段名称',
|
||||
title: t('Field display name'),
|
||||
dataIndex: ['field', 'uiSchema', 'title'],
|
||||
render: (v) => compile(v),
|
||||
});
|
||||
return { columns, dataSource, service };
|
||||
};
|
||||
|
||||
export const ActionPermissionField = observer((props) => {
|
||||
const { t } = useTranslation();
|
||||
const compile = useCompile();
|
||||
const role = useContext(RoleContext);
|
||||
const ctx = useContext(TableRowContext);
|
||||
const field = useField<Formily.Core.Models.ArrayField>();
|
||||
@ -193,22 +200,22 @@ export const ActionPermissionField = observer((props) => {
|
||||
pagination={false}
|
||||
columns={[
|
||||
{
|
||||
title: '操作',
|
||||
title: t('Action name'),
|
||||
dataIndex: 'actionName',
|
||||
render: (value) => <span>{actionTypeMap.get(value)}</span>,
|
||||
render: (value) => <span>{compile(actionTypeMap.get(value))}</span>,
|
||||
},
|
||||
{
|
||||
title: '类型',
|
||||
title: t('Action type'),
|
||||
dataIndex: 'actionName',
|
||||
render: (value) =>
|
||||
value === 'create' ? (
|
||||
<Tag>对新数据操作</Tag>
|
||||
<Tag color={'green'}>{t('Operate on new data')}</Tag>
|
||||
) : (
|
||||
<Tag>对已有数据操作</Tag>
|
||||
<Tag color={'blue'}>{t('Operate on existing data')}</Tag>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '允许操作',
|
||||
title: t('Allow action'),
|
||||
dataIndex: 'enable',
|
||||
render: (value, record) => (
|
||||
<Checkbox
|
||||
@ -242,7 +249,7 @@ export const ActionPermissionField = observer((props) => {
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '可操作的数据范围',
|
||||
title: t('Action scope'),
|
||||
dataIndex: ['scope', 'title'],
|
||||
render: (value) => (
|
||||
<Select style={{ minWidth: 150 }} size={'small'}></Select>
|
||||
|
@ -7,6 +7,7 @@ import { useContext } from 'react';
|
||||
import { RoleContext } from '.';
|
||||
import { useState } from 'react';
|
||||
import { useResourceRequest } from '../../../constate';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const getKeys = (items: any[]) => {
|
||||
const keys = [];
|
||||
@ -19,6 +20,7 @@ const getKeys = (items: any[]) => {
|
||||
};
|
||||
|
||||
export const MenuPermissionTable = observer((props) => {
|
||||
const { t } = useTranslation();
|
||||
const role = useContext(RoleContext);
|
||||
const [allUiSchemaKyes, setAllUiSchemaKyes] = useState([]);
|
||||
const [uiSchemaKyes, setUiSchemaKeys] = useState([]);
|
||||
@ -58,7 +60,7 @@ export const MenuPermissionTable = observer((props) => {
|
||||
}}
|
||||
columns={[
|
||||
{
|
||||
title: '菜单名称',
|
||||
title: t('Menu item name'),
|
||||
dataIndex: 'title',
|
||||
},
|
||||
{
|
||||
@ -83,7 +85,7 @@ export const MenuPermissionTable = observer((props) => {
|
||||
}
|
||||
}}
|
||||
/>{' '}
|
||||
允许访问
|
||||
{t('Allow access')}
|
||||
</div>
|
||||
),
|
||||
dataIndex: 'key',
|
||||
|
@ -17,6 +17,7 @@ import { createContext } from 'react';
|
||||
import { ActionPermissionField } from './ActionPermissionField';
|
||||
import { MenuPermissionTable } from './MenuPermissionTable';
|
||||
import { ISchema } from '../../../';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export const RoleContext = createContext(null);
|
||||
|
||||
@ -166,7 +167,7 @@ const collectionSchema: ISchema = {
|
||||
properties: {
|
||||
column1: {
|
||||
type: 'void',
|
||||
title: '数据表名称',
|
||||
title: '{{t("Collection display name")}}',
|
||||
'x-component': 'Table.Column',
|
||||
properties: {
|
||||
title: {
|
||||
@ -178,7 +179,7 @@ const collectionSchema: ISchema = {
|
||||
},
|
||||
column2: {
|
||||
type: 'void',
|
||||
title: '数据表标识',
|
||||
title: '{{t("Collection name")}}',
|
||||
'x-component': 'Table.Column',
|
||||
properties: {
|
||||
name: {
|
||||
@ -190,7 +191,7 @@ const collectionSchema: ISchema = {
|
||||
},
|
||||
column3: {
|
||||
type: 'void',
|
||||
title: '操作',
|
||||
title: '{{t("Actions")}}',
|
||||
'x-component': 'Table.Column',
|
||||
'x-component-props': {
|
||||
width: 60,
|
||||
@ -205,7 +206,7 @@ const collectionSchema: ISchema = {
|
||||
properties: {
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
title: '配置',
|
||||
title: '{{t("Configure")}}',
|
||||
'x-component': 'Action',
|
||||
'x-component-props': {
|
||||
type: 'link',
|
||||
@ -214,7 +215,7 @@ const collectionSchema: ISchema = {
|
||||
properties: {
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
title: '数据表操作权限',
|
||||
title: '{{t("Action permissions")}}',
|
||||
'x-component': 'Action.Drawer',
|
||||
'x-decorator': 'Form',
|
||||
'x-decorator-props': {
|
||||
@ -244,12 +245,14 @@ const menuSchema: ISchema = {
|
||||
'x-component': 'MenuPermissionTable',
|
||||
};
|
||||
|
||||
export const Permissions = () => {
|
||||
const { t } = useTranslation();
|
||||
const schema: ISchema = {
|
||||
type: 'void',
|
||||
name: 'action',
|
||||
'x-component': 'Action',
|
||||
'x-component-props': {
|
||||
tooltip: '权限配置',
|
||||
tooltip: '{{ t("Roles & Permissions") }}',
|
||||
className: 'nb-database-config',
|
||||
icon: 'LockOutlined',
|
||||
type: 'primary',
|
||||
@ -257,7 +260,7 @@ const schema: ISchema = {
|
||||
properties: {
|
||||
modal1: {
|
||||
type: 'void',
|
||||
title: '角色',
|
||||
title: '{{t("Roles")}}',
|
||||
'x-component': 'Action.Drawer',
|
||||
properties: {
|
||||
table: {
|
||||
@ -284,7 +287,7 @@ const schema: ISchema = {
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
name: 'action1',
|
||||
title: '删除',
|
||||
title: '{{t("Delete")}}',
|
||||
'x-align': 'right',
|
||||
'x-decorator': 'AddNew.Displayed',
|
||||
'x-decorator-props': {
|
||||
@ -294,15 +297,15 @@ const schema: ISchema = {
|
||||
'x-component-props': {
|
||||
icon: 'DeleteOutlined',
|
||||
confirm: {
|
||||
title: '删除数据',
|
||||
content: '删除后无法恢复,确定要删除吗?',
|
||||
title: '{{t("Delete record")}}',
|
||||
content: '{{t("Are you sure you want to delete it?")}}',
|
||||
},
|
||||
useAction: '{{ Table.useTableDestroyAction }}',
|
||||
},
|
||||
},
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
title: '添加',
|
||||
title: '{{t("Add new")}}',
|
||||
'x-align': 'right',
|
||||
'x-decorator': 'AddNew.Displayed',
|
||||
'x-decorator-props': {
|
||||
@ -316,7 +319,7 @@ const schema: ISchema = {
|
||||
properties: {
|
||||
modal: {
|
||||
type: 'void',
|
||||
title: '添加数据',
|
||||
title: '{{t("Add role")}}',
|
||||
'x-decorator': 'Form',
|
||||
'x-component': 'Action.Drawer',
|
||||
'x-component-props': {
|
||||
@ -325,7 +328,7 @@ const schema: ISchema = {
|
||||
properties: {
|
||||
title: {
|
||||
type: 'string',
|
||||
title: '角色名称',
|
||||
title: '{{t("Role name")}}',
|
||||
'x-component': 'Input',
|
||||
'x-decorator': 'FormilyFormItem',
|
||||
},
|
||||
@ -343,7 +346,7 @@ const schema: ISchema = {
|
||||
},
|
||||
column1: {
|
||||
type: 'void',
|
||||
title: '角色名称',
|
||||
title: '{{t("Role name")}}',
|
||||
'x-component': 'Table.Column',
|
||||
properties: {
|
||||
title: {
|
||||
@ -367,7 +370,7 @@ const schema: ISchema = {
|
||||
// },
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
title: '操作',
|
||||
title: '{{t("Actions")}}',
|
||||
'x-component': 'Table.Column',
|
||||
'x-component-props': {
|
||||
width: 160,
|
||||
@ -382,7 +385,7 @@ const schema: ISchema = {
|
||||
properties: {
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
title: '配置',
|
||||
title: '{{t("Configure")}}',
|
||||
'x-component': 'Action',
|
||||
'x-component-props': {
|
||||
type: 'link',
|
||||
@ -391,7 +394,7 @@ const schema: ISchema = {
|
||||
properties: {
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
title: '配置权限',
|
||||
title: '{{t("Configure permissions")}}',
|
||||
'x-decorator': 'RoleProvider',
|
||||
'x-component': 'Action.Drawer',
|
||||
'x-component-props': {
|
||||
@ -407,7 +410,7 @@ const schema: ISchema = {
|
||||
properties: {
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
title: '数据表操作权限',
|
||||
title: '{{t("Action permissions")}}',
|
||||
'x-component': 'Tabs.TabPane',
|
||||
'x-component-props': {},
|
||||
properties: {
|
||||
@ -416,7 +419,7 @@ const schema: ISchema = {
|
||||
},
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
title: '菜单访问权限',
|
||||
title: '{{t("Menu permissions")}}',
|
||||
'x-component': 'Tabs.TabPane',
|
||||
'x-component-props': {},
|
||||
properties: {
|
||||
@ -431,7 +434,7 @@ const schema: ISchema = {
|
||||
},
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
title: '编辑',
|
||||
title: '{{t("Edit")}}',
|
||||
'x-component': 'Action',
|
||||
'x-component-props': {
|
||||
type: 'link',
|
||||
@ -440,7 +443,7 @@ const schema: ISchema = {
|
||||
properties: {
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
title: '编辑角色',
|
||||
title: '{{t("Edit role")}}',
|
||||
'x-decorator': 'Form',
|
||||
'x-decorator-props': {
|
||||
useResource: useDetailsResource,
|
||||
@ -452,7 +455,7 @@ const schema: ISchema = {
|
||||
properties: {
|
||||
title: {
|
||||
type: 'string',
|
||||
title: '角色名称',
|
||||
title: '{{t("Role name")}}',
|
||||
'x-component': 'Input',
|
||||
'x-decorator': 'FormilyFormItem',
|
||||
},
|
||||
@ -462,15 +465,15 @@ const schema: ISchema = {
|
||||
},
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
title: '删除',
|
||||
title: '{{t("Delete")}}',
|
||||
'x-component': 'Action',
|
||||
'x-designable-bar': 'Table.Action.DesignableBar',
|
||||
'x-action-type': 'destroy',
|
||||
'x-component-props': {
|
||||
type: 'link',
|
||||
confirm: {
|
||||
title: '删除数据',
|
||||
content: '删除后无法恢复,确定要删除吗?',
|
||||
title: '{{t("Delete record")}}',
|
||||
content: "{{t('Are you sure you want to delete it?')}}",
|
||||
},
|
||||
useAction: '{{ Table.useTableDestroyAction }}',
|
||||
},
|
||||
@ -486,9 +489,9 @@ const schema: ISchema = {
|
||||
},
|
||||
};
|
||||
|
||||
export const Permissions = () => {
|
||||
return (
|
||||
<SchemaRenderer
|
||||
scope={{ t }}
|
||||
components={{ RoleProvider, ActionPermissionField, MenuPermissionTable }}
|
||||
schema={schema}
|
||||
/>
|
||||
|
@ -6,12 +6,14 @@ import { AuthContext, useCurrentUser } from './Auth';
|
||||
import { FormButtonGroup, FormDrawer, FormLayout, Submit } from '@formily/antd';
|
||||
import { useState } from 'react';
|
||||
import { useClient } from '../../constate';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export const UserInfo = () => {
|
||||
const history = useHistory();
|
||||
const { service, currentUser } = useContext(AuthContext);
|
||||
const [visible, setVisible] = useState(false);
|
||||
const { request } = useClient();
|
||||
const { t, i18n } = useTranslation();
|
||||
return (
|
||||
<Dropdown
|
||||
visible={visible}
|
||||
@ -21,7 +23,7 @@ export const UserInfo = () => {
|
||||
<Menu.Item
|
||||
onClick={async () => {
|
||||
setVisible(false);
|
||||
const values = await FormDrawer('个人资料', () => {
|
||||
const values = await FormDrawer(t('Edit profile'), () => {
|
||||
return (
|
||||
<FormLayout layout={'vertical'}>
|
||||
<SchemaField
|
||||
@ -30,22 +32,32 @@ export const UserInfo = () => {
|
||||
properties: {
|
||||
email: {
|
||||
type: 'string',
|
||||
title: '邮箱',
|
||||
title: t('Email'),
|
||||
'x-component': 'Input',
|
||||
'x-decorator': 'FormilyFormItem',
|
||||
},
|
||||
nickname: {
|
||||
type: 'string',
|
||||
title: '昵称',
|
||||
title: t('Nickname'),
|
||||
'x-component': 'Input',
|
||||
'x-decorator': 'FormilyFormItem',
|
||||
},
|
||||
// appLang: {
|
||||
// type: 'string',
|
||||
// title: '{{t("Language")}}',
|
||||
// 'x-component': 'Select',
|
||||
// 'x-decorator': 'FormItem',
|
||||
// enum: [
|
||||
// { label: 'English', value: 'en-US' },
|
||||
// { label: '简体中文', value: 'zh-CN' },
|
||||
// ],
|
||||
// },
|
||||
},
|
||||
}}
|
||||
/>
|
||||
<FormDrawer.Footer>
|
||||
<FormButtonGroup align="right">
|
||||
<Submit onSubmit={(values) => {}}>保存</Submit>
|
||||
<Submit onSubmit={(values) => {}}>{t('Submit')}</Submit>
|
||||
</FormButtonGroup>
|
||||
</FormDrawer.Footer>
|
||||
</FormLayout>
|
||||
@ -60,12 +72,12 @@ export const UserInfo = () => {
|
||||
service.mutate(data);
|
||||
}}
|
||||
>
|
||||
个人资料
|
||||
{t('Edit profile')}
|
||||
</Menu.Item>
|
||||
<Menu.Item>
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
|
||||
<span style={{ marginRight: 16, display: 'inline-block' }}>
|
||||
角色切换
|
||||
{t('Switch role')}
|
||||
</span>
|
||||
<Select
|
||||
className={'roles-select'}
|
||||
@ -75,7 +87,7 @@ export const UserInfo = () => {
|
||||
defaultValue={'admin'}
|
||||
disabled
|
||||
options={[
|
||||
{ label: '超级管理员', value: 'admin' },
|
||||
{ label: t('Super admin'), value: 'admin' },
|
||||
{ label: '数据管理员', value: 'editor' },
|
||||
{ label: '普通成员', value: 'member' },
|
||||
]}
|
||||
@ -85,14 +97,22 @@ export const UserInfo = () => {
|
||||
<Menu.Item>
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
|
||||
<span style={{ marginRight: 16, display: 'inline-block' }}>
|
||||
语言设置
|
||||
{t('Language')}
|
||||
</span>
|
||||
<Select
|
||||
className={'roles-select'}
|
||||
bordered={false}
|
||||
size={'small'}
|
||||
disabled
|
||||
defaultValue={'zh-CN'}
|
||||
defaultValue={i18n.language}
|
||||
onChange={async (value) => {
|
||||
await request('users:updateProfile', {
|
||||
method: 'post',
|
||||
data: {
|
||||
appLang: value,
|
||||
},
|
||||
});
|
||||
await i18n.changeLanguage(value);
|
||||
}}
|
||||
options={[
|
||||
{ label: '简体中文', value: 'zh-CN' },
|
||||
{ label: 'English', value: 'en-US' },
|
||||
@ -103,12 +123,12 @@ export const UserInfo = () => {
|
||||
<Menu.Divider />
|
||||
<Menu.Item
|
||||
onClick={async () => {
|
||||
await request('users:logout');
|
||||
await request('users:signout');
|
||||
localStorage.removeItem('NOCOBASE_TOKEN');
|
||||
history.push('/login');
|
||||
history.push('/signin');
|
||||
}}
|
||||
>
|
||||
退出登录
|
||||
{t('Sign out')}
|
||||
</Menu.Item>
|
||||
</Menu>
|
||||
}
|
||||
|
@ -47,8 +47,10 @@ import {
|
||||
import { AuthProvider } from './Auth';
|
||||
import { Helmet } from 'react-helmet';
|
||||
import { MenuSelectedKeysContext } from '../../schemas/menu';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
function DesignableToggle() {
|
||||
const { t } = useTranslation();
|
||||
const { designable, setDesignable } = useDesignableSwitchContext();
|
||||
const [visible, setVisible] = useState(false);
|
||||
useEffect(() => {
|
||||
@ -69,14 +71,14 @@ function DesignableToggle() {
|
||||
placement={'bottom'}
|
||||
title={
|
||||
<span>
|
||||
点此进入界面配置{' '}
|
||||
{t('Click here to enter UI editor.')}{' '}
|
||||
<a
|
||||
onClick={() => {
|
||||
localStorage.setItem('hide-tip', 'true');
|
||||
setVisible(false);
|
||||
}}
|
||||
>
|
||||
关闭
|
||||
{t('Close')}
|
||||
</a>
|
||||
</span>
|
||||
}
|
||||
@ -87,7 +89,7 @@ function DesignableToggle() {
|
||||
>
|
||||
<span style={{ height: 45, width: 45, position: 'absolute' }}></span>
|
||||
</Tooltip>
|
||||
<Tooltip title={'界面配置'}>
|
||||
<Tooltip title={t('UI editor')}>
|
||||
<Button
|
||||
className={cls('nb-designable-toggle', {
|
||||
'has-tip': visible,
|
||||
|
@ -7,45 +7,53 @@ import { useForm } from '@formily/react';
|
||||
import { useHistory, useLocation } from 'react-router-dom';
|
||||
import { useSystemSettings } from '../admin-layout/SiteTitle';
|
||||
import { useClient } from '../../constate';
|
||||
import { useCompile } from '../../hooks/useCompile';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
function Div(props) {
|
||||
return <div {...props}></div>;
|
||||
}
|
||||
|
||||
export function useLogin() {
|
||||
export function useSignin() {
|
||||
const form = useForm();
|
||||
const history = useHistory();
|
||||
const location = useLocation<any>();
|
||||
const query = new URLSearchParams(location.search);
|
||||
const redirect = query.get('redirect');
|
||||
const { request } = useClient();
|
||||
const { i18n } = useTranslation();
|
||||
return {
|
||||
async run() {
|
||||
await form.submit();
|
||||
const { data } = await request('users:login', {
|
||||
const { data } = await request('users:signin', {
|
||||
method: 'post',
|
||||
data: form.values,
|
||||
});
|
||||
const lang = localStorage.getItem('locale');
|
||||
if (data.appLang !== lang) {
|
||||
await i18n.changeLanguage(data.appLang);
|
||||
}
|
||||
history.push(redirect || '/admin');
|
||||
localStorage.setItem('NOCOBASE_TOKEN', data?.token);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function useRegister() {
|
||||
export function useSignup() {
|
||||
const form = useForm();
|
||||
const history = useHistory();
|
||||
const { request } = useClient();
|
||||
const { t } = useTranslation();
|
||||
return {
|
||||
async run() {
|
||||
await form.submit();
|
||||
const { data } = await request('users:register', {
|
||||
const { data } = await request('users:signup', {
|
||||
method: 'post',
|
||||
data: form.values,
|
||||
});
|
||||
message.success('注册成功,将跳转登录页');
|
||||
message.success(t('Signed up successfully. It will jump to the login page.'));
|
||||
setTimeout(() => {
|
||||
history.push('/login');
|
||||
history.push('/signin');
|
||||
}, 1000);
|
||||
console.log(form.values);
|
||||
},
|
||||
@ -60,6 +68,7 @@ export function RouteSchemaRenderer({ route }) {
|
||||
formatResult: (result) => result?.data,
|
||||
},
|
||||
);
|
||||
const compile = useCompile();
|
||||
const { title } = useSystemSettings();
|
||||
if (loading) {
|
||||
return <Spin size={'large'} className={'nb-spin-center'} />;
|
||||
@ -67,11 +76,13 @@ export function RouteSchemaRenderer({ route }) {
|
||||
return (
|
||||
<div>
|
||||
<Helmet>
|
||||
<title>{title ? `${data.title} - ${title}` : data.title}</title>
|
||||
<title>
|
||||
{title ? `${compile(data.title)} - ${title}` : compile(data.title)}
|
||||
</title>
|
||||
</Helmet>
|
||||
<SchemaRenderer
|
||||
components={{ Div }}
|
||||
scope={{ useLogin, useRegister }}
|
||||
scope={{ useSignin, useSignup }}
|
||||
schema={data}
|
||||
/>
|
||||
</div>
|
||||
|
@ -13,7 +13,7 @@ const RouteSwitch = createRouteSwitch({
|
||||
console.log({ props });
|
||||
return <div>Home {props.children}</div>;
|
||||
},
|
||||
Login: () => <div>Login</div>,
|
||||
Signin: () => <div>Signin</div>,
|
||||
},
|
||||
});
|
||||
|
||||
@ -21,9 +21,9 @@ export default () => {
|
||||
const routes: Array<RouteRedirectProps> = [
|
||||
{
|
||||
type: 'route',
|
||||
path: '/login',
|
||||
path: '/signin',
|
||||
exact: true,
|
||||
component: 'Login',
|
||||
component: 'Signin',
|
||||
},
|
||||
{
|
||||
type: 'route',
|
||||
@ -34,7 +34,7 @@ export default () => {
|
||||
type: 'route',
|
||||
path: '/home/123',
|
||||
exact: true,
|
||||
component: 'Login',
|
||||
component: 'Signin',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
@ -38,14 +38,14 @@ const routes: Array<RouteRedirectProps> = [
|
||||
children: [
|
||||
{
|
||||
type: 'route',
|
||||
path: '/login',
|
||||
path: '/signin',
|
||||
component: 'RouteSchemaRenderer',
|
||||
title: `登录`,
|
||||
uiSchemaKey: 'dtf9j0b8p9u',
|
||||
},
|
||||
{
|
||||
type: 'route',
|
||||
path: '/register',
|
||||
path: '/signup',
|
||||
component: 'RouteSchemaRenderer',
|
||||
title: `注册`,
|
||||
uiSchemaKey: '46qlxqam3xk',
|
||||
|
@ -78,6 +78,7 @@ import {
|
||||
useCollectionContext,
|
||||
useResourceRequest,
|
||||
} from '../../constate';
|
||||
import { i18n } from '../../i18n';
|
||||
|
||||
export const BlockContext = createContext({ dragRef: null });
|
||||
|
||||
@ -189,6 +190,7 @@ const useAssociationResource = (options) => {
|
||||
|
||||
export const SchemaField = createSchemaField({
|
||||
scope: {
|
||||
t: i18n.t.bind(i18n),
|
||||
Table,
|
||||
Calendar,
|
||||
Kanban,
|
||||
|
@ -13,6 +13,8 @@ import {
|
||||
} from '../';
|
||||
import { UseRequestProvider } from 'ahooks';
|
||||
import { extend } from 'umi-request';
|
||||
import { I18nextProvider } from 'react-i18next';
|
||||
import i18n from '../i18n';
|
||||
|
||||
const request = extend({
|
||||
prefix: process.env.API_URL,
|
||||
|
9
packages/client/src/hooks/useCompile.ts
Normal file
9
packages/client/src/hooks/useCompile.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import { compile } from '@formily/json-schema/lib/compiler';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export const useCompile = () => {
|
||||
const { t } = useTranslation();
|
||||
return (source: any) => {
|
||||
return compile(source, { t });
|
||||
};
|
||||
};
|
52
packages/client/src/i18n.ts
Normal file
52
packages/client/src/i18n.ts
Normal file
@ -0,0 +1,52 @@
|
||||
import i18next from 'i18next';
|
||||
import { initReactI18next } from 'react-i18next';
|
||||
import zhCN from './locale/zh_CN';
|
||||
import enUS from './locale/en_US';
|
||||
import moment from 'moment';
|
||||
|
||||
export const i18n = i18next.createInstance();
|
||||
|
||||
i18n.use(initReactI18next).init({
|
||||
lng: localStorage.getItem('locale') || 'en-US',
|
||||
debug: true,
|
||||
defaultNS: 'client',
|
||||
parseMissingKeyHandler: (key) => {
|
||||
console.log('parseMissingKeyHandler', `'${key}': '${key}',`);
|
||||
return key;
|
||||
},
|
||||
// ns: ['client'],
|
||||
resources: {
|
||||
'en-US': {
|
||||
client: {
|
||||
...enUS,
|
||||
},
|
||||
},
|
||||
'zh-CN': {
|
||||
client: {
|
||||
...zhCN,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const momentLngs = {
|
||||
'en-US': 'en',
|
||||
'zh-CN': 'zh-cn',
|
||||
};
|
||||
|
||||
function setMomentLng(language) {
|
||||
const lng = momentLngs[language||'en-US'] || 'en';
|
||||
console.log("localStorage.getItem('locale')", lng);
|
||||
moment.locale(lng);
|
||||
}
|
||||
|
||||
setMomentLng(localStorage.getItem('locale'));
|
||||
|
||||
i18n.on('languageChanged', (lng) => {
|
||||
localStorage.setItem('locale', lng);
|
||||
setMomentLng(lng);
|
||||
});
|
||||
|
||||
// export const t = i18n.t;
|
||||
|
||||
export default i18n;
|
@ -6,3 +6,4 @@ export * from './schemas';
|
||||
export * from './constate';
|
||||
export * from './ClientSDK';
|
||||
export * from './ConfigProvider';
|
||||
export * from './i18n';
|
||||
|
@ -1 +1,274 @@
|
||||
export default {};
|
||||
export default {
|
||||
'{{count}} filter items_one': '{{count}} filter item',
|
||||
'{{count}} filter items_other': '{{count}} filter items',
|
||||
'{{count}} more items_one': '{{count}} more item',
|
||||
'{{count}} more items_other': '{{count}} more items',
|
||||
'Delete menu item': 'Delete menu item',
|
||||
'Today': 'Today',
|
||||
'Month': 'Month',
|
||||
'Week': 'Week',
|
||||
'Work week': 'Work week',
|
||||
'Day': 'Day',
|
||||
'Agenda': 'Agenda',
|
||||
'Date': 'Date',
|
||||
'Time': 'Time',
|
||||
'Event': 'Event',
|
||||
'None': 'None',
|
||||
'System settings': 'System settings',
|
||||
'System title': 'System title',
|
||||
'Logo': 'Logo',
|
||||
'Add menu item': 'Add menu item',
|
||||
'Page': 'Page',
|
||||
'Name': 'Name',
|
||||
'Icon': 'Icon',
|
||||
'Group': 'Group',
|
||||
'Link': 'Link',
|
||||
'Edit menu item': 'Edit menu item',
|
||||
'Move to': 'Move to',
|
||||
'Insert left': 'Insert left',
|
||||
'Insert right': 'Insert right',
|
||||
'Insert inner': 'Insert inner',
|
||||
'Delete': 'Delete',
|
||||
'UI editor': 'UI editor',
|
||||
'Collections & Fields': 'Collections & Fields',
|
||||
'Roles & Permissions': 'Roles & Permissions',
|
||||
'Edit profile': 'Edit profile',
|
||||
'Switch role': 'Switch role',
|
||||
'Super admin': 'Super admin',
|
||||
'Language': 'Language',
|
||||
'Sign out': 'Sign out',
|
||||
'Cancel': 'Cancel',
|
||||
'Submit': 'Submit',
|
||||
'Set the data scope': 'Set the data scope',
|
||||
'Data blocks': 'Data blocks',
|
||||
'Table': 'Table',
|
||||
'Form': 'Form',
|
||||
'Select data source': 'Select data source',
|
||||
'Calendar': 'Calendar',
|
||||
'Kanban': 'Kanban',
|
||||
'Select group field': 'Select group field',
|
||||
'Media': 'Media',
|
||||
'Markdown': 'Markdown',
|
||||
'Wysiwyg': 'Wysiwyg',
|
||||
'Charts': 'Charts',
|
||||
'Column chart': 'Column chart',
|
||||
'Bar chart': 'Bar chart',
|
||||
'Line chart': 'Line chart',
|
||||
'Pie chart': 'Pie chart',
|
||||
'Select template': 'Select template',
|
||||
'Action logs': 'Action logs',
|
||||
'Create template': 'Create template',
|
||||
'Edit markdown': 'Edit markdown',
|
||||
'Add block': 'Add block',
|
||||
'Add new': 'Add new',
|
||||
'Add record': 'Add record',
|
||||
'Custom field display name': 'Custom field display name',
|
||||
'Display fields': 'Display fields',
|
||||
'Edit record': 'Edit record',
|
||||
|
||||
'Add page': 'Add page',
|
||||
'Add group': 'Add group',
|
||||
'Add link': 'Add link',
|
||||
'Insert above': 'Insert above',
|
||||
'Insert below': 'Insert below',
|
||||
'Save': 'Save',
|
||||
'Delete block': 'Delete block',
|
||||
'Are you sure you want to delete it?': 'Are you sure you want to delete it?',
|
||||
'This is a demo text, **supports Markdown syntax**.': 'This is a demo text, **supports Markdown syntax**.',
|
||||
|
||||
'Filter': 'Filter',
|
||||
'Action type': 'Action type',
|
||||
'Actions': 'Actions',
|
||||
'Insert': 'Insert',
|
||||
'Update': 'Update',
|
||||
'View': 'View',
|
||||
'View record': 'View record',
|
||||
|
||||
'Data changes': 'Data changes',
|
||||
'Field name': 'Field name',
|
||||
'Before change': 'Before change',
|
||||
'After change': 'After change',
|
||||
|
||||
'Delete record': 'Delete record',
|
||||
'Create collection': 'Create collection',
|
||||
'Collection display name': 'Collection display name',
|
||||
'Collection name': 'Collection name',
|
||||
'Randomly generated and can be modified. Support letters, numbers and underscores, must start with an letter.': 'Randomly generated and can be modified. Support letters, numbers and underscores, must start with an letter.',
|
||||
'Storage type': 'Storage type',
|
||||
'Edit': 'Edit',
|
||||
'Edit collection': 'Edit collection',
|
||||
'Configure fields': 'Configure fields',
|
||||
'Edit field': 'Edit field',
|
||||
'Configure fields of {{title}}': 'Configure fields of {{title}}',
|
||||
'Basic': 'Basic',
|
||||
'Single line text': 'Single line text',
|
||||
'Long text': 'Long text',
|
||||
'Phone': 'Phone',
|
||||
'Email': 'Email',
|
||||
'Number': 'Number',
|
||||
'Percent': 'Percent',
|
||||
'Password': 'Password',
|
||||
'Choices': 'Choices',
|
||||
'Checkbox': 'Checkbox',
|
||||
'Single select': 'Single select',
|
||||
'Multiple select': 'Multiple select',
|
||||
'Radio group': 'Radio group',
|
||||
'Checkbox group': 'Checkbox group',
|
||||
'China region': 'China region',
|
||||
'Attachment': 'Attachment',
|
||||
'Date & Time': 'Date & Time',
|
||||
'Datetime': 'Datetime',
|
||||
'Relation': 'Relation',
|
||||
'Link to': 'Link to',
|
||||
'Sub-table': 'Sub-table',
|
||||
'System info': 'System info',
|
||||
'Created at': 'Created at',
|
||||
'Last updated at': 'Last updated at',
|
||||
'Created by': 'Created by',
|
||||
'Last updated by': 'Last updated by',
|
||||
'Add field': 'Add field',
|
||||
'Field display name': 'Field display name',
|
||||
'Field type': 'Field type',
|
||||
|
||||
'Date format': 'Date format',
|
||||
'Year/Month/Day': 'Year/Month/Day',
|
||||
'Year-Month-Day': 'Year-Month-Day',
|
||||
'Day/Month/Year': 'Day/Month/Year',
|
||||
'Show time': 'Show time',
|
||||
'Time format': 'Time format',
|
||||
'12 hour': '12 hour',
|
||||
'24 hour': '24 hour',
|
||||
|
||||
'Meet <1><0>All</0><1>Any</1></1> conditions in the group': 'Meet <1><0>All</0><1>Any</1></1> conditions in the group',
|
||||
'Add filter': 'Add filter',
|
||||
'Add filter group': 'Add filter group',
|
||||
'is': 'is',
|
||||
'is not': 'is not',
|
||||
'contains': 'contains',
|
||||
'does not contain': 'does not contain',
|
||||
'is empty': 'is empty',
|
||||
'is not empty': 'is not empty',
|
||||
'Display <1><0>10</0><1>20</1><2>50</2><3>100</3></1> items per page': 'Display <1><0>10</0><1>20</1><2>50</2><3>100</3></1> items per page',
|
||||
'Edit chart': 'Edit chart',
|
||||
'Add text': 'Add text',
|
||||
'Filterable fields': 'Filterable fields',
|
||||
'Edit button': 'Edit button',
|
||||
'Hide': 'Hide',
|
||||
'Enable actions': 'Enable actions',
|
||||
'Export': 'Export',
|
||||
'Customize': 'Customize',
|
||||
'Function': 'Function',
|
||||
'Popup form': 'Popup form',
|
||||
'Flexible popup': 'Flexible popup',
|
||||
'Configure actions': 'Configure actions',
|
||||
'Display order number': 'Display order number',
|
||||
'Enable drag and drop sorting': 'Enable drag and drop sorting',
|
||||
'Trigger on click the table row': 'Trigger on click the table row',
|
||||
'Add tab': 'Add tab',
|
||||
'Disable tabs': 'Disable tabs',
|
||||
'Details': 'Details',
|
||||
'Edit tab': 'Edit tab',
|
||||
'Relationship blocks': 'Relationship blocks',
|
||||
'Select record': 'Select record',
|
||||
'Display name': 'Display name',
|
||||
'Select icon': 'Select icon',
|
||||
'Custom column name': 'Custom column name',
|
||||
'Edit description': 'Edit description',
|
||||
'Required': 'Required',
|
||||
'Label field': 'Label field',
|
||||
'Default is the ID field': 'Default is the ID field',
|
||||
'Set default sorting rules': 'Set default sorting rules',
|
||||
|
||||
'is before': 'is before',
|
||||
'is after': 'is after',
|
||||
'is on or after': 'is on or after',
|
||||
'is on or before': 'is on or before',
|
||||
|
||||
'Upload': 'Upload',
|
||||
|
||||
'Select level': 'Select level',
|
||||
'Province': 'Province',
|
||||
'City': 'City',
|
||||
'Area': 'Area',
|
||||
'Street': 'Street',
|
||||
'Village': 'Village',
|
||||
'Must select to the last level': 'Must select to the last level',
|
||||
|
||||
'Move {{title}} to': 'Move {{title}} to',
|
||||
'Target position': 'Target position',
|
||||
'After': 'After',
|
||||
'Before': 'Before',
|
||||
|
||||
'Add {{type}} before "{{title}}"': 'Add {{type}} before "{{title}}"',
|
||||
'Add {{type}} after "{{title}}"': 'Add {{type}} after "{{title}}"',
|
||||
'Add {{type}} in "{{title}}"': 'Add {{type}} in "{{title}}"',
|
||||
|
||||
'Original name': 'Original name',
|
||||
'Custom name': 'Custom name',
|
||||
|
||||
'Options': 'Options',
|
||||
'Option value': 'Option value',
|
||||
'Option label': 'Option label',
|
||||
'Color': 'Color',
|
||||
'Add option': 'Add option',
|
||||
'Related collection': 'Related collection',
|
||||
'Allow linking to multiple records': 'Allow linking to multiple records',
|
||||
'Allow uploading multiple files': 'Allow uploading multiple files',
|
||||
|
||||
'Configure calendar': 'Configure calendar',
|
||||
'Title field': 'Title field',
|
||||
'Start date field': 'Start date field',
|
||||
'End date field': 'End date field',
|
||||
'Navigate': 'Navigate',
|
||||
'Title': 'Title',
|
||||
'Select view': 'View',
|
||||
'Reset': 'Reset',
|
||||
'Export fields': 'Export fields',
|
||||
'Saved successfully': 'Saved successfully',
|
||||
'Templates': 'Templates',
|
||||
'Nickname': 'Nickname',
|
||||
'Sign in': 'Sign in',
|
||||
'Create an account': 'Create an account',
|
||||
'Sign up': 'Sign up',
|
||||
'Confirm password': 'Confirm password',
|
||||
'Log in with an existing account': 'Log in with an existing account',
|
||||
'Password mismatch': 'Password mismatch',
|
||||
'Signed up successfully. It will jump to the login page.': 'Signed up successfully. It will jump to the login page.',
|
||||
|
||||
'Users': 'Users',
|
||||
'Roles': 'Roles',
|
||||
'Add role': 'Add role',
|
||||
'Role name': 'Role name',
|
||||
'Configure': 'Configure',
|
||||
'Configure permissions': 'Configure permissions',
|
||||
'Edit role': 'Edit role',
|
||||
|
||||
'Action permissions': 'Action permissions',
|
||||
'Menu permissions': 'Menu permissions',
|
||||
|
||||
'Menu item name': 'Menu item name',
|
||||
'Allow access': 'Allow access',
|
||||
|
||||
'Action name': 'Action name',
|
||||
'Allow action': 'Allow action',
|
||||
'Action scope': 'Action scope',
|
||||
'Operate on new data': 'Operate on new data',
|
||||
'Operate on existing data': 'Operate on existing data',
|
||||
|
||||
'Yes': 'Yes',
|
||||
'No': 'No',
|
||||
|
||||
'Red': 'Red',
|
||||
'Magenta': 'Magenta',
|
||||
'Volcano': 'Volcano',
|
||||
'Orange': 'Orange',
|
||||
'Gold': 'Gold',
|
||||
'Lime': 'Lime',
|
||||
'Green': 'Green',
|
||||
'Cyan': 'Cyan',
|
||||
'Blue': 'Blue',
|
||||
'Geek Blue': 'Geek Blue',
|
||||
'Purple': 'Purple',
|
||||
'Default': 'Default',
|
||||
'Add card': 'Add card',
|
||||
};
|
||||
|
@ -1 +1,274 @@
|
||||
export default {};
|
||||
export default {
|
||||
'Display <1><0>10</0><1>20</1><2>50</2><3>100</3></1> items per page': '每页显示 <1><0>10</0><1>20</1><2>50</2><3>100</3></1> 条',
|
||||
'Meet <1><0>All</0><1>Any</1></1> conditions in the group': '满足组内 <1><0>全部</0><1>任意</1></1> 条件',
|
||||
'Open in<1><0>Modal</0><1>Drawer</1><2>Window</2></1>': '在 <1><0>对话框</0><1>抽屉</1><2>窗口</2></1> 内打开',
|
||||
'{{count}} filter items': '{{count}} 个筛选项',
|
||||
'{{count}} more items': '还有 {{count}} 项',
|
||||
|
||||
'Today': '今天',
|
||||
'Month': '月',
|
||||
'Week': '周',
|
||||
'Work week': '工作日',
|
||||
'Day': '天',
|
||||
'Agenda': '列表',
|
||||
'Date': '日期',
|
||||
'Time': '时间',
|
||||
'Event': '事件',
|
||||
'None': '无',
|
||||
'System settings': '系统设置',
|
||||
'System title': '系统名称',
|
||||
'Logo': 'Logo',
|
||||
'Add menu item': '添加菜单项',
|
||||
'Page': '页面',
|
||||
'Name': '名称',
|
||||
'Icon': '图标',
|
||||
'Group': '分组',
|
||||
'Link': '链接',
|
||||
'Edit menu item': '编辑菜单项',
|
||||
'Move to': '移动到',
|
||||
'Insert left': '在左边插入',
|
||||
'Insert right': '在右边插入',
|
||||
'Insert inner': '在里面插入',
|
||||
'Delete': '删除',
|
||||
'UI editor': '界面配置',
|
||||
'Collections & Fields': '数据表配置',
|
||||
'Roles & Permissions': '角色和权限',
|
||||
'Edit profile': '个人资料',
|
||||
'Switch role': '切换角色',
|
||||
'Super admin': '超级管理员',
|
||||
'Language': '语言设置',
|
||||
'Sign out': '注销',
|
||||
'Cancel': '取消',
|
||||
'Submit': '提交',
|
||||
'Set the data scope': '设置数据范围',
|
||||
'Data blocks': '数据区块',
|
||||
'Table': '表格',
|
||||
'Form': '表单',
|
||||
'Select data source': '选择数据源',
|
||||
'Calendar': '日历',
|
||||
'Kanban': '看板',
|
||||
'Select group field': '选择分组字段',
|
||||
'Media': '多媒体',
|
||||
'Markdown': 'Markdown',
|
||||
'Wysiwyg': '富文本',
|
||||
'Charts': '图表',
|
||||
'Column chart': '柱状图',
|
||||
'Bar chart': '条形图',
|
||||
'Line chart': '折线图',
|
||||
'Pie chart': '饼图',
|
||||
'Templates': '模板',
|
||||
'Select template': '选择模板',
|
||||
'Action logs': '操作日志',
|
||||
'Create template': '创建模板',
|
||||
'Edit markdown': '编辑 Markdown',
|
||||
'Add block': '创建区块',
|
||||
'Add new': '添加',
|
||||
'Add record': '添加数据',
|
||||
'Custom field display name': '自定义字段名称',
|
||||
'Display fields': '显示字段',
|
||||
'Edit record': '编辑数据',
|
||||
'Delete menu item': '删除菜单项',
|
||||
'Add page': '添加页面',
|
||||
'Add group': '添加分组',
|
||||
'Add link': '添加链接',
|
||||
'Insert above': '在上面插入',
|
||||
'Insert below': '在下面插入',
|
||||
'Save': '保存',
|
||||
'Delete block': '删除区块',
|
||||
'Are you sure you want to delete it?': '你确定要删除吗?',
|
||||
'This is a demo text, **supports Markdown syntax**.': '这是一段演示文本,**支持 Markdown 语法**。',
|
||||
|
||||
'Filter': '筛选',
|
||||
'Action type': '操作类型',
|
||||
'Actions': '操作',
|
||||
'Insert': '新增',
|
||||
'Update': '更新',
|
||||
'View': '查看',
|
||||
'View record': '查看数据',
|
||||
|
||||
'Data changes': '数据变更',
|
||||
'Field name': '字段标识',
|
||||
'Before change': '变更前',
|
||||
'After change': '变更后',
|
||||
|
||||
'Delete record': '删除数据',
|
||||
'Create collection': '创建数据表',
|
||||
'Collection display name': '数据表名称',
|
||||
'Collection name': '数据表标识',
|
||||
'Randomly generated and can be modified. Support letters, numbers and underscores, must start with a letter.': '随机生成,可修改。支持英文、数字和下划线,必须以英文字母开头。',
|
||||
'Storage type': '存储类型',
|
||||
'Edit': '编辑',
|
||||
'Edit collection': '编辑数据表',
|
||||
'Configure fields': '配置字段',
|
||||
'Edit field': '编辑字段',
|
||||
'Configure fields of {{title}}': '「{{title}}」的字段配置',
|
||||
'Basic': '基本类型',
|
||||
'Single line text': '单行文本',
|
||||
'Long text': '多行文本',
|
||||
'Phone': '手机号码',
|
||||
'Email': '电子邮箱',
|
||||
'Number': '数字',
|
||||
'Percent': '百分比',
|
||||
'Password': '密码',
|
||||
'Choices': '选择类型',
|
||||
'Checkbox': '勾选',
|
||||
'Single select': '下拉菜单(单选)',
|
||||
'Multiple select': '下拉菜单(多选)',
|
||||
'Radio group': '单选框',
|
||||
'Checkbox group': '复选框',
|
||||
'China region': '中国行政区',
|
||||
'Attachment': '附件',
|
||||
'Date & Time': '日期 & 时间',
|
||||
'Datetime': '日期',
|
||||
'Relation': '关系类型',
|
||||
'Link to': '关联',
|
||||
'Sub-table': '子表格',
|
||||
'System info': '系统信息',
|
||||
'Created at': '创建日期',
|
||||
'Last updated at': '最后修改日期',
|
||||
'Created by': '创建人',
|
||||
'Last updated by': '最后更新日期',
|
||||
'Add field': '添加字段',
|
||||
'Field display name': '字段名称',
|
||||
'Field type': '字段类型',
|
||||
|
||||
'Date format': '日期格式',
|
||||
'Year/Month/Day': '年/月/日',
|
||||
'Year-Month-Day': '年-月-日',
|
||||
'Day/Month/Year': '日/月/年',
|
||||
'Show time': '显示时间',
|
||||
'Time format': '时间格式',
|
||||
'12 hour': '12 小时制',
|
||||
'24 hour': '24 小时制',
|
||||
|
||||
'Add filter': '添加筛选条件',
|
||||
'Add filter group': '添加筛选分组',
|
||||
'is': '等于',
|
||||
'is not': '不等于',
|
||||
'contains': '包含',
|
||||
'does not contain': '不包含',
|
||||
'is empty': '为空',
|
||||
'is not empty': '不为空',
|
||||
'Edit chart': '编辑图表',
|
||||
'Add text': '添加文本',
|
||||
'Filterable fields': '可筛选字段',
|
||||
'Edit button': '编辑按钮',
|
||||
'Hide': '隐藏',
|
||||
'Enable actions': '启用操作',
|
||||
'Export': '导出',
|
||||
'Customize': '自定义',
|
||||
'Function': 'Function',
|
||||
'Popup form': 'Popup form',
|
||||
'Flexible popup': 'Flexible popup',
|
||||
'Configure actions': '配置操作',
|
||||
'Display order number': '显示序号',
|
||||
'Enable drag and drop sorting': '启用拖拽排序',
|
||||
'Trigger on click the table row': '点击表格行时触发',
|
||||
'Add tab': '添加标签页',
|
||||
'Disable tabs': '禁用标签页',
|
||||
'Details': '详情',
|
||||
'Edit tab': '编辑标签页',
|
||||
'Relationship blocks': '关系数据区块',
|
||||
'Select record': '选择数据',
|
||||
'Display name': 'Display name',
|
||||
'Select icon': '选择图标',
|
||||
'Custom column name': '自定义列名称',
|
||||
'Edit description': '编辑描述',
|
||||
'Required': '必填',
|
||||
'Label field': '标签字段',
|
||||
'Default is the ID field': '默认为 ID 字段',
|
||||
'Set default sorting rules': '设置排序规则',
|
||||
|
||||
'is before': '早于',
|
||||
'is after': '晚于',
|
||||
'is on or after': '不早于',
|
||||
'is on or before': '不晚于',
|
||||
|
||||
'Upload': '上传',
|
||||
|
||||
'Select level': '选择层级',
|
||||
'Province': '省',
|
||||
'City': '市',
|
||||
'Area': '区/县',
|
||||
'Street': '乡镇/街道',
|
||||
'Village': '村/居委会',
|
||||
'Must select to the last level': '必须选到最后一级',
|
||||
|
||||
'Move {{title}} to': '将 {{title}} 移动到',
|
||||
'Target position': '目标位置',
|
||||
'After': '之后',
|
||||
'Before': '之前',
|
||||
|
||||
'Add {{type}} before "{{title}}"': '在 "{{title}}" 前插入{{type}}',
|
||||
'Add {{type}} after "{{title}}"': '在 "{{title}}" 前插入{{type}}',
|
||||
'Add {{type}} in "{{title}}"': '在 "{{title}}" 里插入{{type}}',
|
||||
|
||||
'Original name': '原名称',
|
||||
'Custom name': '自定义名称',
|
||||
|
||||
'Options': '选项',
|
||||
'Option value': '选项值',
|
||||
'Option label': '选项',
|
||||
'Color': '颜色',
|
||||
'Add option': '添加选项',
|
||||
'Related collection': '关系表',
|
||||
'Allow linking to multiple records': '允许关联多条记录',
|
||||
'Allow uploading multiple files': '允许上传多个文件',
|
||||
|
||||
'Configure calendar': '配置日历',
|
||||
'Title field': '标题字段',
|
||||
'Start date field': '开始日期字段',
|
||||
'End date field': '结束日期字段',
|
||||
'Navigate': '分页',
|
||||
'Title': '标题',
|
||||
'Select view': '切换视图',
|
||||
'Reset': '重置',
|
||||
'Export fields': '导出字段',
|
||||
'Saved successfully': '保存成功',
|
||||
'Nickname': '昵称',
|
||||
'Sign in': '登录',
|
||||
'Create an account': '注册账号',
|
||||
'Sign up': '注册',
|
||||
'Confirm password': '确认密码',
|
||||
'Log in with an existing account': '使用已有账号登录',
|
||||
'Signed up successfully. It will jump to the login page.': '注册成功,将跳转登录页。',
|
||||
'Password mismatch': '确认密码不匹配',
|
||||
'Users': '用户',
|
||||
|
||||
'Roles': '角色',
|
||||
'Add role': '添加角色',
|
||||
'Role name': '角色名称',
|
||||
'Configure': '配置',
|
||||
'Configure permissions': '配置权限',
|
||||
'Edit role': '编辑角色',
|
||||
|
||||
'Action permissions': '数据表操作权限',
|
||||
'Menu permissions': '菜单访问权限',
|
||||
|
||||
'Menu item name': '菜单名称',
|
||||
'Allow access': '允许访问',
|
||||
|
||||
'Action name': '操作名称',
|
||||
'Allow action': '允许操作',
|
||||
'Action scope': '可操作数据范围',
|
||||
'Operate on new data': '对新增数据操作',
|
||||
'Operate on existing data': '对已有数据操作',
|
||||
|
||||
'Yes': '是',
|
||||
'No': '否',
|
||||
|
||||
'Red': '薄暮',
|
||||
'Magenta': '法式洋红',
|
||||
'Volcano': '火山',
|
||||
'Orange': '日暮',
|
||||
'Gold': '金盏花',
|
||||
'Lime': '青柠',
|
||||
'Green': '极光绿',
|
||||
'Cyan': '明青',
|
||||
'Blue': '拂晓蓝',
|
||||
'Geek Blue': '极客蓝',
|
||||
'Purple': '酱紫',
|
||||
'Default': '默认',
|
||||
|
||||
'Add card': '添加卡片',
|
||||
};
|
||||
|
@ -15,6 +15,7 @@ import { uid } from '@formily/shared';
|
||||
import { PlusOutlined } from '@ant-design/icons';
|
||||
import { Droppable, SortableItem } from '../../components/Sortable';
|
||||
import { useClient } from '../../constate';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export const ActionBar = observer((props: any) => {
|
||||
const { align = 'top' } = props;
|
||||
@ -117,7 +118,7 @@ function generateActionSchema(type) {
|
||||
const actions: { [key: string]: ISchema } = {
|
||||
update: {
|
||||
type: 'void',
|
||||
title: '编辑',
|
||||
title: "{{ t('Edit') }}",
|
||||
'x-align': 'right',
|
||||
'x-decorator': 'AddNew.Displayed',
|
||||
'x-decorator-props': {
|
||||
@ -132,7 +133,7 @@ function generateActionSchema(type) {
|
||||
properties: {
|
||||
modal: {
|
||||
type: 'void',
|
||||
title: '编辑数据',
|
||||
title: "{{ t('Edit record') }}",
|
||||
'x-decorator': 'Form',
|
||||
'x-decorator-props': {
|
||||
useResource: '{{ Table.useResource }}',
|
||||
@ -156,7 +157,7 @@ function generateActionSchema(type) {
|
||||
},
|
||||
destroy: {
|
||||
type: 'void',
|
||||
title: '删除',
|
||||
title: "{{ t('Delete') }}",
|
||||
'x-align': 'right',
|
||||
'x-decorator': 'AddNew.Displayed',
|
||||
'x-decorator-props': {
|
||||
@ -167,8 +168,8 @@ function generateActionSchema(type) {
|
||||
'x-designable-bar': 'Action.DesignableBar',
|
||||
'x-component-props': {
|
||||
confirm: {
|
||||
title: '删除数据',
|
||||
content: '删除后无法恢复,确定要删除吗?',
|
||||
title: "{{ t('Delete record') }}",
|
||||
content: "{{ t('Are you sure you want to delete it?') }}",
|
||||
},
|
||||
useAction: '{{ Table.useTableDestroyAction }}',
|
||||
},
|
||||
@ -178,6 +179,7 @@ function generateActionSchema(type) {
|
||||
}
|
||||
|
||||
function AddActionButton() {
|
||||
const { t } = useTranslation();
|
||||
const [visible, setVisible] = useState(false);
|
||||
const displayed = useDisplayedMapContext();
|
||||
const { appendChild, remove } = useDesignable();
|
||||
@ -193,10 +195,10 @@ function AddActionButton() {
|
||||
onVisibleChange={setVisible}
|
||||
overlay={
|
||||
<Menu>
|
||||
<Menu.ItemGroup title={'启用操作'}>
|
||||
<Menu.ItemGroup title={t('Enable actions')}>
|
||||
{[
|
||||
{ title: '编辑', name: 'update' },
|
||||
{ title: '删除', name: 'destroy' },
|
||||
{ title: t('Edit'), name: 'update' },
|
||||
{ title: t('Delete'), name: 'destroy' },
|
||||
].map((item) => (
|
||||
<SwitchMenuItem
|
||||
key={item.name}
|
||||
@ -219,10 +221,10 @@ function AddActionButton() {
|
||||
))}
|
||||
</Menu.ItemGroup>
|
||||
<Menu.Divider />
|
||||
<Menu.SubMenu disabled title={'自定义'}>
|
||||
<Menu.Item style={{ minWidth: 120 }}>函数操作</Menu.Item>
|
||||
<Menu.Item>弹窗表单</Menu.Item>
|
||||
<Menu.Item>复杂弹窗</Menu.Item>
|
||||
<Menu.SubMenu disabled title={t('Customize')}>
|
||||
<Menu.Item style={{ minWidth: 120 }}>{t('Function')}</Menu.Item>
|
||||
<Menu.Item>{t('Popup form')}</Menu.Item>
|
||||
<Menu.Item>{t('Flexible popup')}</Menu.Item>
|
||||
</Menu.SubMenu>
|
||||
</Menu>
|
||||
}
|
||||
@ -233,7 +235,7 @@ function AddActionButton() {
|
||||
type={'dashed'}
|
||||
icon={<PlusOutlined />}
|
||||
>
|
||||
配置操作
|
||||
{t('Configure actions')}
|
||||
</Button>
|
||||
</Dropdown>
|
||||
);
|
||||
|
@ -47,12 +47,16 @@ import { createPortal } from 'react-dom';
|
||||
import { ActionBar } from './ActionBar';
|
||||
import { DragHandle, SortableItem } from '../../components/Sortable';
|
||||
import { useDisplayedMapContext } from '../../constate';
|
||||
import { Trans, useTranslation } from 'react-i18next';
|
||||
import { useCompile } from '../../hooks/useCompile';
|
||||
|
||||
export const ButtonComponentContext = createContext(null);
|
||||
|
||||
function getTooltipProps(tooltip) {
|
||||
const { t } = useTranslation();
|
||||
const compile = useCompile();
|
||||
if (typeof tooltip === 'string') {
|
||||
return { title: tooltip };
|
||||
return { title: compile(tooltip) };
|
||||
}
|
||||
return tooltip;
|
||||
}
|
||||
@ -65,6 +69,8 @@ export const Action: any = observer((props: any) => {
|
||||
icon,
|
||||
...others
|
||||
} = props;
|
||||
const { t } = useTranslation();
|
||||
const compile = useCompile();
|
||||
const { run } = useAction();
|
||||
const field = useField();
|
||||
const { schema, DesignableBar } = useDesignable();
|
||||
@ -91,10 +97,11 @@ export const Action: any = observer((props: any) => {
|
||||
}
|
||||
}}
|
||||
>
|
||||
{schema.title}
|
||||
{compile(schema.title)}
|
||||
<DesignableBar path={getSchemaPath(schema)} />
|
||||
</Button>
|
||||
);
|
||||
console.log('tooltip', tooltip);
|
||||
if (tooltip) {
|
||||
button = <Tooltip {...getTooltipProps(tooltip)}>{button}</Tooltip>;
|
||||
}
|
||||
@ -110,14 +117,16 @@ export const Action: any = observer((props: any) => {
|
||||
|
||||
Action.Link = observer((props: any) => {
|
||||
const { schema } = useDesignable();
|
||||
return <Link {...props}>{schema.title}</Link>;
|
||||
const compile = useCompile();
|
||||
return <Link {...props}>{compile(schema.title)}</Link>;
|
||||
});
|
||||
|
||||
Action.URL = observer((props: any) => {
|
||||
const { schema } = useDesignable();
|
||||
const compile = useCompile();
|
||||
return (
|
||||
<a target={'_blank'} {...props}>
|
||||
{schema.title}
|
||||
{compile(schema.title)}
|
||||
</a>
|
||||
);
|
||||
});
|
||||
@ -188,6 +197,8 @@ Action.Group = observer((props: any) => {
|
||||
});
|
||||
|
||||
Action.Modal = observer((props: any) => {
|
||||
const { t } = useTranslation();
|
||||
const compile = useCompile();
|
||||
const {
|
||||
useOkAction = useDefaultAction,
|
||||
useCancelAction = useDefaultAction,
|
||||
@ -203,7 +214,7 @@ Action.Modal = observer((props: any) => {
|
||||
console.log('Action.Modal.field', schema['x-read-pretty']);
|
||||
return (
|
||||
<Modal
|
||||
title={schema.title}
|
||||
title={compile(schema.title)}
|
||||
destroyOnClose
|
||||
maskClosable
|
||||
width={'50%'}
|
||||
@ -222,7 +233,7 @@ Action.Modal = observer((props: any) => {
|
||||
}
|
||||
}}
|
||||
>
|
||||
取消
|
||||
{t('Cancel')}
|
||||
</Button>,
|
||||
<Button
|
||||
type={'primary'}
|
||||
@ -237,7 +248,7 @@ Action.Modal = observer((props: any) => {
|
||||
}
|
||||
}}
|
||||
>
|
||||
确定
|
||||
{t('Submit')}
|
||||
</Button>,
|
||||
]
|
||||
: null
|
||||
@ -261,6 +272,8 @@ Action.Modal = observer((props: any) => {
|
||||
});
|
||||
|
||||
Action.Drawer = observer((props: any) => {
|
||||
const { t } = useTranslation();
|
||||
const compile = useCompile();
|
||||
const {
|
||||
useOkAction = useDefaultAction,
|
||||
useCancelAction = useDefaultAction,
|
||||
@ -278,7 +291,7 @@ Action.Drawer = observer((props: any) => {
|
||||
{createPortal(
|
||||
<Drawer
|
||||
width={'50%'}
|
||||
title={schema.title}
|
||||
title={compile(schema.title)}
|
||||
maskClosable
|
||||
destroyOnClose
|
||||
footer={
|
||||
@ -296,7 +309,7 @@ Action.Drawer = observer((props: any) => {
|
||||
}
|
||||
}}
|
||||
>
|
||||
取消
|
||||
{t('Cancel')}
|
||||
</Button>
|
||||
<Button
|
||||
onClick={async (e) => {
|
||||
@ -310,7 +323,7 @@ Action.Drawer = observer((props: any) => {
|
||||
}}
|
||||
type={'primary'}
|
||||
>
|
||||
确定
|
||||
{t('Submit')}
|
||||
</Button>
|
||||
</Space>
|
||||
)
|
||||
@ -394,6 +407,8 @@ Action.Dropdown = observer((props: any) => {
|
||||
});
|
||||
|
||||
Action.Popover = observer((props) => {
|
||||
const { t } = useTranslation();
|
||||
const compile = useCompile();
|
||||
const { schema } = useDesignable();
|
||||
const form = useForm();
|
||||
const isFormDecorator = schema['x-decorator'] === 'Form';
|
||||
@ -405,7 +420,7 @@ Action.Popover = observer((props) => {
|
||||
trigger={['click']}
|
||||
onVisibleChange={setVisible}
|
||||
{...props}
|
||||
title={schema.title}
|
||||
title={compile(schema.title)}
|
||||
content={
|
||||
<div>
|
||||
{props.children}
|
||||
@ -418,7 +433,7 @@ Action.Popover = observer((props) => {
|
||||
setVisible(false);
|
||||
}}
|
||||
>
|
||||
Cancel
|
||||
{t('Cancel')}
|
||||
</Button>
|
||||
<Button
|
||||
type={'primary'}
|
||||
@ -427,7 +442,7 @@ Action.Popover = observer((props) => {
|
||||
setVisible(false);
|
||||
}}
|
||||
>
|
||||
Ok
|
||||
{t('Submit')}
|
||||
</Button>
|
||||
</Space>
|
||||
</div>
|
||||
@ -441,6 +456,7 @@ Action.Popover = observer((props) => {
|
||||
});
|
||||
|
||||
Action.DesignableBar = (props: any) => {
|
||||
const { t } = useTranslation();
|
||||
const { schema, remove, refresh, insertAfter } = useDesignable();
|
||||
const [visible, setVisible] = useState(false);
|
||||
const isPopup = Object.keys(schema.properties || {}).length > 0;
|
||||
@ -466,7 +482,7 @@ Action.DesignableBar = (props: any) => {
|
||||
<Menu>
|
||||
<Menu.Item
|
||||
onClick={async (e) => {
|
||||
const values = await FormDialog('编辑按钮', () => {
|
||||
const values = await FormDialog(t('Edit button'), () => {
|
||||
return (
|
||||
<FormLayout layout={'vertical'}>
|
||||
<SchemaField
|
||||
@ -475,14 +491,14 @@ Action.DesignableBar = (props: any) => {
|
||||
properties: {
|
||||
title: {
|
||||
type: 'string',
|
||||
title: '按钮名称',
|
||||
title: t('Display name'),
|
||||
required: true,
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input',
|
||||
},
|
||||
icon: {
|
||||
type: 'string',
|
||||
title: '按钮图标',
|
||||
title: t('Icon'),
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'IconPicker',
|
||||
},
|
||||
@ -505,11 +521,12 @@ Action.DesignableBar = (props: any) => {
|
||||
refresh();
|
||||
}}
|
||||
>
|
||||
编辑按钮
|
||||
{t('Edit button')}
|
||||
</Menu.Item>
|
||||
{isPopup && (
|
||||
<Menu.Item>
|
||||
在{' '}
|
||||
<Trans>
|
||||
Open in
|
||||
<Select
|
||||
bordered={false}
|
||||
size={'small'}
|
||||
@ -522,16 +539,16 @@ Action.DesignableBar = (props: any) => {
|
||||
}}
|
||||
>
|
||||
<Select.Option value={'Action.Modal'}>
|
||||
对话框
|
||||
Modal
|
||||
</Select.Option>
|
||||
<Select.Option value={'Action.Drawer'}>
|
||||
抽屉
|
||||
Drawer
|
||||
</Select.Option>
|
||||
<Select.Option value={'Action.Window'}>
|
||||
浏览器窗口
|
||||
Window
|
||||
</Select.Option>
|
||||
</Select>{' '}
|
||||
内打开
|
||||
</Select>
|
||||
</Trans>
|
||||
</Menu.Item>
|
||||
)}
|
||||
<Menu.Divider />
|
||||
@ -547,7 +564,7 @@ Action.DesignableBar = (props: any) => {
|
||||
setVisible(false);
|
||||
}}
|
||||
>
|
||||
隐藏
|
||||
{t('Hide')}
|
||||
</Menu.Item>
|
||||
</Menu>
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
export const columnChartConfig = {
|
||||
'zh-CN': {
|
||||
data: [
|
||||
{
|
||||
type: '家具家电',
|
||||
@ -52,57 +53,66 @@ export const columnChartConfig = {
|
||||
type: { alias: '类别' },
|
||||
sales: { alias: '销售额' },
|
||||
},
|
||||
};
|
||||
|
||||
var data = [
|
||||
},
|
||||
'en-US': {
|
||||
data: [
|
||||
{
|
||||
type: '家具家电',
|
||||
type: 'Furniture & Appliances',
|
||||
sales: 38,
|
||||
},
|
||||
{
|
||||
type: '粮油副食',
|
||||
type: 'Food, oil and food',
|
||||
sales: 52,
|
||||
},
|
||||
{
|
||||
type: '生鲜水果',
|
||||
type: 'Fresh fruit',
|
||||
sales: 61,
|
||||
},
|
||||
{
|
||||
type: '美容洗护',
|
||||
type: 'Beauty care',
|
||||
sales: 145,
|
||||
},
|
||||
{
|
||||
type: '母婴用品',
|
||||
type: 'Mother & Baby',
|
||||
sales: 48,
|
||||
},
|
||||
{
|
||||
type: '进口食品',
|
||||
type: 'Imported food',
|
||||
sales: 38,
|
||||
},
|
||||
{
|
||||
type: '食品饮料',
|
||||
type: 'Food & Beverage',
|
||||
sales: 38,
|
||||
},
|
||||
{
|
||||
type: '家庭清洁',
|
||||
type: 'Household cleaning',
|
||||
sales: 38,
|
||||
},
|
||||
];
|
||||
var config = {
|
||||
data: data,
|
||||
xField: 'sales',
|
||||
yField: 'type',
|
||||
legend: { position: 'top-left' },
|
||||
barBackground: { style: { fill: 'rgba(0,0,0,0.1)' } },
|
||||
interactions: [
|
||||
{
|
||||
type: 'active-region',
|
||||
enable: false,
|
||||
},
|
||||
],
|
||||
xField: 'type',
|
||||
yField: 'sales',
|
||||
label: {
|
||||
position: 'middle',
|
||||
style: {
|
||||
fill: '#FFFFFF',
|
||||
opacity: 0.6,
|
||||
},
|
||||
},
|
||||
xAxis: {
|
||||
label: {
|
||||
autoHide: true,
|
||||
autoRotate: false,
|
||||
},
|
||||
},
|
||||
meta: {
|
||||
type: { alias: 'Category' },
|
||||
sales: { alias: 'Sales' },
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const barChartConfig = {
|
||||
'zh-CN': {
|
||||
data: [
|
||||
{
|
||||
type: '家具家电',
|
||||
@ -147,4 +157,51 @@ export const barChartConfig = {
|
||||
enable: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
'en-US': {
|
||||
data: [
|
||||
{
|
||||
type: 'Furniture & Appliances',
|
||||
sales: 38,
|
||||
},
|
||||
{
|
||||
type: 'Food, oil and food',
|
||||
sales: 52,
|
||||
},
|
||||
{
|
||||
type: 'Fresh fruit',
|
||||
sales: 61,
|
||||
},
|
||||
{
|
||||
type: 'Beauty care',
|
||||
sales: 145,
|
||||
},
|
||||
{
|
||||
type: 'Mother & Baby',
|
||||
sales: 48,
|
||||
},
|
||||
{
|
||||
type: 'Imported food',
|
||||
sales: 38,
|
||||
},
|
||||
{
|
||||
type: 'Food & Beverage',
|
||||
sales: 38,
|
||||
},
|
||||
{
|
||||
type: 'Household cleaning',
|
||||
sales: 38,
|
||||
},
|
||||
],
|
||||
xField: 'sales',
|
||||
yField: 'type',
|
||||
legend: { position: 'top-left' },
|
||||
barBackground: { style: { fill: 'rgba(0,0,0,0.1)' } },
|
||||
interactions: [
|
||||
{
|
||||
type: 'active-region',
|
||||
enable: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
@ -70,6 +70,9 @@ import {
|
||||
} from '../../constate';
|
||||
import SwitchMenuItem from '../../components/SwitchMenuItem';
|
||||
import { BlockSchemaContext } from '../../context';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { i18n } from '../../i18n';
|
||||
import { useCompile } from '../../hooks/useCompile';
|
||||
|
||||
const generateGridBlock = (schema: ISchema) => {
|
||||
const name = schema.name || uid();
|
||||
@ -112,7 +115,7 @@ function generateCardItemSchema(component) {
|
||||
const defaults: { [key: string]: ISchema } = {
|
||||
'Markdown.Void': {
|
||||
type: 'void',
|
||||
default: '这是一段演示文字,**支持使用 Markdown 语法**',
|
||||
default: i18n.t('This is a demo text, **supports Markdown syntax**.'),
|
||||
'x-designable-bar': 'Markdown.Void.DesignableBar',
|
||||
'x-decorator': 'CardItem',
|
||||
'x-read-pretty': true,
|
||||
@ -141,7 +144,7 @@ function generateCardItemSchema(component) {
|
||||
properties: {
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
title: '筛选',
|
||||
title: "{{t('Filter')}}",
|
||||
'x-decorator': 'AddNew.Displayed',
|
||||
'x-decorator-props': {
|
||||
displayName: 'filter',
|
||||
@ -156,7 +159,7 @@ function generateCardItemSchema(component) {
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
name: 'action1',
|
||||
title: '删除',
|
||||
title: "{{t('Delete')}}",
|
||||
'x-align': 'right',
|
||||
'x-decorator': 'AddNew.Displayed',
|
||||
'x-decorator-props': {
|
||||
@ -167,8 +170,8 @@ function generateCardItemSchema(component) {
|
||||
'x-component-props': {
|
||||
icon: 'DeleteOutlined',
|
||||
confirm: {
|
||||
title: '删除数据',
|
||||
content: '删除后无法恢复,确定要删除吗?',
|
||||
title: "{{t('Delete record')}}",
|
||||
content: "{{t('Are you sure you want to delete it?')}}",
|
||||
},
|
||||
useAction: '{{ Table.useTableDestroyAction }}',
|
||||
},
|
||||
@ -176,7 +179,7 @@ function generateCardItemSchema(component) {
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
name: 'action1',
|
||||
title: '添加',
|
||||
title: "{{t('Add new')}}",
|
||||
'x-align': 'right',
|
||||
'x-decorator': 'AddNew.Displayed',
|
||||
'x-decorator-props': {
|
||||
@ -191,7 +194,7 @@ function generateCardItemSchema(component) {
|
||||
properties: {
|
||||
modal: {
|
||||
type: 'void',
|
||||
title: '添加数据',
|
||||
title: "{{t('Add record')}}",
|
||||
'x-decorator': 'Form',
|
||||
'x-component': 'Action.Drawer',
|
||||
'x-component-props': {
|
||||
@ -213,7 +216,7 @@ function generateCardItemSchema(component) {
|
||||
},
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
title: '操作',
|
||||
title: '{{t("Actions")}}',
|
||||
'x-component': 'Table.Column',
|
||||
'x-component-props': {},
|
||||
'x-designable-bar': 'Table.Operation.DesignableBar',
|
||||
@ -228,7 +231,7 @@ function generateCardItemSchema(component) {
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
name: 'action1',
|
||||
title: '查看',
|
||||
title: "{{t('View')}}",
|
||||
'x-component': 'Action',
|
||||
'x-component-props': {
|
||||
type: 'link',
|
||||
@ -238,7 +241,7 @@ function generateCardItemSchema(component) {
|
||||
properties: {
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
title: '查看数据',
|
||||
title: "{{t('View record')}}",
|
||||
'x-component': 'Action.Drawer',
|
||||
'x-component-props': {
|
||||
bodyStyle: {
|
||||
@ -254,7 +257,7 @@ function generateCardItemSchema(component) {
|
||||
properties: {
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
title: '详情',
|
||||
title: "{{t('Details')}}",
|
||||
'x-designable-bar': 'Tabs.TabPane.DesignableBar',
|
||||
'x-component': 'Tabs.TabPane',
|
||||
'x-component-props': {},
|
||||
@ -276,7 +279,7 @@ function generateCardItemSchema(component) {
|
||||
},
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
title: '编辑',
|
||||
title: "{{t('Edit')}}",
|
||||
'x-component': 'Action',
|
||||
'x-component-props': {
|
||||
type: 'link',
|
||||
@ -286,7 +289,7 @@ function generateCardItemSchema(component) {
|
||||
properties: {
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
title: '编辑数据',
|
||||
title: "{{t('Edit record')}}",
|
||||
'x-decorator': 'Form',
|
||||
'x-decorator-props': {
|
||||
useResource: '{{ Table.useResource }}',
|
||||
@ -378,7 +381,7 @@ function generateCardItemSchema(component) {
|
||||
properties: {
|
||||
create: {
|
||||
type: 'void',
|
||||
title: '添加卡片',
|
||||
title: "{{t('Add card')}}",
|
||||
// 'x-designable-bar': 'Kanban.AddCardDesignableBar',
|
||||
'x-component': 'Kanban.Card.AddNew',
|
||||
// 'x-decorator': 'AddNew.Displayed',
|
||||
@ -389,7 +392,7 @@ function generateCardItemSchema(component) {
|
||||
properties: {
|
||||
modal: {
|
||||
type: 'void',
|
||||
title: '添加数据',
|
||||
title: "{{t('Add record')}}",
|
||||
'x-decorator': 'Form',
|
||||
'x-decorator-props': {
|
||||
useResource: '{{ Kanban.useCreateResource }}',
|
||||
@ -424,7 +427,7 @@ function generateCardItemSchema(component) {
|
||||
},
|
||||
view1: {
|
||||
type: 'void',
|
||||
title: '编辑数据',
|
||||
title: "{{t('Edit record')}}",
|
||||
'x-decorator': 'Form',
|
||||
'x-component': 'Kanban.Card.View',
|
||||
'x-component-props': {
|
||||
@ -459,7 +462,7 @@ function generateCardItemSchema(component) {
|
||||
properties: {
|
||||
today: {
|
||||
type: 'void',
|
||||
title: '今天',
|
||||
title: "{{t('Today')}}",
|
||||
'x-designable-bar': 'Calendar.ActionDesignableBar',
|
||||
'x-component': 'Calendar.Today',
|
||||
'x-align': 'left',
|
||||
@ -470,7 +473,7 @@ function generateCardItemSchema(component) {
|
||||
},
|
||||
nav: {
|
||||
type: 'void',
|
||||
title: '翻页',
|
||||
title: "{{t('Navigate')}}",
|
||||
'x-designable-bar': 'Calendar.ActionDesignableBar',
|
||||
'x-component': 'Calendar.Nav',
|
||||
'x-align': 'left',
|
||||
@ -481,7 +484,7 @@ function generateCardItemSchema(component) {
|
||||
},
|
||||
title: {
|
||||
type: 'void',
|
||||
title: '标题',
|
||||
title: "{{t('Title')}}",
|
||||
'x-designable-bar': 'Calendar.ActionDesignableBar',
|
||||
'x-component': 'Calendar.Title',
|
||||
'x-align': 'left',
|
||||
@ -492,7 +495,7 @@ function generateCardItemSchema(component) {
|
||||
},
|
||||
viewSelect: {
|
||||
type: 'void',
|
||||
title: '视图切换',
|
||||
title: "{{t('Select view')}}",
|
||||
'x-designable-bar': 'Calendar.ActionDesignableBar',
|
||||
'x-component': 'Calendar.ViewSelect',
|
||||
'x-align': 'right',
|
||||
@ -503,7 +506,7 @@ function generateCardItemSchema(component) {
|
||||
},
|
||||
filter: {
|
||||
type: 'void',
|
||||
title: '筛选',
|
||||
title: "{{t('Filter')}}",
|
||||
'x-align': 'right',
|
||||
'x-designable-bar': 'Calendar.Filter.DesignableBar',
|
||||
'x-component': 'Calendar.Filter',
|
||||
@ -514,7 +517,7 @@ function generateCardItemSchema(component) {
|
||||
},
|
||||
create: {
|
||||
type: 'void',
|
||||
title: '添加',
|
||||
title: "{{t('Add new')}}",
|
||||
'x-align': 'right',
|
||||
'x-designable-bar': 'Calendar.ActionDesignableBar',
|
||||
'x-component': 'Action',
|
||||
@ -529,7 +532,7 @@ function generateCardItemSchema(component) {
|
||||
properties: {
|
||||
modal: {
|
||||
type: 'void',
|
||||
title: '添加数据',
|
||||
title: "{{t('Add record')}}",
|
||||
'x-decorator': 'Form',
|
||||
'x-component': 'Action.Drawer',
|
||||
'x-component-props': {
|
||||
@ -560,7 +563,7 @@ function generateCardItemSchema(component) {
|
||||
properties: {
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
title: '详情',
|
||||
title: "{{t('Details')}}",
|
||||
'x-designable-bar': 'Tabs.TabPane.DesignableBar',
|
||||
'x-component': 'Tabs.TabPane',
|
||||
'x-component-props': {},
|
||||
@ -586,7 +589,7 @@ function generateCardItemSchema(component) {
|
||||
'x-component': 'Chart.Column',
|
||||
'x-designable-bar': 'Chart.DesignableBar',
|
||||
'x-component-props': {
|
||||
config: cloneDeep(columnChartConfig),
|
||||
config: cloneDeep(columnChartConfig[i18n.language] || columnChartConfig['en-US']),
|
||||
},
|
||||
},
|
||||
'Chart.Bar': {
|
||||
@ -595,7 +598,7 @@ function generateCardItemSchema(component) {
|
||||
'x-component': 'Chart.Bar',
|
||||
'x-designable-bar': 'Chart.DesignableBar',
|
||||
'x-component-props': {
|
||||
config: cloneDeep(barChartConfig),
|
||||
config: cloneDeep(barChartConfig[i18n.language] || barChartConfig['en-US']),
|
||||
},
|
||||
},
|
||||
'Ref.ActionLogs': {
|
||||
@ -625,7 +628,7 @@ function generateCardItemSchema(component) {
|
||||
properties: {
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
title: '筛选',
|
||||
title: "{{t('Filter')}}",
|
||||
'x-align': 'left',
|
||||
'x-component': 'Table.Filter',
|
||||
'x-component-props': {
|
||||
@ -634,23 +637,23 @@ function generateCardItemSchema(component) {
|
||||
properties: {
|
||||
column1: {
|
||||
type: 'void',
|
||||
title: '操作类型',
|
||||
title: "{{t('Action type')}}",
|
||||
'x-component': 'Filter.Column',
|
||||
'x-component-props': {
|
||||
operations: [
|
||||
{
|
||||
label: '等于',
|
||||
label: "{{ t('is') }}",
|
||||
value: 'eq',
|
||||
selected: true,
|
||||
schema: { 'x-component': 'Select' },
|
||||
},
|
||||
{
|
||||
label: '不等于',
|
||||
label: "{{ t('is not') }}",
|
||||
value: 'ne',
|
||||
schema: { 'x-component': 'Select' },
|
||||
},
|
||||
{
|
||||
label: '包含',
|
||||
label: "{{ t('contains') }}",
|
||||
value: 'in',
|
||||
schema: {
|
||||
'x-component': 'Select',
|
||||
@ -658,15 +661,23 @@ function generateCardItemSchema(component) {
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '不包含',
|
||||
label: "{{ t('does not contain') }}",
|
||||
value: 'notIn',
|
||||
schema: {
|
||||
'x-component': 'Select',
|
||||
'x-component-props': { mode: 'tags' },
|
||||
},
|
||||
},
|
||||
{ label: '非空', value: '$notNull', noValue: true },
|
||||
{ label: '为空', value: '$null', noValue: true },
|
||||
{
|
||||
label: "{{ t('is empty') }}",
|
||||
value: '$null',
|
||||
noValue: true,
|
||||
},
|
||||
{
|
||||
label: "{{ t('is not empty') }}",
|
||||
value: '$notNull',
|
||||
noValue: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
properties: {
|
||||
@ -674,9 +685,21 @@ function generateCardItemSchema(component) {
|
||||
type: 'string',
|
||||
'x-component': 'Select',
|
||||
enum: [
|
||||
{ label: '新增', value: 'create', color: 'green' },
|
||||
{ label: '更新', value: 'update', color: 'blue' },
|
||||
{ label: '删除', value: 'destroy', color: 'red' },
|
||||
{
|
||||
label: "{{ t('Insert') }}",
|
||||
value: 'create',
|
||||
color: 'green',
|
||||
},
|
||||
{
|
||||
label: "{{ t('Update') }}",
|
||||
value: 'update',
|
||||
color: 'blue',
|
||||
},
|
||||
{
|
||||
label: "{{ t('Delete') }}",
|
||||
value: 'destroy',
|
||||
color: 'red',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
@ -687,7 +710,7 @@ function generateCardItemSchema(component) {
|
||||
},
|
||||
column1: {
|
||||
type: 'void',
|
||||
title: '操作时间',
|
||||
title: "{{t('Created at')}}",
|
||||
'x-component': 'Table.Column',
|
||||
properties: {
|
||||
created_at: {
|
||||
@ -702,7 +725,7 @@ function generateCardItemSchema(component) {
|
||||
},
|
||||
column2: {
|
||||
type: 'void',
|
||||
title: '操作用户',
|
||||
title: "{{t('Created by')}}",
|
||||
'x-component': 'Table.Column',
|
||||
properties: {
|
||||
'user.nickname': {
|
||||
@ -714,7 +737,7 @@ function generateCardItemSchema(component) {
|
||||
},
|
||||
column3: {
|
||||
type: 'void',
|
||||
title: '数据表',
|
||||
title: "{{t('Collection display name')}}",
|
||||
'x-component': 'Table.Column',
|
||||
properties: {
|
||||
'collection.title': {
|
||||
@ -726,7 +749,7 @@ function generateCardItemSchema(component) {
|
||||
},
|
||||
column4: {
|
||||
type: 'void',
|
||||
title: '操作类型',
|
||||
title: "{{t('Action type')}}",
|
||||
'x-component': 'Table.Column',
|
||||
properties: {
|
||||
type: {
|
||||
@ -734,16 +757,16 @@ function generateCardItemSchema(component) {
|
||||
'x-component': 'Select',
|
||||
'x-read-pretty': true,
|
||||
enum: [
|
||||
{ label: '新增', value: 'create', color: 'green' },
|
||||
{ label: '更新', value: 'update', color: 'blue' },
|
||||
{ label: '删除', value: 'destroy', color: 'red' },
|
||||
{ label: "{{ t('Insert') }}", value: 'create', color: 'green' },
|
||||
{ label: "{{ t('Update') }}", value: 'update', color: 'blue' },
|
||||
{ label: "{{ t('Delete') }}", value: 'destroy', color: 'red' },
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
title: '操作',
|
||||
title: "{{t('Actions')}}",
|
||||
'x-component': 'Table.Column',
|
||||
'x-component-props': {
|
||||
width: 60,
|
||||
@ -753,7 +776,7 @@ function generateCardItemSchema(component) {
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
name: 'action1',
|
||||
title: '查看',
|
||||
title: "{{t('View')}}",
|
||||
'x-component': 'Action',
|
||||
'x-component-props': {
|
||||
type: 'link',
|
||||
@ -766,7 +789,7 @@ function generateCardItemSchema(component) {
|
||||
properties: {
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
title: '查看数据',
|
||||
title: "{{t('View record')}}",
|
||||
'x-read-pretty': true,
|
||||
'x-decorator': 'Form',
|
||||
'x-decorator-props': {
|
||||
@ -782,7 +805,7 @@ function generateCardItemSchema(component) {
|
||||
properties: {
|
||||
created_at: {
|
||||
type: 'string',
|
||||
title: '操作时间',
|
||||
title: "{{t('Created at')}}",
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'DatePicker',
|
||||
'x-read-pretty': true,
|
||||
@ -792,37 +815,37 @@ function generateCardItemSchema(component) {
|
||||
},
|
||||
'user.nickname': {
|
||||
type: 'string',
|
||||
title: '操作用户',
|
||||
title: "{{t('Created by')}}",
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input',
|
||||
'x-read-pretty': true,
|
||||
},
|
||||
'collection.title': {
|
||||
type: 'string',
|
||||
title: '数据表',
|
||||
title: "{{t('Collection display name')}}",
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input',
|
||||
'x-read-pretty': true,
|
||||
},
|
||||
type: {
|
||||
type: 'string',
|
||||
title: '操作类型',
|
||||
title: "{{t('Action type')}}",
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Select',
|
||||
'x-read-pretty': true,
|
||||
enum: [
|
||||
{
|
||||
label: '新增',
|
||||
label: "{{t('Insert')}}",
|
||||
value: 'create',
|
||||
color: 'green',
|
||||
},
|
||||
{
|
||||
label: '更新',
|
||||
label: "{{t('Update')}}",
|
||||
value: 'update',
|
||||
color: 'blue',
|
||||
},
|
||||
{
|
||||
label: '删除',
|
||||
label: "{{t('Delete')}}",
|
||||
value: 'destroy',
|
||||
color: 'red',
|
||||
},
|
||||
@ -830,7 +853,7 @@ function generateCardItemSchema(component) {
|
||||
},
|
||||
changes: {
|
||||
type: 'array',
|
||||
title: '数据变动',
|
||||
title: "{{t('Data changes')}}",
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'ArrayTable',
|
||||
'x-component-props': {
|
||||
@ -858,7 +881,7 @@ function generateCardItemSchema(component) {
|
||||
column1: {
|
||||
type: 'void',
|
||||
'x-component': 'ArrayTable.Column',
|
||||
'x-component-props': { title: '字段名称' },
|
||||
'x-component-props': { title: "{{t('Field display name')}}" },
|
||||
properties: {
|
||||
field: {
|
||||
type: 'string',
|
||||
@ -870,7 +893,7 @@ function generateCardItemSchema(component) {
|
||||
column3: {
|
||||
type: 'void',
|
||||
'x-component': 'ArrayTable.Column',
|
||||
'x-component-props': { title: '操作前' },
|
||||
'x-component-props': { title: "{{ t('Before change') }}" },
|
||||
properties: {
|
||||
before: {
|
||||
type: 'string',
|
||||
@ -882,7 +905,7 @@ function generateCardItemSchema(component) {
|
||||
column4: {
|
||||
type: 'void',
|
||||
'x-component': 'ArrayTable.Column',
|
||||
'x-component-props': { title: '操作后' },
|
||||
'x-component-props': { title: "{{ t('After change') }}" },
|
||||
properties: {
|
||||
after: {
|
||||
type: 'string',
|
||||
@ -920,33 +943,6 @@ function generateFormItemSchema(component) {
|
||||
return defaults[component];
|
||||
}
|
||||
|
||||
const dbSchema = {
|
||||
type: 'object',
|
||||
properties: {
|
||||
title: {
|
||||
type: 'string',
|
||||
title: '数据表名称',
|
||||
required: true,
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input',
|
||||
},
|
||||
name: {
|
||||
type: 'string',
|
||||
title: '数据表标识',
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input',
|
||||
'x-read-pretty': true,
|
||||
},
|
||||
generalFields: {
|
||||
type: 'array',
|
||||
title: '数据表字段',
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'DatabaseField',
|
||||
default: [],
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const AddNew = () => null;
|
||||
|
||||
AddNew.CardItem = observer((props: any) => {
|
||||
@ -955,6 +951,8 @@ AddNew.CardItem = observer((props: any) => {
|
||||
const path = useSchemaPath();
|
||||
const { collections = [], loading, refresh } = useCollectionsContext();
|
||||
const { createSchema } = useClient();
|
||||
const { t } = useTranslation();
|
||||
const compile = useCompile();
|
||||
return (
|
||||
<Dropdown
|
||||
trigger={['hover']}
|
||||
@ -1037,10 +1035,10 @@ AddNew.CardItem = observer((props: any) => {
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Menu.ItemGroup title={'数据区块'}>
|
||||
<Menu.ItemGroup title={t('Data blocks')}>
|
||||
{[
|
||||
{ key: 'Table', title: '表格', icon: 'TableOutlined' },
|
||||
{ key: 'Form', title: '表单', icon: 'FormOutlined' },
|
||||
{ key: 'Table', title: t('Table'), icon: 'TableOutlined' },
|
||||
{ key: 'Form', title: t('Form'), icon: 'FormOutlined' },
|
||||
].map((view) => (
|
||||
<Menu.SubMenu
|
||||
icon={<IconPicker type={view.icon} />}
|
||||
@ -1051,14 +1049,14 @@ AddNew.CardItem = observer((props: any) => {
|
||||
<Menu.ItemGroup
|
||||
className={'display-fields'}
|
||||
key={`${view.key}-select`}
|
||||
title={'选择数据源'}
|
||||
title={t('Select data source')}
|
||||
>
|
||||
{collections?.map((item) => (
|
||||
<Menu.Item
|
||||
style={{ minWidth: 150 }}
|
||||
key={`collection.${item.name}.${view.key}`}
|
||||
>
|
||||
{item.title}
|
||||
{compile(item.title)}
|
||||
</Menu.Item>
|
||||
))}
|
||||
</Menu.ItemGroup>
|
||||
@ -1071,7 +1069,7 @@ AddNew.CardItem = observer((props: any) => {
|
||||
{[
|
||||
{
|
||||
key: 'Calendar',
|
||||
title: '日历',
|
||||
title: t('Calendar'),
|
||||
icon: 'CalendarOutlined',
|
||||
// disabled: true,
|
||||
},
|
||||
@ -1085,14 +1083,14 @@ AddNew.CardItem = observer((props: any) => {
|
||||
<Menu.ItemGroup
|
||||
className={'display-fields'}
|
||||
key={`${view.key}-select`}
|
||||
title={'选择数据源'}
|
||||
title={t('Select data source')}
|
||||
>
|
||||
{collections?.map((item) => (
|
||||
<Menu.Item
|
||||
style={{ minWidth: 150 }}
|
||||
key={`Calendar.collection.${item.name}.${view.key}`}
|
||||
onClick={async () => {
|
||||
const values = await FormDialog(`日历配置`, () => {
|
||||
const values = await FormDialog(t('Configure calendar'), () => {
|
||||
return (
|
||||
<FormLayout layout={'vertical'}>
|
||||
<SchemaField
|
||||
@ -1101,7 +1099,7 @@ AddNew.CardItem = observer((props: any) => {
|
||||
properties: {
|
||||
title: {
|
||||
type: 'string',
|
||||
title: '标题字段',
|
||||
title: t('Title field'),
|
||||
required: true,
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Select',
|
||||
@ -1115,7 +1113,7 @@ AddNew.CardItem = observer((props: any) => {
|
||||
),
|
||||
},
|
||||
start: {
|
||||
title: '开始日期字段',
|
||||
title: t('Start date field'),
|
||||
required: true,
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Select',
|
||||
@ -1131,7 +1129,7 @@ AddNew.CardItem = observer((props: any) => {
|
||||
}),
|
||||
},
|
||||
end: {
|
||||
title: '结束日期字段',
|
||||
title: t('End date field'),
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Select',
|
||||
enum: item?.generalFields
|
||||
@ -1186,7 +1184,7 @@ AddNew.CardItem = observer((props: any) => {
|
||||
}
|
||||
}}
|
||||
>
|
||||
{item.title}
|
||||
{compile(item.title)}
|
||||
</Menu.Item>
|
||||
))}
|
||||
</Menu.ItemGroup>
|
||||
@ -1199,7 +1197,7 @@ AddNew.CardItem = observer((props: any) => {
|
||||
{[
|
||||
{
|
||||
key: 'Kanban',
|
||||
title: '看板',
|
||||
title: t('Kanban'),
|
||||
icon: 'CreditCardOutlined',
|
||||
// disabled: true,
|
||||
},
|
||||
@ -1213,15 +1211,15 @@ AddNew.CardItem = observer((props: any) => {
|
||||
<Menu.ItemGroup
|
||||
className={'display-fields'}
|
||||
key={`${view.key}-select`}
|
||||
title={'选择数据源'}
|
||||
title={t('Select data source')}
|
||||
>
|
||||
{collections?.map((item) => (
|
||||
<Menu.SubMenu
|
||||
// style={{ minWidth: 150 }}
|
||||
key={`collection.${item.name}.${view.key}`}
|
||||
title={item.title}
|
||||
title={compile(item.title)}
|
||||
>
|
||||
<Menu.ItemGroup title={'选择分组字段'}>
|
||||
<Menu.ItemGroup title={t('Select group field')}>
|
||||
{item?.generalFields
|
||||
?.filter((item) => {
|
||||
return item?.uiSchema?.enum;
|
||||
@ -1271,7 +1269,7 @@ AddNew.CardItem = observer((props: any) => {
|
||||
}
|
||||
}}
|
||||
>
|
||||
{field?.uiSchema?.title}
|
||||
{compile(field?.uiSchema?.title)}
|
||||
</Menu.Item>
|
||||
);
|
||||
})}
|
||||
@ -1293,58 +1291,58 @@ AddNew.CardItem = observer((props: any) => {
|
||||
))}
|
||||
</Menu.ItemGroup>
|
||||
<Menu.Divider />
|
||||
<Menu.ItemGroup title={'多媒体区块'}>
|
||||
<Menu.ItemGroup title={t('Media')}>
|
||||
<Menu.Item
|
||||
key={'Markdown.Void'}
|
||||
icon={<IconPicker type={'FileMarkdownOutlined'} />}
|
||||
>
|
||||
Markdown
|
||||
{t('Markdown')}
|
||||
</Menu.Item>
|
||||
<Menu.Item
|
||||
disabled
|
||||
key={'Wysiwyg.Void'}
|
||||
icon={<IconPicker type={'FileTextOutlined'} />}
|
||||
>
|
||||
富文本
|
||||
{t('Wysiwyg')}
|
||||
</Menu.Item>
|
||||
</Menu.ItemGroup>
|
||||
<Menu.Divider />
|
||||
<Menu.ItemGroup title={'图表区块'}>
|
||||
<Menu.ItemGroup title={t('Charts')}>
|
||||
<Menu.Item
|
||||
key={'Chart.Column'}
|
||||
icon={<IconPicker type={'BarChartOutlined'} />}
|
||||
>
|
||||
柱状图
|
||||
{t('Column chart')}
|
||||
</Menu.Item>
|
||||
<Menu.Item
|
||||
key={'Chart.Bar'}
|
||||
icon={<IconPicker type={'BarChartOutlined'} />}
|
||||
>
|
||||
条形图
|
||||
{t('Bar chart')}
|
||||
</Menu.Item>
|
||||
<Menu.Item
|
||||
disabled
|
||||
key={'Chart.Line'}
|
||||
icon={<IconPicker type={'LineChartOutlined'} />}
|
||||
>
|
||||
折线图
|
||||
{t('Line chart')}
|
||||
</Menu.Item>
|
||||
<Menu.Item
|
||||
disabled
|
||||
key={'Chart.Pie'}
|
||||
icon={<IconPicker type={'PieChartOutlined'} />}
|
||||
>
|
||||
饼图
|
||||
{t('Pie chart')}
|
||||
</Menu.Item>
|
||||
</Menu.ItemGroup>
|
||||
<Menu.Divider />
|
||||
<Menu.SubMenu key={'Ref'} icon={<LinkOutlined />} title={'引用模板'}>
|
||||
<Menu.ItemGroup key={'form-select'} title={'选择模板'}>
|
||||
<Menu.Item key={'Ref.ActionLogs'}>操作日志</Menu.Item>
|
||||
<Menu.SubMenu key={'Ref'} icon={<LinkOutlined />} title={t('Templates')}>
|
||||
<Menu.ItemGroup key={'form-select'} title={t('Select template')}>
|
||||
<Menu.Item key={'Ref.ActionLogs'}>{t('Action logs')}</Menu.Item>
|
||||
</Menu.ItemGroup>
|
||||
<Menu.Divider></Menu.Divider>
|
||||
<Menu.Item disabled key={'addNewRef'}>
|
||||
添加模板
|
||||
{t('Create template')}
|
||||
</Menu.Item>
|
||||
</Menu.SubMenu>
|
||||
</Menu>
|
||||
@ -1358,7 +1356,7 @@ AddNew.CardItem = observer((props: any) => {
|
||||
className={'designable-btn designable-btn-dash'}
|
||||
icon={<PlusOutlined />}
|
||||
>
|
||||
创建区块
|
||||
{t('Add block')}
|
||||
</Button>
|
||||
)}
|
||||
</Dropdown>
|
||||
@ -1375,6 +1373,7 @@ AddNew.FormItem = observer((props: any) => {
|
||||
const [visible, setVisible] = useState(false);
|
||||
const displayed = useDisplayedMapContext();
|
||||
const { createSchema, removeSchema } = useClient();
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<Dropdown
|
||||
@ -1386,7 +1385,10 @@ AddNew.FormItem = observer((props: any) => {
|
||||
}}
|
||||
overlay={
|
||||
<Menu>
|
||||
<Menu.ItemGroup className={'display-fields'} title={`显示字段`}>
|
||||
<Menu.ItemGroup
|
||||
className={'display-fields'}
|
||||
title={t('Display fields')}
|
||||
>
|
||||
{fields?.map((field) => (
|
||||
<SwitchMenuItem
|
||||
key={field.key}
|
||||
@ -1427,7 +1429,7 @@ AddNew.FormItem = observer((props: any) => {
|
||||
'x-component-props': {
|
||||
useOkAction: '{{ Select.useOkAction }}',
|
||||
},
|
||||
title: '关联数据',
|
||||
title: "{{t('Select record')}}",
|
||||
properties: {
|
||||
table: {
|
||||
type: 'array',
|
||||
@ -1461,7 +1463,7 @@ AddNew.FormItem = observer((props: any) => {
|
||||
properties: {
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
title: '筛选',
|
||||
title: "{{t('Filter')}}",
|
||||
'x-decorator': 'AddNew.Displayed',
|
||||
'x-decorator-props': {
|
||||
displayName: 'filter',
|
||||
@ -1486,7 +1488,7 @@ AddNew.FormItem = observer((props: any) => {
|
||||
properties: {
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
title: '查看数据',
|
||||
title: "{{ t('View record') }}",
|
||||
'x-component': 'Action.Drawer',
|
||||
'x-component-props': {
|
||||
bodyStyle: {
|
||||
@ -1501,7 +1503,7 @@ AddNew.FormItem = observer((props: any) => {
|
||||
properties: {
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
title: '详情',
|
||||
title: "{{t('Details')}}",
|
||||
'x-designable-bar':
|
||||
'Tabs.TabPane.DesignableBar',
|
||||
'x-component': 'Tabs.TabPane',
|
||||
@ -1551,7 +1553,7 @@ AddNew.FormItem = observer((props: any) => {
|
||||
disabled
|
||||
popupClassName={'add-new-fields-popup'}
|
||||
className={'sub-menu-add-new-fields'}
|
||||
title={'添加字段'}
|
||||
title={t('Add field')}
|
||||
>
|
||||
{options.map(
|
||||
(option) =>
|
||||
@ -1563,7 +1565,9 @@ AddNew.FormItem = observer((props: any) => {
|
||||
key={item.name}
|
||||
onClick={async () => {
|
||||
setVisible(false);
|
||||
const values = await FormDialog(`添加字段`, () => {
|
||||
const values = await FormDialog(
|
||||
t('Add field'),
|
||||
() => {
|
||||
return (
|
||||
<FormLayout layout={'vertical'}>
|
||||
<SchemaField
|
||||
@ -1572,7 +1576,8 @@ AddNew.FormItem = observer((props: any) => {
|
||||
/>
|
||||
</FormLayout>
|
||||
);
|
||||
}).open({
|
||||
},
|
||||
).open({
|
||||
initialValues: {
|
||||
interface: item.name,
|
||||
...item.default,
|
||||
@ -1618,7 +1623,9 @@ AddNew.FormItem = observer((props: any) => {
|
||||
onClick={async () => {
|
||||
let data: ISchema = {
|
||||
type: 'void',
|
||||
default: '这是一段演示文字,**支持使用 Markdown 语法**',
|
||||
default: t(
|
||||
'This is a demo text, **supports Markdown syntax**.',
|
||||
),
|
||||
'x-designable-bar': 'Markdown.Void.DesignableBar',
|
||||
'x-decorator': 'FormItem',
|
||||
'x-read-pretty': true,
|
||||
@ -1649,7 +1656,7 @@ AddNew.FormItem = observer((props: any) => {
|
||||
setVisible(false);
|
||||
}}
|
||||
>
|
||||
添加说明文字
|
||||
{t('Add text')}
|
||||
</Menu.Item>
|
||||
</Menu>
|
||||
}
|
||||
@ -1662,7 +1669,7 @@ AddNew.FormItem = observer((props: any) => {
|
||||
className={'designable-btn designable-btn-dash'}
|
||||
icon={<SettingOutlined />}
|
||||
>
|
||||
配置字段
|
||||
{t('Configure fields')}
|
||||
</Button>
|
||||
)}
|
||||
</Dropdown>
|
||||
@ -1679,7 +1686,7 @@ AddNew.PaneItem = observer((props: any) => {
|
||||
console.log('AddNew.PaneItem.useResource', useResource);
|
||||
const { collection, fields } = useCollectionContext();
|
||||
const { createSchema } = useClient();
|
||||
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<Dropdown
|
||||
trigger={['hover']}
|
||||
@ -1691,7 +1698,7 @@ AddNew.PaneItem = observer((props: any) => {
|
||||
// placement={'bottomCenter'}
|
||||
overlay={
|
||||
<Menu>
|
||||
<Menu.ItemGroup title={'数据区块'}>
|
||||
<Menu.ItemGroup title={t('Data blocks')}>
|
||||
<Menu.Item
|
||||
icon={<IconPicker type={'FileOutlined'} />}
|
||||
onClick={async () => {
|
||||
@ -1743,7 +1750,7 @@ AddNew.PaneItem = observer((props: any) => {
|
||||
}}
|
||||
style={{ minWidth: 150 }}
|
||||
>
|
||||
详情
|
||||
{t('Details')}
|
||||
</Menu.Item>
|
||||
<Menu.Item
|
||||
icon={<IconPicker type={'FormOutlined'} />}
|
||||
@ -1789,10 +1796,10 @@ AddNew.PaneItem = observer((props: any) => {
|
||||
setVisible(false);
|
||||
}}
|
||||
>
|
||||
表单
|
||||
{t('Form')}
|
||||
</Menu.Item>
|
||||
</Menu.ItemGroup>
|
||||
<Menu.ItemGroup title={'相关数据区块'}>
|
||||
<Menu.ItemGroup title={t('Relationship blocks')}>
|
||||
<Menu.Item
|
||||
style={{ minWidth: 150 }}
|
||||
icon={<IconPicker type={'HistoryOutlined'} />}
|
||||
@ -1819,7 +1826,7 @@ AddNew.PaneItem = observer((props: any) => {
|
||||
setVisible(false);
|
||||
}}
|
||||
>
|
||||
日志
|
||||
{t('Action logs')}
|
||||
</Menu.Item>
|
||||
{fields
|
||||
?.filter((f) => f.interface === 'linkTo')
|
||||
@ -1872,14 +1879,16 @@ AddNew.PaneItem = observer((props: any) => {
|
||||
);
|
||||
})}
|
||||
</Menu.ItemGroup>
|
||||
<Menu.ItemGroup title={'多媒体区块'}>
|
||||
<Menu.ItemGroup title={t('Media')}>
|
||||
<Menu.Item
|
||||
icon={<IconPicker type={'FileMarkdownOutlined'} />}
|
||||
onClick={async () => {
|
||||
let data: ISchema = {
|
||||
key: uid(),
|
||||
type: 'void',
|
||||
default: '这是一段演示文字,**支持使用 Markdown 语法**',
|
||||
default: t(
|
||||
'This is a demo text, **supports Markdown syntax**.',
|
||||
),
|
||||
'x-designable-bar': 'Markdown.Void.DesignableBar',
|
||||
'x-decorator': 'CardItem',
|
||||
'x-read-pretty': true,
|
||||
@ -1906,7 +1915,7 @@ AddNew.PaneItem = observer((props: any) => {
|
||||
setVisible(false);
|
||||
}}
|
||||
>
|
||||
Markdown
|
||||
{t('Markdown')}
|
||||
</Menu.Item>
|
||||
</Menu.ItemGroup>
|
||||
</Menu>
|
||||
@ -1920,7 +1929,7 @@ AddNew.PaneItem = observer((props: any) => {
|
||||
type={'dashed'}
|
||||
icon={<PlusOutlined />}
|
||||
>
|
||||
创建区块
|
||||
{t('Add block')}
|
||||
</Button>
|
||||
)}
|
||||
</Dropdown>
|
||||
|
@ -34,6 +34,7 @@ import { uid } from '@formily/shared';
|
||||
import { getSchemaPath } from '../../components/schema-renderer';
|
||||
import { useDisplayedMapContext } from '../../constate';
|
||||
import { DragHandle } from '../../components/Sortable';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export const ActionDesignableBar = (props: any) => {
|
||||
const { schema, remove, refresh, insertAfter } = useDesignable();
|
||||
@ -41,6 +42,7 @@ export const ActionDesignableBar = (props: any) => {
|
||||
const isPopup = Object.keys(schema.properties || {}).length > 0;
|
||||
const displayed = useDisplayedMapContext();
|
||||
const field = useField();
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<div className={cls('designable-bar', { active: visible })}>
|
||||
<span
|
||||
@ -71,7 +73,7 @@ export const ActionDesignableBar = (props: any) => {
|
||||
setVisible(false);
|
||||
}}
|
||||
>
|
||||
隐藏
|
||||
{t('Hide')}
|
||||
</Menu.Item>
|
||||
</Menu>
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ import SwitchMenuItem from '../../components/SwitchMenuItem';
|
||||
import { uid } from '@formily/shared';
|
||||
import { SettingOutlined } from '@ant-design/icons';
|
||||
import { Droppable, SortableItem } from '../../components/Sortable';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export const ActionBar = observer((props: any) => {
|
||||
const { align = 'top' } = props;
|
||||
@ -114,7 +115,7 @@ function generateActionSchema(type) {
|
||||
const actions: { [key: string]: ISchema } = {
|
||||
today: {
|
||||
type: 'void',
|
||||
title: '今天',
|
||||
title: '{{t("Today")}}',
|
||||
'x-designable-bar': 'Calendar.ActionDesignableBar',
|
||||
'x-component': 'Calendar.Today',
|
||||
'x-align': 'left',
|
||||
@ -125,7 +126,7 @@ function generateActionSchema(type) {
|
||||
},
|
||||
nav: {
|
||||
type: 'void',
|
||||
title: '翻页',
|
||||
title: '{{t("Navigate")}}',
|
||||
'x-designable-bar': 'Calendar.ActionDesignableBar',
|
||||
'x-component': 'Calendar.Nav',
|
||||
'x-align': 'left',
|
||||
@ -136,7 +137,7 @@ function generateActionSchema(type) {
|
||||
},
|
||||
title: {
|
||||
type: 'void',
|
||||
title: '标题',
|
||||
title: '{{t("Title")}}',
|
||||
'x-designable-bar': 'Calendar.ActionDesignableBar',
|
||||
'x-component': 'Calendar.Title',
|
||||
'x-align': 'left',
|
||||
@ -147,7 +148,7 @@ function generateActionSchema(type) {
|
||||
},
|
||||
viewSelect: {
|
||||
type: 'void',
|
||||
title: '视图切换',
|
||||
title: '{{t("Select view")}}',
|
||||
'x-designable-bar': 'Calendar.ActionDesignableBar',
|
||||
'x-component': 'Calendar.ViewSelect',
|
||||
'x-align': 'right',
|
||||
@ -158,7 +159,7 @@ function generateActionSchema(type) {
|
||||
},
|
||||
filter: {
|
||||
type: 'void',
|
||||
title: '过滤',
|
||||
title: '{{t("Filter")}}',
|
||||
'x-align': 'right',
|
||||
'x-designable-bar': 'Calendar.ActionDesignableBar',
|
||||
'x-component': 'Calendar.Filter',
|
||||
@ -169,7 +170,7 @@ function generateActionSchema(type) {
|
||||
},
|
||||
create: {
|
||||
type: 'void',
|
||||
title: '添加',
|
||||
title: '{{t("Add new")}}',
|
||||
'x-align': 'right',
|
||||
'x-designable-bar': 'Calendar.ActionDesignableBar',
|
||||
'x-component': 'Action',
|
||||
@ -184,7 +185,7 @@ function generateActionSchema(type) {
|
||||
properties: {
|
||||
modal: {
|
||||
type: 'void',
|
||||
title: '添加数据',
|
||||
title: '{{t("Add record")}}',
|
||||
'x-decorator': 'Form',
|
||||
'x-component': 'Action.Drawer',
|
||||
'x-component-props': {
|
||||
@ -207,6 +208,7 @@ function generateActionSchema(type) {
|
||||
}
|
||||
|
||||
function AddActionButton() {
|
||||
const { t } = useTranslation();
|
||||
const [visible, setVisible] = useState(false);
|
||||
const displayed = useDisplayedMapContext();
|
||||
const { appendChild, remove } = useDesignable();
|
||||
@ -223,14 +225,14 @@ function AddActionButton() {
|
||||
onVisibleChange={setVisible}
|
||||
overlay={
|
||||
<Menu>
|
||||
<Menu.ItemGroup title={'启用操作'}>
|
||||
<Menu.ItemGroup title={t('Enable actions')}>
|
||||
{[
|
||||
{ title: '今天', name: 'today' },
|
||||
{ title: '翻页', name: 'nav' },
|
||||
{ title: '标题', name: 'title' },
|
||||
{ title: '视图切换', name: 'viewSelect' },
|
||||
{ title: '筛选', name: 'filter' },
|
||||
{ title: '添加', name: 'create' },
|
||||
{ title: t('Today'), name: 'today' },
|
||||
{ title: t('Navigate'), name: 'nav' },
|
||||
{ title: t('Title'), name: 'title' },
|
||||
{ title: t('Select view'), name: 'viewSelect' },
|
||||
{ title: t('Filter'), name: 'filter' },
|
||||
{ title: t('Add new'), name: 'create' },
|
||||
].map((item) => (
|
||||
<SwitchMenuItem
|
||||
key={item.name}
|
||||
@ -253,10 +255,10 @@ function AddActionButton() {
|
||||
))}
|
||||
</Menu.ItemGroup>
|
||||
<Menu.Divider />
|
||||
<Menu.SubMenu disabled title={'自定义'}>
|
||||
<Menu.Item style={{ minWidth: 120 }}>函数操作</Menu.Item>
|
||||
<Menu.Item>弹窗表单</Menu.Item>
|
||||
<Menu.Item>复杂弹窗</Menu.Item>
|
||||
<Menu.SubMenu disabled title={t('Customize')}>
|
||||
<Menu.Item style={{ minWidth: 120 }}>{t('Function')}</Menu.Item>
|
||||
<Menu.Item>{t('Popup form')}</Menu.Item>
|
||||
<Menu.Item>{t('Flexible popup')}</Menu.Item>
|
||||
</Menu.SubMenu>
|
||||
</Menu>
|
||||
}
|
||||
@ -267,7 +269,7 @@ function AddActionButton() {
|
||||
type={'dashed'}
|
||||
icon={<SettingOutlined />}
|
||||
>
|
||||
配置工具栏
|
||||
{t('Configure actions')}
|
||||
</Button>
|
||||
</Dropdown>
|
||||
);
|
||||
|
@ -43,8 +43,12 @@ import { fieldsToFilterColumns } from './';
|
||||
import { set } from 'lodash';
|
||||
import { DragHandle } from '../../components/Sortable';
|
||||
import { DeleteOutlined, FilterOutlined } from '@ant-design/icons';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useCompile } from '../../hooks/useCompile';
|
||||
|
||||
export const DesignableBar = observer((props) => {
|
||||
const { t } = useTranslation();
|
||||
const compile = useCompile();
|
||||
const field = useField();
|
||||
const { designable, schema, refresh, deepRemove } = useDesignable();
|
||||
const [visible, setVisible] = useState(false);
|
||||
@ -57,7 +61,7 @@ export const DesignableBar = observer((props) => {
|
||||
return (
|
||||
<div className={cls('designable-bar', { active: visible })}>
|
||||
<div className={'designable-info'}>
|
||||
{collection?.title || collection?.name}
|
||||
{compile(collection?.title || collection?.name)}
|
||||
</div>
|
||||
<span
|
||||
onClick={(e) => {
|
||||
@ -80,7 +84,7 @@ export const DesignableBar = observer((props) => {
|
||||
<div
|
||||
style={{ display: 'flex', justifyContent: 'space-between' }}
|
||||
>
|
||||
标题字段:
|
||||
{t('Title field')}
|
||||
<Select
|
||||
bordered={false}
|
||||
size={'small'}
|
||||
@ -101,7 +105,7 @@ export const DesignableBar = observer((props) => {
|
||||
}}
|
||||
options={fields?.map((field) => {
|
||||
return {
|
||||
label: field?.uiSchema.title,
|
||||
label: compile(field?.uiSchema.title),
|
||||
value: field?.name,
|
||||
};
|
||||
})}
|
||||
@ -112,7 +116,7 @@ export const DesignableBar = observer((props) => {
|
||||
<div
|
||||
style={{ display: 'flex', justifyContent: 'space-between' }}
|
||||
>
|
||||
开始日期字段:
|
||||
{t('Start date field')}
|
||||
<Select
|
||||
bordered={false}
|
||||
size={'small'}
|
||||
@ -135,7 +139,7 @@ export const DesignableBar = observer((props) => {
|
||||
?.filter((field) => field.dataType === 'date')
|
||||
?.map((field) => {
|
||||
return {
|
||||
label: field?.uiSchema.title,
|
||||
label: compile(field?.uiSchema.title),
|
||||
value: field?.name,
|
||||
};
|
||||
})}
|
||||
@ -146,7 +150,7 @@ export const DesignableBar = observer((props) => {
|
||||
<div
|
||||
style={{ display: 'flex', justifyContent: 'space-between' }}
|
||||
>
|
||||
结束日期字段:
|
||||
{t('End date field')}
|
||||
<Select
|
||||
bordered={false}
|
||||
size={'small'}
|
||||
@ -168,7 +172,7 @@ export const DesignableBar = observer((props) => {
|
||||
?.filter((field) => field.dataType === 'date')
|
||||
?.map((field) => {
|
||||
return {
|
||||
label: field?.uiSchema.title,
|
||||
label: compile(field?.uiSchema.title),
|
||||
value: field?.name,
|
||||
};
|
||||
})}
|
||||
@ -180,7 +184,7 @@ export const DesignableBar = observer((props) => {
|
||||
icon={<FilterOutlined />}
|
||||
onClick={async () => {
|
||||
const { defaultFilter } = await FormDialog(
|
||||
'设置数据范围',
|
||||
t('Set the data scope'),
|
||||
() => {
|
||||
return (
|
||||
<FormLayout layout={'vertical'}>
|
||||
@ -211,7 +215,7 @@ export const DesignableBar = observer((props) => {
|
||||
await updateSchema(schema);
|
||||
}}
|
||||
>
|
||||
设置数据范围
|
||||
{t('Set the data scope')}
|
||||
</Menu.Item>
|
||||
<Menu.Divider />
|
||||
<Menu.Item
|
||||
@ -220,8 +224,8 @@ export const DesignableBar = observer((props) => {
|
||||
onClick={async () => {
|
||||
setVisible(false);
|
||||
Modal.confirm({
|
||||
title: '删除区块',
|
||||
content: '删除后无法恢复,确定要删除吗?',
|
||||
title: t('Delete block'),
|
||||
content: t('Are you sure you want to delete it?'),
|
||||
onOk: async () => {
|
||||
const removed = deepRemove();
|
||||
// console.log({ removed })
|
||||
@ -231,7 +235,7 @@ export const DesignableBar = observer((props) => {
|
||||
});
|
||||
}}
|
||||
>
|
||||
删除
|
||||
{t('Delete')}
|
||||
</Menu.Item>
|
||||
</Menu>
|
||||
}
|
||||
|
@ -40,7 +40,8 @@ import { SchemaField, useDesignable } from '../../components/schema-renderer';
|
||||
import { ActionBar } from './ActionBar';
|
||||
import { ActionDesignableBar } from './Action';
|
||||
import { createForm } from '@formily/core';
|
||||
import { flatten, get } from 'lodash';
|
||||
import { get } from 'lodash';
|
||||
import flatten from 'flat';
|
||||
import {
|
||||
CollectionProvider,
|
||||
useCollectionContext,
|
||||
@ -57,11 +58,12 @@ import { interfaces } from '../database-field/interfaces';
|
||||
import cls from 'classnames';
|
||||
import { Resource } from '../../resource';
|
||||
import { useRequest } from 'ahooks';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useCompile } from '../../hooks/useCompile';
|
||||
import { i18n } from '../../i18n';
|
||||
|
||||
const localizer = momentLocalizer(moment);
|
||||
|
||||
moment.locale('zh-CN');
|
||||
|
||||
const allViews = Object.keys(Views).map((k) => Views[k]);
|
||||
|
||||
interface ToolbarProps {
|
||||
@ -113,17 +115,17 @@ const messages: any = {
|
||||
<RightOutlined />
|
||||
</div>
|
||||
),
|
||||
today: '今天',
|
||||
month: '月',
|
||||
week: '周',
|
||||
work_week: '工作日',
|
||||
day: '天',
|
||||
agenda: '列表',
|
||||
date: '日期',
|
||||
time: '时间',
|
||||
event: '事件',
|
||||
noEventsInRange: '无',
|
||||
showMore: (count) => `还有 ${count} 项`,
|
||||
today: i18n.t('Today'),
|
||||
month: i18n.t('Month'),
|
||||
week: i18n.t('Week'),
|
||||
work_week: i18n.t('Work week'),
|
||||
day: i18n.t('Day'),
|
||||
agenda: i18n.t('Agenda'),
|
||||
date: i18n.t('Date'),
|
||||
time: i18n.t('Time'),
|
||||
event: i18n.t('Event'),
|
||||
noEventsInRange: i18n.t('None'),
|
||||
showMore: (count) => i18n.t('{{count}} more items', { count }),
|
||||
};
|
||||
|
||||
const useCalendar = () => {
|
||||
@ -134,14 +136,15 @@ const toEvents = (data: any[], fieldNames: any) => {
|
||||
return data?.map((item) => {
|
||||
return {
|
||||
id: get(item, fieldNames.id || 'id'),
|
||||
title: get(item, fieldNames.title) || '无标题',
|
||||
start: get(item, fieldNames.start),
|
||||
end: get(item, fieldNames.end || fieldNames.start),
|
||||
title: get(item, fieldNames.title) || i18n.t('Untitle'),
|
||||
start: new Date(get(item, fieldNames.start)),
|
||||
end: new Date(get(item, fieldNames.end || fieldNames.start)),
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
export const Calendar: any = observer((props: any) => {
|
||||
const { t } = useTranslation();
|
||||
const field = useField<Formily.Core.Models.ArrayField>();
|
||||
const { collectionName, fieldNames = {} } = props;
|
||||
console.log('Calendar', props);
|
||||
@ -167,7 +170,7 @@ export const Calendar: any = observer((props: any) => {
|
||||
formatResult: (data) => data?.data,
|
||||
onSuccess(data) {
|
||||
const events = toEvents(data, fieldNames) || [];
|
||||
// console.log('events', events);
|
||||
console.log('events', events);
|
||||
field.setValue(events);
|
||||
},
|
||||
// refreshDeps: [props.fieldNames],
|
||||
@ -192,7 +195,7 @@ export const Calendar: any = observer((props: any) => {
|
||||
onClose={() => {
|
||||
setVisible(false);
|
||||
}}
|
||||
title={'查看数据'}
|
||||
title={t('View record')}
|
||||
bodyStyle={{
|
||||
background: '#f0f2f5',
|
||||
paddingTop: 0,
|
||||
@ -232,18 +235,18 @@ export const Calendar: any = observer((props: any) => {
|
||||
console.log('onSelectEvent');
|
||||
}}
|
||||
formats={{
|
||||
monthHeaderFormat: 'Y年M月',
|
||||
agendaDateFormat: 'M月DD日',
|
||||
dayHeaderFormat: 'Y年M月DD日',
|
||||
monthHeaderFormat: 'Y-M',
|
||||
agendaDateFormat: 'M-DD',
|
||||
dayHeaderFormat: 'Y-M-DD',
|
||||
dayRangeHeaderFormat: ({ start, end }, culture, local) => {
|
||||
if (dates.eq(start, end, 'month')) {
|
||||
return local.format(start, 'Y年M月', culture);
|
||||
return local.format(start, 'Y-M', culture);
|
||||
}
|
||||
return `${local.format(
|
||||
start,
|
||||
'Y年M月',
|
||||
'Y-M',
|
||||
culture,
|
||||
)} - ${local.format(end, 'Y年M月', culture)}`;
|
||||
)} - ${local.format(end, 'Y-M', culture)}`;
|
||||
},
|
||||
}}
|
||||
defaultDate={new Date()}
|
||||
@ -316,13 +319,14 @@ Calendar.Title = observer(() => {
|
||||
Calendar.Today = observer((props) => {
|
||||
const { DesignableBar } = useDesignable();
|
||||
const { onNavigate } = useContext(ToolbarContext);
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<Button
|
||||
onClick={() => {
|
||||
onNavigate(navigate.TODAY);
|
||||
}}
|
||||
>
|
||||
今天
|
||||
{t('Today')}
|
||||
<DesignableBar />
|
||||
</Button>
|
||||
);
|
||||
@ -398,13 +402,14 @@ export const fieldsToFilterColumns = (fields: any[], options: any = {}) => {
|
||||
|
||||
Calendar.Filter = observer((props: any) => {
|
||||
const { service } = useCalendar();
|
||||
const { t } = useTranslation();
|
||||
const compile = useCompile();
|
||||
const { fieldNames = [] } = props;
|
||||
const { schema, DesignableBar } = useDesignable();
|
||||
const form = useMemo(() => createForm(), []);
|
||||
const { fields = [] } = useCollectionContext();
|
||||
const [visible, setVisible] = useState(false);
|
||||
const obj = flatten(form.values.filter || {});
|
||||
console.log('flatten', obj, Object.values(obj));
|
||||
const count = Object.values(obj).filter((i) =>
|
||||
Array.isArray(i) ? i.length : i,
|
||||
).length;
|
||||
@ -446,7 +451,7 @@ Calendar.Filter = observer((props: any) => {
|
||||
// });
|
||||
}}
|
||||
>
|
||||
提交
|
||||
{t('Submit')}
|
||||
</Submit>
|
||||
</FormButtonGroup>
|
||||
</FormProvider>
|
||||
@ -454,7 +459,7 @@ Calendar.Filter = observer((props: any) => {
|
||||
}
|
||||
>
|
||||
<Button icon={<IconPicker type={icon} />}>
|
||||
{count > 0 ? `${count} 个筛选项` : schema.title}
|
||||
{count > 0 ? t('{{count}} filter items', { count }) : compile(schema.title)}
|
||||
<DesignableBar />
|
||||
</Button>
|
||||
</Popover>
|
||||
@ -462,6 +467,7 @@ Calendar.Filter = observer((props: any) => {
|
||||
});
|
||||
|
||||
Calendar.Filter.DesignableBar = () => {
|
||||
const { t } = useTranslation();
|
||||
const { schema, remove, refresh, insertAfter } = useDesignable();
|
||||
const [visible, setVisible] = useState(false);
|
||||
const displayed = useDisplayedMapContext();
|
||||
@ -489,7 +495,7 @@ Calendar.Filter.DesignableBar = () => {
|
||||
}}
|
||||
overlay={
|
||||
<Menu>
|
||||
<Menu.ItemGroup title={'可筛选字段'}>
|
||||
<Menu.ItemGroup title={t('Filterable fields')}>
|
||||
{fields
|
||||
.filter((collectionField) => {
|
||||
const option = interfaces.get(collectionField.interface);
|
||||
@ -523,7 +529,7 @@ Calendar.Filter.DesignableBar = () => {
|
||||
<Menu.Item
|
||||
onClick={async (e) => {
|
||||
setVisible(false);
|
||||
const values = await FormDialog('编辑按钮', () => {
|
||||
const values = await FormDialog(t('Edit button'), () => {
|
||||
return (
|
||||
<FormLayout layout={'vertical'}>
|
||||
<SchemaField
|
||||
@ -532,14 +538,14 @@ Calendar.Filter.DesignableBar = () => {
|
||||
properties: {
|
||||
title: {
|
||||
type: 'string',
|
||||
title: '按钮名称',
|
||||
title: t('Display name'),
|
||||
required: true,
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input',
|
||||
},
|
||||
icon: {
|
||||
type: 'string',
|
||||
title: '按钮图标',
|
||||
title: t('Icon'),
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'IconPicker',
|
||||
},
|
||||
@ -562,7 +568,7 @@ Calendar.Filter.DesignableBar = () => {
|
||||
refresh();
|
||||
}}
|
||||
>
|
||||
编辑按钮
|
||||
{t('Edit button')}
|
||||
</Menu.Item>
|
||||
<Menu.Divider />
|
||||
<Menu.Item
|
||||
@ -577,7 +583,7 @@ Calendar.Filter.DesignableBar = () => {
|
||||
setVisible(false);
|
||||
}}
|
||||
>
|
||||
隐藏
|
||||
{t('Hide')}
|
||||
</Menu.Item>
|
||||
</Menu>
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ import {
|
||||
useFieldSchema,
|
||||
mapReadPretty,
|
||||
} from '@formily/react';
|
||||
import { Button, Dropdown, Input as AntdInput, Menu, Space } from 'antd';
|
||||
import { Button, Dropdown, Input as AntdInput, Menu, Modal, Space } from 'antd';
|
||||
import { LoadingOutlined, MenuOutlined, DragOutlined } from '@ant-design/icons';
|
||||
import { useDesignable } from '../../components/schema-renderer';
|
||||
import { useState } from 'react';
|
||||
@ -21,6 +21,7 @@ import { isGridRowOrCol } from '../grid';
|
||||
import G2Plot from './G2Plot';
|
||||
import { Column, Line, Pie, Bar } from '@antv/g2plot';
|
||||
import { DragHandle } from '../../components/Sortable';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export const Chart: any = {};
|
||||
|
||||
@ -41,6 +42,7 @@ Chart.Bar = observer((props: any) => {
|
||||
});
|
||||
|
||||
Chart.DesignableBar = observer((props) => {
|
||||
const { t } = useTranslation();
|
||||
const field = useField();
|
||||
const { designable, schema, refresh, deepRemove } = useDesignable();
|
||||
const [visible, setVisible] = useState(false);
|
||||
@ -73,20 +75,27 @@ Chart.DesignableBar = observer((props) => {
|
||||
field.readPretty = false;
|
||||
setVisible(false);
|
||||
}}
|
||||
disabled
|
||||
>
|
||||
编辑图表
|
||||
{t('Edit')}
|
||||
</Menu.Item>
|
||||
<Menu.Divider />
|
||||
<Menu.Item
|
||||
key={'delete'}
|
||||
onClick={async () => {
|
||||
Modal.confirm({
|
||||
title: t(`Delete block`),
|
||||
content: t('Are you sure you want to delete it?'),
|
||||
onOk: async () => {
|
||||
const removed = deepRemove();
|
||||
// console.log({ removed })
|
||||
const last = removed.pop();
|
||||
await removeSchema(last);
|
||||
},
|
||||
});
|
||||
}}
|
||||
>
|
||||
删除
|
||||
{t('Delete')}
|
||||
</Menu.Item>
|
||||
</Menu>
|
||||
}
|
||||
|
@ -2,29 +2,31 @@ import React from 'react';
|
||||
import { connect, mapProps, mapReadPretty } from '@formily/react';
|
||||
import { Tag, Select } from 'antd';
|
||||
import { LoadingOutlined } from '@ant-design/icons';
|
||||
import { useCompile } from '../../hooks/useCompile';
|
||||
|
||||
const colors = {
|
||||
red: '薄暮',
|
||||
magenta: '法式洋红',
|
||||
volcano: '火山',
|
||||
orange: '日暮',
|
||||
gold: '金盏花',
|
||||
lime: '青柠',
|
||||
green: '极光绿',
|
||||
cyan: '明青',
|
||||
blue: '拂晓蓝',
|
||||
geekblue: '极客蓝',
|
||||
purple: '酱紫',
|
||||
default: '默认',
|
||||
red: '{{t("Red")}}',
|
||||
magenta: '{{t("Magenta")}}',
|
||||
volcano: '{{t("Volcano")}}',
|
||||
orange: '{{t("Orange")}}',
|
||||
gold: '{{t("Gold")}}',
|
||||
lime: '{{t("Lime")}}',
|
||||
green: '{{t("Green")}}',
|
||||
cyan: '{{t("Cyan")}}',
|
||||
blue: '{{t("Blue")}}',
|
||||
geekblue: '{{t("Geek blue")}}',
|
||||
purple: '{{t("Purple")}}',
|
||||
default: '{{t("Default")}}',
|
||||
};
|
||||
|
||||
export const ColorSelect = connect(
|
||||
(props) => {
|
||||
const compile = useCompile();
|
||||
return (
|
||||
<Select {...props}>
|
||||
{Object.keys(colors).map((color) => (
|
||||
<Select.Option value={color}>
|
||||
<Tag color={color}>{colors[color]}</Tag>
|
||||
<Tag color={color}>{compile(colors[color] || colors.default)}</Tag>
|
||||
</Select.Option>
|
||||
))}
|
||||
</Select>
|
||||
@ -45,11 +47,12 @@ export const ColorSelect = connect(
|
||||
};
|
||||
}),
|
||||
mapReadPretty((props) => {
|
||||
const compile = useCompile();
|
||||
const { value } = props;
|
||||
if (!colors[value]) {
|
||||
return null;
|
||||
}
|
||||
return <Tag color={value}>{colors[value]}</Tag>;
|
||||
return <Tag color={value}>{compile(colors[value] || colors.default)}</Tag>;
|
||||
}),
|
||||
);
|
||||
|
||||
|
@ -6,7 +6,7 @@ export const attachment: FieldOptions = {
|
||||
name: 'attachment',
|
||||
type: 'object',
|
||||
group: 'media',
|
||||
title: '附件',
|
||||
title: '{{t("Attachment")}}',
|
||||
isAssociation: true,
|
||||
default: {
|
||||
dataType: 'belongsToMany',
|
||||
@ -41,7 +41,7 @@ export const attachment: FieldOptions = {
|
||||
...defaultProps,
|
||||
'uiSchema.x-component-props.multiple': {
|
||||
type: 'boolean',
|
||||
'x-content': '允许上传多个文件',
|
||||
'x-content': "{{t('Allow uploading multiple files')}}",
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Checkbox',
|
||||
default: true,
|
||||
|
@ -6,7 +6,7 @@ export const checkbox: FieldOptions = {
|
||||
type: 'object',
|
||||
group: 'choices',
|
||||
order: 1,
|
||||
title: '勾选',
|
||||
title: '{{t("Checkbox")}}',
|
||||
default: {
|
||||
dataType: 'boolean',
|
||||
// name,
|
||||
@ -22,7 +22,7 @@ export const checkbox: FieldOptions = {
|
||||
...defaultProps,
|
||||
},
|
||||
operations: [
|
||||
{ label: '是', value: '$isTruly', selected: true, noValue: true },
|
||||
{ label: '否', value: '$isFalsy', noValue: true },
|
||||
{ label: '{{t("Yes")}}', value: '$isTruly', selected: true, noValue: true },
|
||||
{ label: '{{t("No")}}', value: '$isFalsy', noValue: true },
|
||||
],
|
||||
};
|
||||
|
@ -7,7 +7,7 @@ export const checkboxGroup: FieldOptions = {
|
||||
type: 'object',
|
||||
group: 'choices',
|
||||
order: 5,
|
||||
title: '复选框',
|
||||
title: '{{t("Checkbox group")}}',
|
||||
default: {
|
||||
interface: 'checkboxGroup',
|
||||
dataType: 'json',
|
||||
|
@ -7,7 +7,7 @@ export const chinaRegion: FieldOptions = {
|
||||
type: 'object',
|
||||
group: 'choices',
|
||||
order: 7,
|
||||
title: '中国行政区划',
|
||||
title: '{{t("China region")}}',
|
||||
isAssociation: true,
|
||||
default: {
|
||||
dataType: 'belongsToMany',
|
||||
@ -60,22 +60,22 @@ export const chinaRegion: FieldOptions = {
|
||||
type: 'number',
|
||||
'x-component': 'Radio.Group',
|
||||
'x-decorator': 'FormItem',
|
||||
title: '可选择的层级',
|
||||
title: '{{t("Select level")}}',
|
||||
default: 3,
|
||||
enum: [
|
||||
{ value: 1, label: '省' },
|
||||
{ value: 2, label: '市' },
|
||||
{ value: 3, label: '区/县' },
|
||||
{ value: 4, label: '乡镇/街道' },
|
||||
{ value: 5, label: '村/居委会' },
|
||||
{ value: 1, label: '{{t("Province")}}' },
|
||||
{ value: 2, label: '{{t("City")}}' },
|
||||
{ value: 3, label: '{{t("Area")}}' },
|
||||
{ value: 4, label: '{{t("Street")}}' },
|
||||
{ value: 5, label: '{{t("Village")}}' },
|
||||
],
|
||||
},
|
||||
'uiSchema.x-component-props.changeOnSelectLast': {
|
||||
type: 'boolean',
|
||||
'x-component': 'Checkbox',
|
||||
'x-content': '必须选到最后一级',
|
||||
'x-content': '{{t("Must select to the last level")}}',
|
||||
'x-decorator': 'FormItem',
|
||||
},
|
||||
},
|
||||
operations: [{ label: '等于', value: 'code.in' }],
|
||||
operations: [{ label: '{{t("is")}}', value: 'code.in' }],
|
||||
};
|
||||
|
@ -7,7 +7,7 @@ export const createdAt: FieldOptions = {
|
||||
type: 'object',
|
||||
group: 'systemInfo',
|
||||
order: 1,
|
||||
title: '添加时间',
|
||||
title: '{{t("Created at")}}',
|
||||
sortable: true,
|
||||
default: {
|
||||
dataType: 'date',
|
||||
@ -15,7 +15,7 @@ export const createdAt: FieldOptions = {
|
||||
// name,
|
||||
uiSchema: {
|
||||
type: 'datetime',
|
||||
title: '添加时间',
|
||||
title: '{{t("Created at")}}',
|
||||
'x-component': 'DatePicker',
|
||||
'x-component-props': {},
|
||||
'x-read-pretty': true,
|
||||
|
@ -7,7 +7,7 @@ export const createdBy: FieldOptions = {
|
||||
type: 'object',
|
||||
group: 'systemInfo',
|
||||
order: 3,
|
||||
title: '添加人',
|
||||
title: '{{t("Created by")}}',
|
||||
isAssociation: true,
|
||||
default: {
|
||||
dataType: 'belongsTo',
|
||||
@ -16,7 +16,7 @@ export const createdBy: FieldOptions = {
|
||||
// name,
|
||||
uiSchema: {
|
||||
type: 'object',
|
||||
title: '添加人',
|
||||
title: '{{t("Created by")}}',
|
||||
'x-component': 'Select.Drawer',
|
||||
'x-component-props': {
|
||||
fieldNames: {
|
||||
|
@ -7,7 +7,7 @@ export const datetime: FieldOptions = {
|
||||
type: 'object',
|
||||
group: 'datetime',
|
||||
order: 1,
|
||||
title: '日期',
|
||||
title: '{{t("Datetime")}}',
|
||||
sortable: true,
|
||||
default: {
|
||||
dataType: 'date',
|
||||
@ -28,13 +28,13 @@ export const datetime: FieldOptions = {
|
||||
...dateTimeProps,
|
||||
},
|
||||
operations: [
|
||||
{ label: '等于', value: '$dateOn', selected: true },
|
||||
{ label: '不等于', value: '$dateNotOn' },
|
||||
{ label: '早于', value: '$dateBefore' },
|
||||
{ label: '晚于', value: '$dateAfter' },
|
||||
{ label: '不早于', value: '$dateNotBefore' },
|
||||
{ label: '不晚于', value: '$dateNotAfter' },
|
||||
{ label: '非空', value: '$notNull', noValue: true },
|
||||
{ label: '为空', value: '$null', noValue: true },
|
||||
{ label: "{{ t('is') }}", value: '$dateOn', selected: true },
|
||||
{ label: "{{ t('is not') }}", value: '$dateNotOn' },
|
||||
{ label: "{{ t('is before') }}", value: '$dateBefore' },
|
||||
{ label: "{{ t('is after') }}", value: '$dateAfter' },
|
||||
{ label: "{{ t('is on or after') }}", value: '$dateNotBefore' },
|
||||
{ label: "{{ t('is on or before') }}", value: '$dateNotAfter' },
|
||||
{ label: "{{ t('is empty') }}", value: '$null', noValue: true },
|
||||
{ label: "{{ t('is not empty') }}", value: '$notNull', noValue: true },
|
||||
],
|
||||
};
|
||||
|
@ -7,7 +7,7 @@ export const email: FieldOptions = {
|
||||
type: 'object',
|
||||
group: 'basic',
|
||||
order: 4,
|
||||
title: '电子邮箱',
|
||||
title: '{{t("Email")}}',
|
||||
sortable: true,
|
||||
default: {
|
||||
dataType: 'string',
|
||||
|
@ -6,7 +6,7 @@ export const icon: FieldOptions = {
|
||||
type: 'object',
|
||||
group: 'basic',
|
||||
order: 8,
|
||||
title: '图标',
|
||||
title: '{{t("Icon")}}',
|
||||
default: {
|
||||
dataType: 'string',
|
||||
// name,
|
||||
|
@ -47,13 +47,13 @@ Object.keys(types).forEach((type) => {
|
||||
registerField(schema.group || 'others', type, { order: 0, ...schema });
|
||||
});
|
||||
|
||||
registerGroupLabel('basic', '基本类型');
|
||||
registerGroupLabel('choices', '选择类型');
|
||||
registerGroupLabel('media', '多媒体类型');
|
||||
registerGroupLabel('datetime', '日期和时间');
|
||||
registerGroupLabel('relation', '关系类型');
|
||||
registerGroupLabel('systemInfo', '系统信息');
|
||||
registerGroupLabel('others', '其他类型');
|
||||
registerGroupLabel('basic', '{{t("Basic")}}');
|
||||
registerGroupLabel('choices', '{{t("Choices")}}');
|
||||
registerGroupLabel('media', '{{t("Media")}}');
|
||||
registerGroupLabel('datetime', '{{t("Date & Time")}}');
|
||||
registerGroupLabel('relation', '{{t("Relation")}}');
|
||||
registerGroupLabel('systemInfo', '{{t("System info")}}');
|
||||
registerGroupLabel('others', '{{t("Others")}}');
|
||||
|
||||
export const options = Object.keys(groupLabels).map((groupName) => {
|
||||
return {
|
||||
|
@ -7,7 +7,7 @@ export const linkTo: FieldOptions = {
|
||||
type: 'object',
|
||||
group: 'relation',
|
||||
order: 1,
|
||||
title: '关联字段',
|
||||
title: '{{t("Link to")}}',
|
||||
isAssociation: true,
|
||||
default: {
|
||||
dataType: 'belongsToMany',
|
||||
@ -44,7 +44,7 @@ export const linkTo: FieldOptions = {
|
||||
...defaultProps,
|
||||
target: {
|
||||
type: 'string',
|
||||
title: '要关联的数据表',
|
||||
title: '{{t("Related collection")}}',
|
||||
required: true,
|
||||
'x-reactions': ['{{useAsyncDataSource(loadCollections)}}'],
|
||||
'x-decorator': 'FormItem',
|
||||
@ -60,7 +60,7 @@ export const linkTo: FieldOptions = {
|
||||
// },
|
||||
'uiSchema.x-component-props.multiple': {
|
||||
type: 'boolean',
|
||||
'x-content': '允许关联多条记录',
|
||||
'x-content': '{{t("Allow linking to multiple records")}}',
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Checkbox',
|
||||
},
|
||||
|
@ -6,7 +6,7 @@ export const multipleSelect: FieldOptions = {
|
||||
type: 'object',
|
||||
group: 'choices',
|
||||
order: 3,
|
||||
title: '下拉选择(多选)',
|
||||
title: '{{t("Multiple select")}}',
|
||||
default: {
|
||||
dataType: 'json',
|
||||
// name,
|
||||
@ -28,19 +28,27 @@ export const multipleSelect: FieldOptions = {
|
||||
},
|
||||
operations: [
|
||||
{
|
||||
label: '等于',
|
||||
label: '{{t("is")}}',
|
||||
value: '$match',
|
||||
selected: true,
|
||||
schema: { 'x-component': 'Select' },
|
||||
},
|
||||
{
|
||||
label: '不等于',
|
||||
label: '{{t("is not")}}',
|
||||
value: '$notMatch',
|
||||
schema: { 'x-component': 'Select' },
|
||||
},
|
||||
{ label: '包含', value: '$anyOf', schema: { 'x-component': 'Select' } },
|
||||
{ label: '不包含', value: '$noneOf', schema: { 'x-component': 'Select' } },
|
||||
{ label: '非空', value: '$notNull', noValue: true },
|
||||
{ label: '为空', value: '$null', noValue: true },
|
||||
{
|
||||
label: '{{t("contains")}}',
|
||||
value: '$anyOf',
|
||||
schema: { 'x-component': 'Select' },
|
||||
},
|
||||
{
|
||||
label: '{{t("does not contain")}}',
|
||||
value: '$noneOf',
|
||||
schema: { 'x-component': 'Select' },
|
||||
},
|
||||
{ label: '{{t("is empty")}}', value: '$null', noValue: true },
|
||||
{ label: '{{t("is not empty")}}', value: '$notNull', noValue: true },
|
||||
],
|
||||
};
|
||||
|
@ -6,7 +6,7 @@ export const number: FieldOptions = {
|
||||
type: 'object',
|
||||
group: 'basic',
|
||||
order: 5,
|
||||
title: '数字',
|
||||
title: '{{t("Number")}}',
|
||||
sortable: true,
|
||||
default: {
|
||||
dataType: 'float',
|
||||
@ -27,7 +27,7 @@ export const number: FieldOptions = {
|
||||
...defaultProps,
|
||||
'uiSchema.x-component-props.step': {
|
||||
type: 'string',
|
||||
title: '精度',
|
||||
title: '{{t("Precision")}}',
|
||||
'x-component': 'Select',
|
||||
'x-decorator': 'FormItem',
|
||||
default: '0',
|
||||
@ -42,14 +42,14 @@ export const number: FieldOptions = {
|
||||
},
|
||||
},
|
||||
operations: [
|
||||
{ label: '等于', value: 'eq', selected: true },
|
||||
{ label: '不等于', value: 'ne' },
|
||||
{ label: '大于', value: 'gt' },
|
||||
{ label: '大于等于', value: 'gte' },
|
||||
{ label: '小于', value: 'lt' },
|
||||
{ label: '小于等于', value: 'lte' },
|
||||
{ label: '{{t("=")}}', value: 'eq', selected: true },
|
||||
{ label: '{{t("≠")}}', value: 'ne' },
|
||||
{ label: '{{t(">")}}', value: 'gt' },
|
||||
{ label: '{{t("≥")}}', value: 'gte' },
|
||||
{ label: '{{t("<")}}', value: 'lt' },
|
||||
{ label: '{{t("≤")}}', value: 'lte' },
|
||||
// {label: '介于', value: 'between'},
|
||||
{ label: '非空', value: '$notNull', noValue: true },
|
||||
{ label: '为空', value: '$null', noValue: true },
|
||||
{ label: '{{t("is empty")}}', value: '$null', noValue: true },
|
||||
{ label: '{{t("is not empty")}}', value: '$notNull', noValue: true },
|
||||
],
|
||||
};
|
||||
|
@ -6,7 +6,7 @@ export const password: FieldOptions = {
|
||||
type: 'object',
|
||||
group: 'basic',
|
||||
order: 7,
|
||||
title: '密码',
|
||||
title: '{{t("Password")}}',
|
||||
default: {
|
||||
dataType: 'password',
|
||||
// name,
|
||||
|
@ -7,7 +7,7 @@ export const percent: FieldOptions = {
|
||||
type: 'object',
|
||||
group: 'basic',
|
||||
order: 6,
|
||||
title: '百分比',
|
||||
title: '{{t("Percent")}}',
|
||||
sortable: true,
|
||||
default: {
|
||||
dataType: 'float',
|
||||
@ -29,7 +29,7 @@ export const percent: FieldOptions = {
|
||||
...defaultProps,
|
||||
'uiSchema.x-component-props.step': {
|
||||
type: 'string',
|
||||
title: '精度',
|
||||
title: '{{t("Precision")}}',
|
||||
'x-component': 'Select',
|
||||
'x-decorator': 'FormItem',
|
||||
default: '0',
|
||||
|
@ -7,7 +7,7 @@ export const phone: FieldOptions = {
|
||||
type: 'object',
|
||||
group: 'basic',
|
||||
order: 3,
|
||||
title: '手机号码',
|
||||
title: '{{t("Phone")}}',
|
||||
sortable: true,
|
||||
default: {
|
||||
dataType: 'string',
|
||||
|
@ -2,7 +2,7 @@ import { ISchema } from '@formily/react';
|
||||
|
||||
export const dataType: ISchema = {
|
||||
type: 'string',
|
||||
title: '数据类型',
|
||||
title: '{{t("Storage type")}}',
|
||||
required: true,
|
||||
'x-disabled': true,
|
||||
'x-decorator': 'FormItem',
|
||||
@ -30,21 +30,21 @@ export const dataType: ISchema = {
|
||||
export const dateTimeProps: { [key: string]: ISchema } = {
|
||||
'uiSchema.x-component-props.dateFormat': {
|
||||
type: 'string',
|
||||
title: '日期格式',
|
||||
title: '{{t("Date format")}}',
|
||||
'x-component': 'Radio.Group',
|
||||
'x-decorator': 'FormItem',
|
||||
default: 'YYYY-MM-DD',
|
||||
enum: [
|
||||
{
|
||||
label: '年/月/日',
|
||||
label: '{{t("Year/Month/Day")}}',
|
||||
value: 'YYYY/MM/DD',
|
||||
},
|
||||
{
|
||||
label: '年-月-日',
|
||||
label: '{{t("Year-Month-Day")}}',
|
||||
value: 'YYYY-MM-DD',
|
||||
},
|
||||
{
|
||||
label: '日/月/年',
|
||||
label: '{{t("Day/Month/Year")}}',
|
||||
value: 'DD/MM/YYYY',
|
||||
},
|
||||
],
|
||||
@ -53,7 +53,7 @@ export const dateTimeProps: { [key: string]: ISchema } = {
|
||||
type: 'boolean',
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Checkbox',
|
||||
'x-content': '显示时间',
|
||||
'x-content': '{{t("Show time")}}',
|
||||
'x-reactions': [
|
||||
`{{(field) => {
|
||||
field.query('..[].timeFormat').take(f => {
|
||||
@ -64,18 +64,18 @@ export const dateTimeProps: { [key: string]: ISchema } = {
|
||||
},
|
||||
'uiSchema.x-component-props.timeFormat': {
|
||||
type: 'string',
|
||||
title: '时间格式',
|
||||
title: '{{t("Time format")}}',
|
||||
'x-component': 'Radio.Group',
|
||||
'x-decorator': 'FormItem',
|
||||
default: 'HH:mm:ss',
|
||||
enum: [
|
||||
{
|
||||
label: '24小时制',
|
||||
value: 'HH:mm:ss',
|
||||
label: '{{t("12 hour")}}',
|
||||
value: 'hh:mm:ss a',
|
||||
},
|
||||
{
|
||||
label: '12小时制',
|
||||
value: 'hh:mm:ss a',
|
||||
label: '{{t("24 hour")}}',
|
||||
value: 'HH:mm:ss',
|
||||
},
|
||||
],
|
||||
},
|
||||
@ -83,7 +83,7 @@ export const dateTimeProps: { [key: string]: ISchema } = {
|
||||
|
||||
export const dataSource: ISchema = {
|
||||
type: 'array',
|
||||
title: '可选项',
|
||||
title: '{{t("Options")}}',
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'ArrayTable',
|
||||
'x-component-props': {
|
||||
@ -107,7 +107,7 @@ export const dataSource: ISchema = {
|
||||
column2: {
|
||||
type: 'void',
|
||||
'x-component': 'ArrayTable.Column',
|
||||
'x-component-props': { title: '选项值' },
|
||||
'x-component-props': { title: '{{t("Option value")}}' },
|
||||
'x-hidden': true,
|
||||
properties: {
|
||||
value: {
|
||||
@ -120,7 +120,7 @@ export const dataSource: ISchema = {
|
||||
column3: {
|
||||
type: 'void',
|
||||
'x-component': 'ArrayTable.Column',
|
||||
'x-component-props': { title: '选项' },
|
||||
'x-component-props': { title: '{{t("Option label")}}' },
|
||||
properties: {
|
||||
label: {
|
||||
type: 'string',
|
||||
@ -132,7 +132,7 @@ export const dataSource: ISchema = {
|
||||
column4: {
|
||||
type: 'void',
|
||||
'x-component': 'ArrayTable.Column',
|
||||
'x-component-props': { title: '颜色' },
|
||||
'x-component-props': { title: '{{t("Color")}}' },
|
||||
properties: {
|
||||
color: {
|
||||
type: 'string',
|
||||
@ -171,7 +171,7 @@ export const dataSource: ISchema = {
|
||||
'x-component-props': {
|
||||
randomValue: true,
|
||||
},
|
||||
title: '添加可选项',
|
||||
title: "{{t('Add option')}}",
|
||||
},
|
||||
},
|
||||
};
|
||||
@ -179,19 +179,20 @@ export const dataSource: ISchema = {
|
||||
export const defaultProps = {
|
||||
'uiSchema.title': {
|
||||
type: 'string',
|
||||
title: '字段名称',
|
||||
title: '{{t("Field display name")}}',
|
||||
required: true,
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input',
|
||||
},
|
||||
name: {
|
||||
type: 'string',
|
||||
title: '字段标识',
|
||||
title: '{{t("Field name")}}',
|
||||
required: true,
|
||||
// 'x-disabled': true,
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input',
|
||||
description: '随机生成,可修改。支持英文、数字和下划线,必须以英文字母开头',
|
||||
description:
|
||||
"{{t('Randomly generated and can be modified. Support letters, numbers and underscores, must start with an letter.')}}",
|
||||
},
|
||||
dataType,
|
||||
// 'uiSchema.required': {
|
||||
|
@ -7,7 +7,7 @@ export const radioGroup: FieldOptions = {
|
||||
type: 'object',
|
||||
group: 'choices',
|
||||
order: 4,
|
||||
title: '单选框',
|
||||
title: '{{t("Radio group")}}',
|
||||
default: {
|
||||
dataType: 'string',
|
||||
// name,
|
||||
|
@ -6,7 +6,7 @@ export const select: FieldOptions = {
|
||||
type: 'object',
|
||||
group: 'choices',
|
||||
order: 2,
|
||||
title: '下拉选择(单选)',
|
||||
title: '{{t("Single select")}}',
|
||||
default: {
|
||||
dataType: 'string',
|
||||
// name,
|
||||
@ -25,14 +25,18 @@ export const select: FieldOptions = {
|
||||
},
|
||||
operations: [
|
||||
{
|
||||
label: '等于',
|
||||
label: '{{t("is")}}',
|
||||
value: 'eq',
|
||||
selected: true,
|
||||
schema: { 'x-component': 'Select' },
|
||||
},
|
||||
{ label: '不等于', value: 'ne', schema: { 'x-component': 'Select' } },
|
||||
{
|
||||
label: '包含',
|
||||
label: '{{t("is not")}}',
|
||||
value: 'ne',
|
||||
schema: { 'x-component': 'Select' },
|
||||
},
|
||||
{
|
||||
label: '{{t("contains")}}',
|
||||
value: 'in',
|
||||
schema: {
|
||||
'x-component': 'Select',
|
||||
@ -40,14 +44,14 @@ export const select: FieldOptions = {
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '不包含',
|
||||
label: '{{t("does not contain")}}',
|
||||
value: 'notIn',
|
||||
schema: {
|
||||
'x-component': 'Select',
|
||||
'x-component-props': { mode: 'tags' },
|
||||
},
|
||||
},
|
||||
{ label: '非空', value: '$notNull', noValue: true },
|
||||
{ label: '为空', value: '$null', noValue: true },
|
||||
{ label: '{{t("is empty")}}', value: '$null', noValue: true },
|
||||
{ label: '{{t("is not empty")}}', value: '$notNull', noValue: true },
|
||||
],
|
||||
};
|
||||
|
@ -6,7 +6,7 @@ export const string: FieldOptions = {
|
||||
type: 'object',
|
||||
group: 'basic',
|
||||
order: 1,
|
||||
title: '单行文本',
|
||||
title: '{{t("Single line text")}}',
|
||||
sortable: true,
|
||||
default: {
|
||||
interface: 'string',
|
||||
@ -24,11 +24,11 @@ export const string: FieldOptions = {
|
||||
...defaultProps,
|
||||
},
|
||||
operations: [
|
||||
{ label: '包含', value: '$includes', selected: true },
|
||||
{ label: '不包含', value: '$notIncludes' },
|
||||
{ label: '等于', value: 'eq' },
|
||||
{ label: '不等于', value: 'ne' },
|
||||
{ label: '非空', value: '$notNull', noValue: true },
|
||||
{ label: '为空', value: '$null', noValue: true },
|
||||
{ label: '{{t("contains")}}', value: '$includes', selected: true },
|
||||
{ label: '{{t("does not contain")}}', value: '$notIncludes' },
|
||||
{ label: '{{t("is")}}', value: 'eq' },
|
||||
{ label: '{{t("is not")}}', value: 'ne' },
|
||||
{ label: '{{t("is empty")}}', value: '$null', noValue: true },
|
||||
{ label: '{{t("is not empty")}}', value: '$notNull', noValue: true },
|
||||
],
|
||||
};
|
||||
|
@ -7,7 +7,7 @@ export const subTable: FieldOptions = {
|
||||
type: 'object',
|
||||
group: 'relation',
|
||||
order: 2,
|
||||
title: '子表格',
|
||||
title: '{{t("Sub-table")}}',
|
||||
isAssociation: true,
|
||||
disabled: true,
|
||||
default: {
|
||||
@ -35,7 +35,7 @@ export const subTable: FieldOptions = {
|
||||
...defaultProps,
|
||||
children: {
|
||||
type: 'array',
|
||||
title: '子表格字段',
|
||||
title: '{{t("Sub-table fields")}}',
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'DatabaseField',
|
||||
},
|
||||
|
@ -6,7 +6,7 @@ export const textarea: FieldOptions = {
|
||||
type: 'object',
|
||||
group: 'basic',
|
||||
order: 2,
|
||||
title: '多行文本',
|
||||
title: '{{t("Long text")}}',
|
||||
default: {
|
||||
dataType: 'text',
|
||||
// name,
|
||||
|
@ -6,7 +6,7 @@ export const time: FieldOptions = {
|
||||
type: 'object',
|
||||
group: 'datetime',
|
||||
order: 2,
|
||||
title: '时间',
|
||||
title: '{{t("Time")}}',
|
||||
sortable: true,
|
||||
default: {
|
||||
dataType: 'time',
|
||||
@ -23,30 +23,30 @@ export const time: FieldOptions = {
|
||||
...defaultProps,
|
||||
'uiSchema.x-component-props.format': {
|
||||
type: 'string',
|
||||
title: '时间格式',
|
||||
title: '{{t("Time format")}}',
|
||||
'x-component': 'Radio.Group',
|
||||
'x-decorator': 'FormItem',
|
||||
default: 'HH:mm:ss',
|
||||
enum: [
|
||||
{
|
||||
label: '24小时制',
|
||||
value: 'HH:mm:ss',
|
||||
label: '{{t("12 hour")}}',
|
||||
value: 'hh:mm:ss a',
|
||||
},
|
||||
{
|
||||
label: '12小时制',
|
||||
value: 'hh:mm:ss a',
|
||||
label: '{{t("24 hour")}}',
|
||||
value: 'HH:mm:ss',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
operations: [
|
||||
{ label: '等于', value: 'eq', selected: true },
|
||||
{ label: '不等于', value: 'neq' },
|
||||
{ label: '大于', value: 'gt' },
|
||||
{ label: '大于等于', value: 'gte' },
|
||||
{ label: '小于', value: 'lt' },
|
||||
{ label: '小于等于', value: 'lte' },
|
||||
{ label: '非空', value: '$notNull', noValue: true },
|
||||
{ label: '为空', value: '$null', noValue: true },
|
||||
{ label: '{{t("is")}}', value: 'eq', selected: true },
|
||||
{ label: '{{t("is not")}}', value: 'neq' },
|
||||
// { label: '大于', value: 'gt' },
|
||||
// { label: '大于等于', value: 'gte' },
|
||||
// { label: '小于', value: 'lt' },
|
||||
// { label: '小于等于', value: 'lte' },
|
||||
{ label: '{{t("is empty")}}', value: '$null', noValue: true },
|
||||
{ label: '{{t("is not empty")}}', value: '$notNull', noValue: true },
|
||||
],
|
||||
};
|
||||
|
@ -7,7 +7,7 @@ export const updatedAt: FieldOptions = {
|
||||
type: 'object',
|
||||
group: 'systemInfo',
|
||||
order: 2,
|
||||
title: '最后更新时间',
|
||||
title: '{{t("Last updated at")}}',
|
||||
sortable: true,
|
||||
default: {
|
||||
dataType: 'date',
|
||||
@ -15,7 +15,7 @@ export const updatedAt: FieldOptions = {
|
||||
// name,
|
||||
uiSchema: {
|
||||
type: 'datetime',
|
||||
title: '最后更新时间',
|
||||
title: '{{t("Last updated at")}}',
|
||||
'x-component': 'DatePicker',
|
||||
'x-component-props': {},
|
||||
'x-read-pretty': true,
|
||||
|
@ -6,7 +6,7 @@ export const updatedBy: FieldOptions = {
|
||||
type: 'object',
|
||||
group: 'systemInfo',
|
||||
order: 4,
|
||||
title: '最后修改人',
|
||||
title: '{{t("Last updated by")}}',
|
||||
isAssociation: true,
|
||||
default: {
|
||||
dataType: 'belongsTo',
|
||||
@ -15,7 +15,7 @@ export const updatedBy: FieldOptions = {
|
||||
// name,
|
||||
uiSchema: {
|
||||
type: 'object',
|
||||
title: '最后修改人',
|
||||
title: '{{t("Last updated by")}}',
|
||||
'x-component': 'Select.Drawer',
|
||||
'x-component-props': {
|
||||
fieldNames: {
|
||||
|
@ -19,6 +19,7 @@ import {
|
||||
} from '@formily/antd/esm/__builtins__';
|
||||
import { FullscreenOutlined } from '@ant-design/icons';
|
||||
import moment from 'moment';
|
||||
import { useCompile } from '../../hooks/useCompile';
|
||||
|
||||
const PlaceholderContext = createContext<string>('');
|
||||
|
||||
@ -31,11 +32,12 @@ const usePlaceholder = (value?: any) => {
|
||||
|
||||
const Input: React.FC<InputProps> = (props) => {
|
||||
const prefixCls = usePrefixCls('description-input', props);
|
||||
const compile = useCompile();
|
||||
return (
|
||||
<div className={cls(prefixCls, props.className)} style={props.style}>
|
||||
{props.addonBefore}
|
||||
{props.prefix}
|
||||
{usePlaceholder(props.value)}
|
||||
{compile(usePlaceholder(props.value))}
|
||||
{props.suffix}
|
||||
{props.addonAfter}
|
||||
</div>
|
||||
|
@ -24,6 +24,7 @@ import { SchemaField, SchemaRenderer } from '../../components/schema-renderer';
|
||||
import { useMemo } from 'react';
|
||||
import { createForm, onFormValuesChange } from '@formily/core';
|
||||
import deepmerge from 'deepmerge';
|
||||
import { Trans, useTranslation } from 'react-i18next';
|
||||
|
||||
const toValue = (value) => {
|
||||
if (!value) {
|
||||
@ -62,7 +63,8 @@ export function FilterGroup(props) {
|
||||
</a>
|
||||
)}
|
||||
<div style={{ marginBottom: 14 }}>
|
||||
满足组内{' '}
|
||||
<Trans>
|
||||
{'Meet '}
|
||||
<Select
|
||||
style={{ width: 80 }}
|
||||
onChange={(logical) => {
|
||||
@ -73,10 +75,11 @@ export function FilterGroup(props) {
|
||||
}}
|
||||
defaultValue={value.logical}
|
||||
>
|
||||
<Select.Option value={'and'}>全部</Select.Option>
|
||||
<Select.Option value={'or'}>任意</Select.Option>
|
||||
</Select>{' '}
|
||||
条件
|
||||
<Select.Option value={'and'}>All</Select.Option>
|
||||
<Select.Option value={'or'}>Any</Select.Option>
|
||||
</Select>
|
||||
{' conditions in the group'}
|
||||
</Trans>
|
||||
</div>
|
||||
<FilterList
|
||||
initialValue={value.list}
|
||||
@ -97,6 +100,8 @@ export function FilterGroup(props) {
|
||||
export function FilterList(props) {
|
||||
const { initialValue = [] } = props;
|
||||
|
||||
const { t } = useTranslation();
|
||||
|
||||
const [map, { set, setAll, remove, reset, get }] = useMap<string, any>(
|
||||
initialValue.map((item, index) => {
|
||||
return [`index-${index}`, item];
|
||||
@ -137,7 +142,7 @@ export function FilterList(props) {
|
||||
set(uid(), {});
|
||||
}}
|
||||
>
|
||||
添加条件
|
||||
{t('Add filter')}
|
||||
</a>
|
||||
<a
|
||||
style={{ marginLeft: 16 }}
|
||||
@ -147,7 +152,7 @@ export function FilterList(props) {
|
||||
});
|
||||
}}
|
||||
>
|
||||
添加条件组
|
||||
{t('Add filter group')}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -30,6 +30,8 @@ import { useCollection, useCollectionContext } from '../../constate';
|
||||
import { useTable } from '../table';
|
||||
import { BlockSchemaContext } from '../../context';
|
||||
import { DragHandle } from '../../components/Sortable';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useCompile } from '../../hooks/useCompile';
|
||||
|
||||
export const DesignableBar = observer((props) => {
|
||||
const field = useField();
|
||||
@ -40,11 +42,13 @@ export const DesignableBar = observer((props) => {
|
||||
const blockSchema = useContext(BlockSchemaContext);
|
||||
const collectionName = blockSchema['x-component-props']?.collectionName;
|
||||
const { collection } = useCollection({ collectionName });
|
||||
const { t } = useTranslation();
|
||||
const compile = useCompile();
|
||||
return (
|
||||
<div className={cls('designable-bar', { active: visible })}>
|
||||
{collection && (
|
||||
<div className={'designable-info'}>
|
||||
{collection?.title || collection?.name}
|
||||
{compile(collection?.title || collection?.name)}
|
||||
</div>
|
||||
)}
|
||||
<span
|
||||
@ -77,8 +81,8 @@ export const DesignableBar = observer((props) => {
|
||||
key={'delete'}
|
||||
onClick={async () => {
|
||||
Modal.confirm({
|
||||
title: '删除区块',
|
||||
content: '删除后无法恢复,确定要删除吗?',
|
||||
title: t('Delete block'),
|
||||
content: t('Are you sure you want to delete it?'),
|
||||
onOk: async () => {
|
||||
const removed = deepRemove();
|
||||
// console.log({ removed })
|
||||
@ -88,7 +92,7 @@ export const DesignableBar = observer((props) => {
|
||||
});
|
||||
}}
|
||||
>
|
||||
删除
|
||||
{t('Delete')}
|
||||
</Menu.Item>
|
||||
</Menu>
|
||||
}
|
||||
|
@ -41,8 +41,10 @@ import {
|
||||
import SwitchMenuItem from '../../components/SwitchMenuItem';
|
||||
import { DragHandle } from '../../components/Sortable';
|
||||
import { set } from 'lodash';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export const FieldDesignableBar = observer((props) => {
|
||||
const { t } = useTranslation();
|
||||
const field = useField();
|
||||
const { schema, deepRemove, refresh } = useDesignable();
|
||||
const [visible, setVisible] = useState(false);
|
||||
@ -84,7 +86,7 @@ export const FieldDesignableBar = observer((props) => {
|
||||
<Menu.Item
|
||||
key={'update'}
|
||||
onClick={async () => {
|
||||
const values = await FormDialog('自定义字段名称', () => {
|
||||
const values = await FormDialog(t('Custom field display name'), () => {
|
||||
return (
|
||||
<FormLayout layout={'vertical'}>
|
||||
<SchemaField
|
||||
@ -93,14 +95,14 @@ export const FieldDesignableBar = observer((props) => {
|
||||
properties: {
|
||||
fieldName: {
|
||||
type: 'string',
|
||||
title: '原字段名称',
|
||||
title: t('Original name'),
|
||||
'x-read-pretty': true,
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input',
|
||||
},
|
||||
title: {
|
||||
type: 'string',
|
||||
title: '自定义名称',
|
||||
title: t('Custom name'),
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input',
|
||||
},
|
||||
@ -128,7 +130,7 @@ export const FieldDesignableBar = observer((props) => {
|
||||
});
|
||||
}}
|
||||
>
|
||||
自定义字段名称
|
||||
{t('Custom field display name')}
|
||||
</Menu.Item>
|
||||
{collectionField?.interface === 'linkTo' && (
|
||||
<Menu.Item>
|
||||
@ -138,14 +140,14 @@ export const FieldDesignableBar = observer((props) => {
|
||||
justifyContent: 'space-between',
|
||||
}}
|
||||
>
|
||||
标签字段{' '}
|
||||
{t('Label field')}{' '}
|
||||
<Select
|
||||
value={
|
||||
schema?.['x-component-props']?.['fieldNames']?.[
|
||||
'label'
|
||||
]
|
||||
}
|
||||
placeholder={'默认为 ID 字段'}
|
||||
placeholder={t('Default is the ID field')}
|
||||
onChange={async (value) => {
|
||||
set(
|
||||
schema['x-component-props'],
|
||||
@ -186,7 +188,7 @@ export const FieldDesignableBar = observer((props) => {
|
||||
<Menu.Item
|
||||
style={{ minWidth: 150 }}
|
||||
onClick={async () => {
|
||||
const values = await FormDialog('编辑描述', () => {
|
||||
const values = await FormDialog(t('Edit description'), () => {
|
||||
return (
|
||||
<FormLayout layout={'vertical'}>
|
||||
<SchemaField
|
||||
@ -217,10 +219,10 @@ export const FieldDesignableBar = observer((props) => {
|
||||
});
|
||||
}}
|
||||
>
|
||||
编辑描述
|
||||
{t('Edit description')}
|
||||
</Menu.Item>
|
||||
<SwitchMenuItem
|
||||
title={'必填'}
|
||||
title={t('Required')}
|
||||
checked={schema.required as boolean}
|
||||
onChange={(checked) => {
|
||||
field
|
||||
@ -245,7 +247,7 @@ export const FieldDesignableBar = observer((props) => {
|
||||
await removeSchema(last);
|
||||
}}
|
||||
>
|
||||
隐藏
|
||||
{t('Hide')}
|
||||
</Menu.Item>
|
||||
</Menu>
|
||||
}
|
||||
|
@ -45,6 +45,7 @@ import { useResource as useGeneralResource } from '../../hooks/useResource';
|
||||
import { Resource } from '../../resource';
|
||||
import { BaseResult } from '@ahooksjs/use-request/lib/types';
|
||||
import { CollectionFieldContext } from '../table';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export interface DescriptionsContextProps {
|
||||
resource?: Resource;
|
||||
@ -54,6 +55,7 @@ export interface DescriptionsContextProps {
|
||||
export const DescriptionsContext = createContext<DescriptionsContextProps>({});
|
||||
|
||||
const FormMain = (props: any) => {
|
||||
const { t } = useTranslation();
|
||||
const {
|
||||
useResource = useGeneralResource,
|
||||
showDefaultButtons = false,
|
||||
@ -123,19 +125,19 @@ const FormMain = (props: any) => {
|
||||
const values = await form.submit();
|
||||
console.log({ values });
|
||||
await resource.save(values);
|
||||
message.success('保存成功');
|
||||
message.success(t('Saved successfully'));
|
||||
await form.reset();
|
||||
}}
|
||||
type={'primary'}
|
||||
>
|
||||
提交
|
||||
{t('Submit')}
|
||||
</Button>
|
||||
<Button
|
||||
onClick={async () => {
|
||||
await form.reset();
|
||||
}}
|
||||
>
|
||||
重置
|
||||
{t('Reset')}
|
||||
</Button>
|
||||
</Space>
|
||||
)}
|
||||
|
@ -29,6 +29,7 @@ import { getSchemaPath } from '../../components/schema-renderer';
|
||||
import { useCollection, useCollectionContext } from '../../constate';
|
||||
import { useTable } from '../table';
|
||||
import { DragHandle } from '../../components/Sortable';
|
||||
import { useCompile } from '../../hooks/useCompile';
|
||||
|
||||
export const DesignableBar = observer((props) => {
|
||||
const field = useField();
|
||||
@ -39,10 +40,11 @@ export const DesignableBar = observer((props) => {
|
||||
const collectionName =
|
||||
field.componentProps?.collectionName || tableProps?.collectionName;
|
||||
const { collection } = useCollection({ collectionName });
|
||||
const compile = useCompile();
|
||||
return (
|
||||
<div className={cls('designable-bar', { active: visible })}>
|
||||
<div className={'designable-info'}>
|
||||
{collection?.title || collection?.name}
|
||||
{compile(collection?.title || collection?.name)}
|
||||
</div>
|
||||
<span
|
||||
onClick={(e) => {
|
||||
|
@ -8,10 +8,12 @@ import {
|
||||
IconPicker as Icon,
|
||||
} from '../../components/icon-picker';
|
||||
import { isValid } from '@formily/shared';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
function IconField(props: any) {
|
||||
const { value, onChange } = props;
|
||||
const [visible, setVisible] = useState(false);
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<div>
|
||||
<Input.Group compact>
|
||||
@ -38,10 +40,10 @@ function IconField(props: any) {
|
||||
))}
|
||||
</div>
|
||||
}
|
||||
title="图标"
|
||||
title={t('Icon')}
|
||||
trigger="click"
|
||||
>
|
||||
<Button>{hasIcon(value) ? <Icon type={value} /> : '选择图标'}</Button>
|
||||
<Button>{hasIcon(value) ? <Icon type={value} /> : t('Select icon')}</Button>
|
||||
</Popover>
|
||||
{value && (
|
||||
<Button
|
||||
|
@ -35,8 +35,10 @@ import { useTable } from '../table';
|
||||
import SwitchMenuItem from '../../components/SwitchMenuItem';
|
||||
import { useKanban } from '.';
|
||||
import { isAssociation } from '../database-field/interfaces';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export const CardDesignableBar = observer((props) => {
|
||||
const { t } = useTranslation();
|
||||
const field = useField();
|
||||
const { schema, appendChild, deepRemove } = useDesignable();
|
||||
const [visible, setVisible] = useState(false);
|
||||
@ -62,7 +64,7 @@ export const CardDesignableBar = observer((props) => {
|
||||
}}
|
||||
overlay={
|
||||
<Menu>
|
||||
<Menu.ItemGroup className={'display-fields'} title={`显示字段`}>
|
||||
<Menu.ItemGroup className={'display-fields'} title={t('Display fields')}>
|
||||
{fields?.map((field) => (
|
||||
<SwitchMenuItem
|
||||
key={field.key}
|
||||
|
@ -36,9 +36,12 @@ import { useCollection, useCollectionContext } from '../../constate';
|
||||
import { useTable } from '../table';
|
||||
import { DragHandle } from '../../components/Sortable';
|
||||
import { fieldsToFilterColumns } from '../calendar';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useCompile } from '../../hooks/useCompile';
|
||||
|
||||
export const DesignableBar = observer((props) => {
|
||||
const field = useField();
|
||||
const { t } = useTranslation();
|
||||
const { designable, schema, refresh, deepRemove } = useDesignable();
|
||||
const [visible, setVisible] = useState(false);
|
||||
const { dragRef } = useContext(DraggableBlockContext);
|
||||
@ -46,10 +49,11 @@ export const DesignableBar = observer((props) => {
|
||||
const collectionName =
|
||||
field.componentProps?.collectionName || tableProps?.collectionName;
|
||||
const { collection, fields } = useCollection({ collectionName });
|
||||
const compile = useCompile();
|
||||
return (
|
||||
<div className={cls('designable-bar', { active: visible })}>
|
||||
<div className={'designable-info'}>
|
||||
{collection?.title || collection?.name}
|
||||
{compile(collection?.title || collection?.name)}
|
||||
</div>
|
||||
<span
|
||||
onClick={(e) => {
|
||||
@ -80,7 +84,7 @@ export const DesignableBar = observer((props) => {
|
||||
key={'defaultFilter'}
|
||||
onClick={async () => {
|
||||
const { defaultFilter } = await FormDialog(
|
||||
'设置数据范围',
|
||||
t('Set the data scope'),
|
||||
() => {
|
||||
return (
|
||||
<FormLayout layout={'vertical'}>
|
||||
@ -111,15 +115,15 @@ export const DesignableBar = observer((props) => {
|
||||
await updateSchema(schema);
|
||||
}}
|
||||
>
|
||||
设置数据范围
|
||||
{t('Set the data scope')}
|
||||
</Menu.Item>
|
||||
<Menu.Divider />
|
||||
<Menu.Item
|
||||
key={'delete'}
|
||||
onClick={async () => {
|
||||
Modal.confirm({
|
||||
title: '删除区块',
|
||||
content: '删除后无法恢复,确定要删除吗?',
|
||||
title: t('Delete block'),
|
||||
content: t('Are you sure you want to delete it?'),
|
||||
onOk: async () => {
|
||||
const removed = deepRemove();
|
||||
// console.log({ removed })
|
||||
@ -129,7 +133,7 @@ export const DesignableBar = observer((props) => {
|
||||
});
|
||||
}}
|
||||
>
|
||||
删除
|
||||
{t('Delete')}
|
||||
</Menu.Item>
|
||||
</Menu>
|
||||
}
|
||||
|
@ -36,9 +36,11 @@ import { RandomNameContext } from '../form';
|
||||
import { useCollectionContext, useDisplayedMapContext } from '../../constate';
|
||||
import SwitchMenuItem from '../../components/SwitchMenuItem';
|
||||
import { DragHandle } from '../../components/Sortable';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export const FieldDesignableBar = observer((props) => {
|
||||
const field = useField();
|
||||
const { t } = useTranslation();
|
||||
const { schema, deepRemove } = useDesignable();
|
||||
const [visible, setVisible] = useState(false);
|
||||
const { dragRef } = useContext(DraggableBlockContext);
|
||||
@ -78,7 +80,7 @@ export const FieldDesignableBar = observer((props) => {
|
||||
<Menu.Item
|
||||
key={'update'}
|
||||
onClick={async () => {
|
||||
const values = await FormDialog('自定义字段名称', () => {
|
||||
const values = await FormDialog(t('Custom field display name'), () => {
|
||||
return (
|
||||
<FormLayout layout={'vertical'}>
|
||||
<SchemaField
|
||||
@ -87,14 +89,14 @@ export const FieldDesignableBar = observer((props) => {
|
||||
properties: {
|
||||
fieldName: {
|
||||
type: 'string',
|
||||
title: '原字段名称',
|
||||
title: t('Original name'),
|
||||
'x-read-pretty': true,
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input',
|
||||
},
|
||||
title: {
|
||||
type: 'string',
|
||||
title: '自定义名称',
|
||||
title: t('Custom name'),
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input',
|
||||
},
|
||||
@ -122,15 +124,15 @@ export const FieldDesignableBar = observer((props) => {
|
||||
});
|
||||
}}
|
||||
>
|
||||
自定义字段名称
|
||||
{t('Custom field display name')}
|
||||
</Menu.Item>
|
||||
<Menu.Divider />
|
||||
<Menu.Item
|
||||
key={'delete'}
|
||||
onClick={async () => {
|
||||
Modal.confirm({
|
||||
title: '删除区块',
|
||||
content: '删除后无法恢复,确定要删除吗?',
|
||||
title: t('Delete block'),
|
||||
content: t('Are you sure you want to delete it?'),
|
||||
onOk: async () => {
|
||||
const removed = deepRemove();
|
||||
const fieldName =
|
||||
@ -142,7 +144,7 @@ export const FieldDesignableBar = observer((props) => {
|
||||
});
|
||||
}}
|
||||
>
|
||||
删除
|
||||
{t('Delete')}
|
||||
</Menu.Item>
|
||||
</Menu>
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ import { removeSchema, updateSchema } from '..';
|
||||
import { isGridRowOrCol } from '../grid';
|
||||
import './style.less';
|
||||
import { DragHandle } from '../../components/Sortable';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export const Markdown: any = connect(
|
||||
AntdInput.TextArea,
|
||||
@ -52,6 +53,7 @@ export const Markdown: any = connect(
|
||||
);
|
||||
|
||||
function MarkdownTextArea(props: any) {
|
||||
const { t } = useTranslation();
|
||||
const [value, setValue] = useState(props.defaultValue);
|
||||
return (
|
||||
<div className={'mb-markdown'} style={{ position: 'relative' }}>
|
||||
@ -69,7 +71,7 @@ function MarkdownTextArea(props: any) {
|
||||
props.onCancel && props.onCancel(e);
|
||||
}}
|
||||
>
|
||||
取消
|
||||
{t('Cancel')}
|
||||
</Button>
|
||||
<Button
|
||||
type={'primary'}
|
||||
@ -77,7 +79,7 @@ function MarkdownTextArea(props: any) {
|
||||
props.onSubmit && props.onSubmit(value);
|
||||
}}
|
||||
>
|
||||
保存
|
||||
{t('Save')}
|
||||
</Button>
|
||||
</Space>
|
||||
</div>
|
||||
@ -116,6 +118,7 @@ Markdown.Void = observer((props: any) => {
|
||||
});
|
||||
|
||||
Markdown.Void.DesignableBar = observer((props) => {
|
||||
const { t } = useTranslation();
|
||||
const field = useField();
|
||||
const { designable, schema, refresh, deepRemove } = useDesignable();
|
||||
const [visible, setVisible] = useState(false);
|
||||
@ -149,15 +152,15 @@ Markdown.Void.DesignableBar = observer((props) => {
|
||||
setVisible(false);
|
||||
}}
|
||||
>
|
||||
编辑内容
|
||||
{t('Edit')}
|
||||
</Menu.Item>
|
||||
<Menu.Divider />
|
||||
<Menu.Item
|
||||
key={'delete'}
|
||||
onClick={async () => {
|
||||
Modal.confirm({
|
||||
title: '删除区块',
|
||||
content: '删除后无法恢复,确定要删除吗?',
|
||||
title: t('Delete block'),
|
||||
content: t('Are you sure you want to delete it?'),
|
||||
onOk: async () => {
|
||||
const removed = deepRemove();
|
||||
const last = removed.pop();
|
||||
@ -167,7 +170,7 @@ Markdown.Void.DesignableBar = observer((props) => {
|
||||
});
|
||||
}}
|
||||
>
|
||||
删除
|
||||
{t('Delete')}
|
||||
</Menu.Item>
|
||||
</Menu>
|
||||
}
|
||||
|
@ -1,3 +1,12 @@
|
||||
.nb-markdown > *:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.ant-description-textarea,
|
||||
.ant-description-input {
|
||||
line-height: 1.612;
|
||||
}
|
||||
|
||||
.field-interface-datetime {
|
||||
min-width: 100px;
|
||||
}
|
@ -71,6 +71,7 @@ import { DndContext, DragOverlay } from '@dnd-kit/core';
|
||||
import { createPortal } from 'react-dom';
|
||||
import { Resource } from '../../resource';
|
||||
import { useClient } from '../../constate';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export interface MenuContextProps {
|
||||
schema?: Schema;
|
||||
@ -82,6 +83,7 @@ export const MenuContext = createContext<MenuContextProps>(null);
|
||||
|
||||
const SideMenu = (props: any) => {
|
||||
const { selectedKey, defaultSelectedKeys, onSelect, path } = props;
|
||||
const { t } = useTranslation();
|
||||
const { schema } = useDesignable();
|
||||
const [selectedKeys, setSelectedKeys] = useState(defaultSelectedKeys);
|
||||
useEffect(() => {
|
||||
@ -114,7 +116,7 @@ const SideMenu = (props: any) => {
|
||||
icon={<PlusOutlined />}
|
||||
className={`nb-add-new-menu-item menu-mode-inline designable-btn designable-btn-dash`}
|
||||
>
|
||||
添加菜单项
|
||||
{t('Add menu item')}
|
||||
</Button>
|
||||
</Menu.AddNew>
|
||||
</AntdMenu>
|
||||
@ -160,6 +162,7 @@ export const Menu: any = observer((props: any) => {
|
||||
const child = schema.properties && schema.properties[selectedKey];
|
||||
const isSubMenu = child && child['x-component'] === 'Menu.SubMenu';
|
||||
const { updateSchema } = useClient();
|
||||
const { t } = useTranslation();
|
||||
|
||||
useMount(() => {
|
||||
if (mode !== 'mix') {
|
||||
@ -238,7 +241,7 @@ export const Menu: any = observer((props: any) => {
|
||||
icon={<PlusOutlined />}
|
||||
type={mode == 'inline' ? 'dashed' : 'primary'}
|
||||
>
|
||||
添加菜单项
|
||||
{t('Add menu item')}
|
||||
</Button>
|
||||
</Menu.AddNew>
|
||||
</AntdMenu>
|
||||
@ -437,26 +440,27 @@ Menu.SubMenu = observer((props: any) => {
|
||||
Menu.AddNew = observer((props: any) => {
|
||||
const { designable, appendChild } = useDesignable(props.path);
|
||||
const { createSchema, removeSchema, updateSchema } = useClient();
|
||||
const { t } = useTranslation();
|
||||
if (!designable) {
|
||||
return null;
|
||||
}
|
||||
const schemas = {
|
||||
'Menu.Link': {
|
||||
icon: <MenuOutlined />,
|
||||
title: '添加页面',
|
||||
title: t('Add page'),
|
||||
schema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
title: {
|
||||
type: 'string',
|
||||
title: '名称',
|
||||
title: t('Name'),
|
||||
required: true,
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input',
|
||||
},
|
||||
'x-component-props.icon': {
|
||||
type: 'string',
|
||||
title: '图标',
|
||||
title: t('Icon'),
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'IconPicker',
|
||||
},
|
||||
@ -465,20 +469,20 @@ Menu.AddNew = observer((props: any) => {
|
||||
},
|
||||
'Menu.SubMenu': {
|
||||
icon: <GroupOutlined />,
|
||||
title: '添加分组',
|
||||
title: t('Add group'),
|
||||
schema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
title: {
|
||||
type: 'string',
|
||||
title: '名称',
|
||||
title: t('Name'),
|
||||
required: true,
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input',
|
||||
},
|
||||
'x-component-props.icon': {
|
||||
type: 'string',
|
||||
title: '图标',
|
||||
title: t('Icon'),
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'IconPicker',
|
||||
},
|
||||
@ -487,26 +491,26 @@ Menu.AddNew = observer((props: any) => {
|
||||
},
|
||||
'Menu.URL': {
|
||||
icon: <LinkOutlined />,
|
||||
title: '添加链接',
|
||||
title: t('Add link'),
|
||||
schema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
title: {
|
||||
type: 'string',
|
||||
title: '名称',
|
||||
title: t('Name'),
|
||||
required: true,
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input',
|
||||
},
|
||||
'x-component-props.icon': {
|
||||
type: 'string',
|
||||
title: '图标',
|
||||
title: t('Icon'),
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'IconPicker',
|
||||
},
|
||||
'x-component-props.href': {
|
||||
type: 'string',
|
||||
title: '链接',
|
||||
title: t('Link'),
|
||||
required: true,
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input',
|
||||
@ -539,13 +543,13 @@ Menu.AddNew = observer((props: any) => {
|
||||
}}
|
||||
>
|
||||
<AntdMenu.Item key={'Menu.SubMenu'} icon={<GroupOutlined />}>
|
||||
分组
|
||||
{t('Group')}
|
||||
</AntdMenu.Item>
|
||||
<AntdMenu.Item key={'Menu.Link'} icon={<MenuOutlined />}>
|
||||
页面
|
||||
{t('Page')}
|
||||
</AntdMenu.Item>
|
||||
<AntdMenu.Item key={'Menu.URL'} icon={<LinkOutlined />}>
|
||||
链接
|
||||
{t('Link')}
|
||||
</AntdMenu.Item>
|
||||
</AntdMenu>
|
||||
}
|
||||
@ -558,23 +562,24 @@ Menu.AddNew = observer((props: any) => {
|
||||
});
|
||||
|
||||
Menu.DesignableBar = (props) => {
|
||||
const { t } = useTranslation();
|
||||
const schemas = {
|
||||
'Menu.Action': {
|
||||
icon: <MenuOutlined />,
|
||||
title: '页面',
|
||||
title: t('Page'),
|
||||
schema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
title: {
|
||||
type: 'string',
|
||||
title: '名称',
|
||||
title: t('Name'),
|
||||
required: true,
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input',
|
||||
},
|
||||
'x-component-props.icon': {
|
||||
type: 'string',
|
||||
title: '图标',
|
||||
title: t('Icon'),
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'IconPicker',
|
||||
},
|
||||
@ -583,20 +588,20 @@ Menu.DesignableBar = (props) => {
|
||||
},
|
||||
'Menu.Item': {
|
||||
icon: <MenuOutlined />,
|
||||
title: '页面',
|
||||
title: t('Page'),
|
||||
schema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
title: {
|
||||
type: 'string',
|
||||
title: '名称',
|
||||
title: t('Name'),
|
||||
required: true,
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input',
|
||||
},
|
||||
'x-component-props.icon': {
|
||||
type: 'string',
|
||||
title: '图标',
|
||||
title: t('Icon'),
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'IconPicker',
|
||||
},
|
||||
@ -605,20 +610,20 @@ Menu.DesignableBar = (props) => {
|
||||
},
|
||||
'Menu.Link': {
|
||||
icon: <MenuOutlined />,
|
||||
title: '页面',
|
||||
title: t('Page'),
|
||||
schema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
title: {
|
||||
type: 'string',
|
||||
title: '名称',
|
||||
title: t('Name'),
|
||||
required: true,
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input',
|
||||
},
|
||||
'x-component-props.icon': {
|
||||
type: 'string',
|
||||
title: '图标',
|
||||
title: t('Icon'),
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'IconPicker',
|
||||
},
|
||||
@ -627,20 +632,20 @@ Menu.DesignableBar = (props) => {
|
||||
},
|
||||
'Menu.SubMenu': {
|
||||
icon: <GroupOutlined />,
|
||||
title: '分组',
|
||||
title: t('Group'),
|
||||
schema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
title: {
|
||||
type: 'string',
|
||||
title: '名称',
|
||||
title: t('Name'),
|
||||
required: true,
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input',
|
||||
},
|
||||
'x-component-props.icon': {
|
||||
type: 'string',
|
||||
title: '图标',
|
||||
title: t('Icon'),
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'IconPicker',
|
||||
},
|
||||
@ -649,26 +654,26 @@ Menu.DesignableBar = (props) => {
|
||||
},
|
||||
'Menu.URL': {
|
||||
icon: <LinkOutlined />,
|
||||
title: '链接',
|
||||
title: 'Link',
|
||||
schema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
title: {
|
||||
type: 'string',
|
||||
title: '名称',
|
||||
title: t('Name'),
|
||||
required: true,
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input',
|
||||
},
|
||||
'x-component-props.icon': {
|
||||
type: 'string',
|
||||
title: '图标',
|
||||
title: t('Icon'),
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'IconPicker',
|
||||
},
|
||||
'x-component-props.href': {
|
||||
type: 'string',
|
||||
title: '链接',
|
||||
title: t('Link'),
|
||||
required: true,
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input',
|
||||
@ -718,9 +723,9 @@ Menu.DesignableBar = (props) => {
|
||||
return;
|
||||
}
|
||||
const methodLabels = {
|
||||
insertBefore: '之前',
|
||||
insertAfter: '之后',
|
||||
appendChild: '里',
|
||||
insertBefore: 'before',
|
||||
insertAfter: 'after',
|
||||
appendChild: 'in',
|
||||
};
|
||||
const keys = info.key.split('.');
|
||||
const method = keys.shift();
|
||||
@ -730,7 +735,8 @@ Menu.DesignableBar = (props) => {
|
||||
return;
|
||||
}
|
||||
const values = await FormDialog(
|
||||
`在「${schema.title}」${methodLabels[method]}插入${config.title}`,
|
||||
t(`Add {{type}} ${methodLabels[method]} "{{title}}"`, { type: (config.title as string).toLowerCase(), title: schema.title }),
|
||||
// `在「${schema.title}」${methodLabels[method]}插入${config.title}`,
|
||||
() => {
|
||||
return (
|
||||
<FormLayout layout={'vertical'}>
|
||||
@ -758,7 +764,7 @@ Menu.DesignableBar = (props) => {
|
||||
_.set(initialValues, name, get(schema, name));
|
||||
},
|
||||
);
|
||||
const values = await FormDialog(`编辑菜单项`, () => {
|
||||
const values = await FormDialog(t('Edit menu item'), () => {
|
||||
return (
|
||||
<FormLayout layout={'vertical'}>
|
||||
<SchemaField schema={formConfig.schema} />
|
||||
@ -780,7 +786,7 @@ Menu.DesignableBar = (props) => {
|
||||
await updateSchema(schema);
|
||||
}}
|
||||
>
|
||||
<EditOutlined /> 编辑菜单项
|
||||
<EditOutlined /> {t('Edit')}
|
||||
</AntdMenu.Item>
|
||||
<AntdMenu.Item
|
||||
key={'move'}
|
||||
@ -825,7 +831,7 @@ Menu.DesignableBar = (props) => {
|
||||
const dataSource = toTreeData(menuSchema);
|
||||
|
||||
const values = await FormDialog(
|
||||
`将「${schema.title}」移动到`,
|
||||
t(`Move {{title}} to`, { title: schema.title }),
|
||||
() => {
|
||||
return (
|
||||
<FormLayout layout={'vertical'}>
|
||||
@ -835,8 +841,9 @@ Menu.DesignableBar = (props) => {
|
||||
properties: {
|
||||
path: {
|
||||
type: 'string',
|
||||
title: '目标位置',
|
||||
title: t('Target position'),
|
||||
enum: dataSource,
|
||||
required: true,
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'TreeSelect',
|
||||
},
|
||||
@ -844,8 +851,8 @@ Menu.DesignableBar = (props) => {
|
||||
type: 'string',
|
||||
default: 'insertAfter',
|
||||
enum: [
|
||||
{ label: '之后', value: 'insertAfter' },
|
||||
{ label: '之前', value: 'insertBefore' },
|
||||
{ label: t('After'), value: 'insertAfter' },
|
||||
{ label: t('Before'), value: 'insertBefore' },
|
||||
],
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Radio.Group',
|
||||
@ -872,13 +879,13 @@ Menu.DesignableBar = (props) => {
|
||||
f.dataSource =
|
||||
target['x-component'] === 'Menu.SubMenu'
|
||||
? [
|
||||
{ label: '之后', value: 'insertAfter' },
|
||||
{ label: '之前', value: 'insertBefore' },
|
||||
{ label: '组里', value: 'appendChild' },
|
||||
{ label: t('After'), value: 'insertAfter' },
|
||||
{ label: t('Before'), value: 'insertBefore' },
|
||||
{ label: t('Inner'), value: 'appendChild' },
|
||||
]
|
||||
: [
|
||||
{ label: '之后', value: 'insertAfter' },
|
||||
{ label: '之前', value: 'insertBefore' },
|
||||
{ label: t('After'), value: 'insertAfter' },
|
||||
{ label: t('Before'), value: 'insertBefore' },
|
||||
];
|
||||
});
|
||||
});
|
||||
@ -895,80 +902,80 @@ Menu.DesignableBar = (props) => {
|
||||
await updateSchema(source);
|
||||
}}
|
||||
>
|
||||
<DragOutlined /> 移动到
|
||||
<DragOutlined /> {t('Move to')}
|
||||
</AntdMenu.Item>
|
||||
<AntdMenu.Divider />
|
||||
<AntdMenu.SubMenu
|
||||
key={'insertBefore'}
|
||||
icon={<ArrowUpOutlined />}
|
||||
title={`向${mode == 'inline' ? '上' : '左'}插入`}
|
||||
title={t(`Insert ${mode == 'inline' ? 'above' : 'left'}`)}
|
||||
>
|
||||
<AntdMenu.Item
|
||||
key={'insertBefore.Menu.SubMenu'}
|
||||
icon={<GroupOutlined />}
|
||||
>
|
||||
分组
|
||||
{t('Group')}
|
||||
</AntdMenu.Item>
|
||||
<AntdMenu.Item
|
||||
key={'insertBefore.Menu.Link'}
|
||||
icon={<MenuOutlined />}
|
||||
>
|
||||
页面
|
||||
{t('Page')}
|
||||
</AntdMenu.Item>
|
||||
<AntdMenu.Item
|
||||
key={'insertBefore.Menu.URL'}
|
||||
icon={<LinkOutlined />}
|
||||
>
|
||||
链接
|
||||
{t('Link')}
|
||||
</AntdMenu.Item>
|
||||
</AntdMenu.SubMenu>
|
||||
<AntdMenu.SubMenu
|
||||
key={'insertAfter'}
|
||||
icon={<ArrowDownOutlined />}
|
||||
title={`向${mode == 'inline' ? '下' : '右'}插入`}
|
||||
title={t(`Insert ${mode == 'inline' ? 'below' : 'right'}`)}
|
||||
>
|
||||
<AntdMenu.Item
|
||||
key={'insertAfter.Menu.SubMenu'}
|
||||
icon={<GroupOutlined />}
|
||||
>
|
||||
分组
|
||||
{t('Group')}
|
||||
</AntdMenu.Item>
|
||||
<AntdMenu.Item
|
||||
key={'insertAfter.Menu.Link'}
|
||||
icon={<MenuOutlined />}
|
||||
>
|
||||
页面
|
||||
{t('Page')}
|
||||
</AntdMenu.Item>
|
||||
<AntdMenu.Item
|
||||
key={'insertAfter.Menu.URL'}
|
||||
icon={<LinkOutlined />}
|
||||
>
|
||||
链接
|
||||
{t('Link')}
|
||||
</AntdMenu.Item>
|
||||
</AntdMenu.SubMenu>
|
||||
{isSubMenu && (
|
||||
<AntdMenu.SubMenu
|
||||
key={'appendChild'}
|
||||
icon={<ArrowRightOutlined />}
|
||||
title={'向里插入'}
|
||||
title={t('Insert inner')}
|
||||
>
|
||||
<AntdMenu.Item
|
||||
key={'appendChild.Menu.SubMenu'}
|
||||
icon={<GroupOutlined />}
|
||||
>
|
||||
分组
|
||||
{t('Group')}
|
||||
</AntdMenu.Item>
|
||||
<AntdMenu.Item
|
||||
key={'appendChild.Menu.Link'}
|
||||
icon={<MenuOutlined />}
|
||||
>
|
||||
页面
|
||||
{t('Page')}
|
||||
</AntdMenu.Item>
|
||||
<AntdMenu.Item
|
||||
key={'appendChild.Menu.URL'}
|
||||
icon={<LinkOutlined />}
|
||||
>
|
||||
链接
|
||||
{t('Link')}
|
||||
</AntdMenu.Item>
|
||||
</AntdMenu.SubMenu>
|
||||
)}
|
||||
@ -1035,8 +1042,8 @@ Menu.DesignableBar = (props) => {
|
||||
key={'delete'}
|
||||
onClick={() => {
|
||||
Modal.confirm({
|
||||
title: `删除${formConfig.title}`,
|
||||
content: '删除后无法恢复,确定要删除吗?',
|
||||
title: t(`Delete menu item`),
|
||||
content: t('Are you sure you want to delete it?'),
|
||||
onOk: async () => {
|
||||
const target = remove();
|
||||
await removeSchema(target);
|
||||
@ -1045,7 +1052,7 @@ Menu.DesignableBar = (props) => {
|
||||
});
|
||||
}}
|
||||
>
|
||||
<DeleteOutlined /> 删除
|
||||
<DeleteOutlined /> {t('Delete')}
|
||||
</AntdMenu.Item>
|
||||
</AntdMenu>
|
||||
}
|
||||
|
@ -3,14 +3,16 @@ import { PageHeader as AntdPageHeader } from 'antd';
|
||||
import { observer } from '@formily/react';
|
||||
import { usePageTitleContext } from '../../constate/PageTitle';
|
||||
import { Helmet } from 'react-helmet';
|
||||
import { useCompile } from '../../hooks/useCompile';
|
||||
|
||||
export const Page = observer((props) => {
|
||||
const { children, ...others } = props;
|
||||
const { documentTitle, pageTitle } = usePageTitleContext();
|
||||
const compile = useCompile();
|
||||
return (
|
||||
<>
|
||||
<Helmet>
|
||||
<title>{documentTitle}</title>
|
||||
<title>{compile(documentTitle)}</title>
|
||||
</Helmet>
|
||||
<AntdPageHeader ghost={false} title={pageTitle} {...others} />
|
||||
<div style={{ margin: 24 }}>{children}</div>
|
||||
|
@ -34,8 +34,10 @@ import { uid } from '@formily/shared';
|
||||
import { getSchemaPath } from '../../components/schema-renderer';
|
||||
import { set } from 'lodash';
|
||||
import { DragHandle } from '../../components/Sortable';
|
||||
import { Trans, useTranslation } from 'react-i18next';
|
||||
|
||||
export const SimpleDesignableBar = observer((props) => {
|
||||
const { t } = useTranslation();
|
||||
const field = useField();
|
||||
const { designable, schema, refresh, deepRemove } = useDesignable();
|
||||
const [visible, setVisible] = useState(false);
|
||||
@ -68,7 +70,7 @@ export const SimpleDesignableBar = observer((props) => {
|
||||
key={'defaultFilter'}
|
||||
onClick={async () => {
|
||||
const { defaultFilter } = await FormDialog(
|
||||
'设置数据范围',
|
||||
t('Set the data scope'),
|
||||
() => {
|
||||
return (
|
||||
<FormLayout layout={'vertical'}>
|
||||
@ -82,12 +84,12 @@ export const SimpleDesignableBar = observer((props) => {
|
||||
properties: {
|
||||
column1: {
|
||||
type: 'void',
|
||||
title: '操作类型',
|
||||
title: t('Action type'),
|
||||
'x-component': 'Filter.Column',
|
||||
'x-component-props': {
|
||||
operations: [
|
||||
{
|
||||
label: '等于',
|
||||
label: '{{t("is")}}',
|
||||
value: 'eq',
|
||||
selected: true,
|
||||
schema: {
|
||||
@ -95,14 +97,14 @@ export const SimpleDesignableBar = observer((props) => {
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '不等于',
|
||||
label: '{{t("is not")}}',
|
||||
value: 'ne',
|
||||
schema: {
|
||||
'x-component': 'Select',
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '包含',
|
||||
label: '{{t("contains")}}',
|
||||
value: 'in',
|
||||
schema: {
|
||||
'x-component': 'Select',
|
||||
@ -112,7 +114,7 @@ export const SimpleDesignableBar = observer((props) => {
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '不包含',
|
||||
label: '{{t("does not contain")}}',
|
||||
value: 'notIn',
|
||||
schema: {
|
||||
'x-component': 'Select',
|
||||
@ -122,13 +124,13 @@ export const SimpleDesignableBar = observer((props) => {
|
||||
},
|
||||
},
|
||||
{
|
||||
label: '非空',
|
||||
value: '$notNull',
|
||||
label: '{{t("is empty")}}',
|
||||
value: '$null',
|
||||
noValue: true,
|
||||
},
|
||||
{
|
||||
label: '为空',
|
||||
value: '$null',
|
||||
label: '{{t("is not empty")}}',
|
||||
value: '$notNull',
|
||||
noValue: true,
|
||||
},
|
||||
],
|
||||
@ -139,15 +141,15 @@ export const SimpleDesignableBar = observer((props) => {
|
||||
'x-component': 'Select',
|
||||
enum: [
|
||||
{
|
||||
label: '添加数据',
|
||||
label: '{{t("Insert")}}',
|
||||
value: 'create',
|
||||
},
|
||||
{
|
||||
label: '更新数据',
|
||||
label: '{{t("Update")}}',
|
||||
value: 'update',
|
||||
},
|
||||
{
|
||||
label: '删除数据',
|
||||
label: '{{t("Delete")}}',
|
||||
value: 'destroy',
|
||||
},
|
||||
],
|
||||
@ -175,10 +177,11 @@ export const SimpleDesignableBar = observer((props) => {
|
||||
setVisible(false);
|
||||
}}
|
||||
>
|
||||
设置数据范围
|
||||
{t('Set the data scope')}
|
||||
</Menu.Item>
|
||||
<Menu.Item key={'defaultPageSize'}>
|
||||
每页默认显示{' '}
|
||||
<Trans>
|
||||
{'Display '}
|
||||
<Select
|
||||
bordered={false}
|
||||
size={'small'}
|
||||
@ -199,16 +202,17 @@ export const SimpleDesignableBar = observer((props) => {
|
||||
<Select.Option value={20}>20</Select.Option>
|
||||
<Select.Option value={50}>50</Select.Option>
|
||||
<Select.Option value={100}>100</Select.Option>
|
||||
</Select>{' '}
|
||||
条
|
||||
</Select>
|
||||
{' items per page'}
|
||||
</Trans>
|
||||
</Menu.Item>
|
||||
<Menu.Divider />
|
||||
<Menu.Item
|
||||
key={'delete'}
|
||||
onClick={async () => {
|
||||
Modal.confirm({
|
||||
title: '删除区块',
|
||||
content: '删除后无法恢复,确定要删除吗?',
|
||||
title: t('Delete block'),
|
||||
content: t('Are you sure you want to delete it?'),
|
||||
onOk: async () => {
|
||||
const removed = deepRemove();
|
||||
// console.log({ removed })
|
||||
@ -219,7 +223,7 @@ export const SimpleDesignableBar = observer((props) => {
|
||||
});
|
||||
}}
|
||||
>
|
||||
删除
|
||||
{t('Delete')}
|
||||
</Menu.Item>
|
||||
</Menu>
|
||||
}
|
||||
|
@ -72,6 +72,8 @@ import IconPicker from '../../components/icon-picker';
|
||||
import { DescriptionsContext } from '../form';
|
||||
import { VisibleContext } from '../../context';
|
||||
import { SimpleDesignableBar } from './SimpleDesignableBar';
|
||||
import { Trans, useTranslation } from 'react-i18next';
|
||||
import { useCompile } from '../../hooks/useCompile';
|
||||
|
||||
export interface ITableContext {
|
||||
props: any;
|
||||
@ -401,6 +403,7 @@ const useTableColumns = () => {
|
||||
};
|
||||
|
||||
function AddColumn() {
|
||||
const { t } = useTranslation();
|
||||
const [visible, setVisible] = useState(false);
|
||||
const { appendChild, remove } = useDesignable();
|
||||
const { loadCollections } = useCollectionsContext();
|
||||
@ -408,7 +411,6 @@ function AddColumn() {
|
||||
const displayed = useDisplayedMapContext();
|
||||
const { service } = useTable();
|
||||
const { createSchema, removeSchema, updateSchema } = useClient();
|
||||
|
||||
return (
|
||||
<Dropdown
|
||||
trigger={['hover']}
|
||||
@ -416,7 +418,10 @@ function AddColumn() {
|
||||
onVisibleChange={setVisible}
|
||||
overlay={
|
||||
<Menu>
|
||||
<Menu.ItemGroup className={'display-fields'} title={'显示字段'}>
|
||||
<Menu.ItemGroup
|
||||
className={'display-fields'}
|
||||
title={t('Display fields')}
|
||||
>
|
||||
{fields.map((field) => (
|
||||
<SwitchMenuItem
|
||||
title={field?.uiSchema?.title}
|
||||
@ -445,7 +450,7 @@ function AddColumn() {
|
||||
'x-component-props': {
|
||||
useOkAction: '{{ Select.useOkAction }}',
|
||||
},
|
||||
title: '关联数据',
|
||||
title: "{{t('Select record')}}",
|
||||
properties: {
|
||||
table: {
|
||||
type: 'array',
|
||||
@ -479,7 +484,7 @@ function AddColumn() {
|
||||
properties: {
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
title: '筛选',
|
||||
title: "{{t('Filter')}}",
|
||||
'x-decorator': 'AddNew.Displayed',
|
||||
'x-decorator-props': {
|
||||
displayName: 'filter',
|
||||
@ -504,7 +509,7 @@ function AddColumn() {
|
||||
properties: {
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
title: '查看数据',
|
||||
title: "{{t('View record')}}",
|
||||
'x-component': 'Action.Drawer',
|
||||
'x-component-props': {
|
||||
bodyStyle: {
|
||||
@ -519,7 +524,7 @@ function AddColumn() {
|
||||
properties: {
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
title: '详情',
|
||||
title: "{{t('Details')}}",
|
||||
'x-designable-bar':
|
||||
'Tabs.TabPane.DesignableBar',
|
||||
'x-component': 'Tabs.TabPane',
|
||||
@ -581,7 +586,7 @@ function AddColumn() {
|
||||
<Menu.SubMenu
|
||||
disabled
|
||||
popupClassName={'add-new-fields-popup'}
|
||||
title={'添加字段'}
|
||||
title={t('Add field')}
|
||||
>
|
||||
{options.map((option) => (
|
||||
<Menu.ItemGroup title={option.label}>
|
||||
@ -591,7 +596,7 @@ function AddColumn() {
|
||||
key={item.name}
|
||||
onClick={async () => {
|
||||
setVisible(false);
|
||||
const values = await FormDialog(`添加字段`, () => {
|
||||
const values = await FormDialog(t('Add field'), () => {
|
||||
return (
|
||||
<FormLayout layout={'vertical'}>
|
||||
<SchemaField
|
||||
@ -635,7 +640,7 @@ function AddColumn() {
|
||||
className={'designable-btn designable-btn-dash'}
|
||||
icon={<SettingOutlined />}
|
||||
>
|
||||
配置字段
|
||||
{t('Configure fields')}
|
||||
</Button>
|
||||
</Dropdown>
|
||||
);
|
||||
@ -903,8 +908,8 @@ const TableProvider = (props: any) => {
|
||||
useEffect(() => {
|
||||
service.run(getDefaultParams());
|
||||
}, [
|
||||
pagination.pageSize,
|
||||
pagination.page,
|
||||
pagination?.pageSize,
|
||||
pagination?.page,
|
||||
props.dragSort,
|
||||
props.defaultSort,
|
||||
props.defaultFilter,
|
||||
@ -1001,7 +1006,7 @@ function generateActionSchema(type) {
|
||||
key: uid(),
|
||||
name: uid(),
|
||||
type: 'void',
|
||||
title: '筛选',
|
||||
title: "{{ t('Filter') }}",
|
||||
'x-align': 'left',
|
||||
'x-decorator': 'AddNew.Displayed',
|
||||
'x-decorator-props': {
|
||||
@ -1017,7 +1022,7 @@ function generateActionSchema(type) {
|
||||
key: uid(),
|
||||
type: 'void',
|
||||
name: uid(),
|
||||
title: '导出',
|
||||
title: "{{ t('Export') }}",
|
||||
'x-align': 'right',
|
||||
'x-decorator': 'AddNew.Displayed',
|
||||
'x-decorator-props': {
|
||||
@ -1036,7 +1041,7 @@ function generateActionSchema(type) {
|
||||
key: uid(),
|
||||
type: 'void',
|
||||
name: uid(),
|
||||
title: '添加',
|
||||
title: "{{ t('Add new') }}",
|
||||
'x-align': 'right',
|
||||
'x-decorator': 'AddNew.Displayed',
|
||||
'x-decorator-props': {
|
||||
@ -1051,7 +1056,7 @@ function generateActionSchema(type) {
|
||||
properties: {
|
||||
modal: {
|
||||
type: 'void',
|
||||
title: '添加数据',
|
||||
title: "{{ t('Add record') }}",
|
||||
'x-decorator': 'Form',
|
||||
'x-component': 'Action.Drawer',
|
||||
'x-component-props': {
|
||||
@ -1073,7 +1078,7 @@ function generateActionSchema(type) {
|
||||
key: uid(),
|
||||
type: 'void',
|
||||
name: uid(),
|
||||
title: '删除',
|
||||
title: "{{ t('Delete') }}",
|
||||
'x-align': 'right',
|
||||
'x-decorator': 'AddNew.Displayed',
|
||||
'x-decorator-props': {
|
||||
@ -1084,8 +1089,8 @@ function generateActionSchema(type) {
|
||||
'x-designable-bar': 'Table.Action.DesignableBar',
|
||||
'x-component-props': {
|
||||
confirm: {
|
||||
title: '删除数据',
|
||||
content: '删除后无法恢复,确定要删除吗?',
|
||||
title: "{{ t('Delete record') }}",
|
||||
content: "{{ t('Are you sure you want to delete it?') }}",
|
||||
},
|
||||
useAction: '{{ Table.useTableDestroyAction }}',
|
||||
},
|
||||
@ -1102,7 +1107,7 @@ function generateMenuActionSchema(type) {
|
||||
key: uid(),
|
||||
name: uid(),
|
||||
type: 'void',
|
||||
title: '查看',
|
||||
title: "{{ t('View') }}",
|
||||
'x-component': 'Action',
|
||||
'x-component-props': {
|
||||
type: 'link',
|
||||
@ -1112,7 +1117,7 @@ function generateMenuActionSchema(type) {
|
||||
properties: {
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
title: '查看数据',
|
||||
title: "{{ t('View record') }}",
|
||||
'x-component': 'Action.Drawer',
|
||||
'x-component-props': {
|
||||
bodyStyle: {
|
||||
@ -1128,7 +1133,7 @@ function generateMenuActionSchema(type) {
|
||||
properties: {
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
title: '详情',
|
||||
title: "{{ t('Details') }}",
|
||||
'x-designable-bar': 'Tabs.TabPane.DesignableBar',
|
||||
'x-component': 'Tabs.TabPane',
|
||||
'x-component-props': {},
|
||||
@ -1152,7 +1157,7 @@ function generateMenuActionSchema(type) {
|
||||
key: uid(),
|
||||
name: uid(),
|
||||
type: 'void',
|
||||
title: '编辑',
|
||||
title: "{{ t('Edit') }}",
|
||||
'x-component': 'Action',
|
||||
'x-component-props': {
|
||||
type: 'link',
|
||||
@ -1162,7 +1167,7 @@ function generateMenuActionSchema(type) {
|
||||
properties: {
|
||||
[uid()]: {
|
||||
type: 'void',
|
||||
title: '编辑数据',
|
||||
title: "{{ t('Edit record') }}",
|
||||
'x-decorator': 'Form',
|
||||
'x-decorator-props': {
|
||||
useResource: '{{ Table.useResource }}',
|
||||
@ -1188,7 +1193,7 @@ function generateMenuActionSchema(type) {
|
||||
key: uid(),
|
||||
name: uid(),
|
||||
type: 'void',
|
||||
title: '删除',
|
||||
title: "{{ t('Delete') }}",
|
||||
'x-component': 'Action',
|
||||
'x-designable-bar': 'Table.Action.DesignableBar',
|
||||
'x-action-type': 'destroy',
|
||||
@ -1196,8 +1201,8 @@ function generateMenuActionSchema(type) {
|
||||
useAction: '{{ Table.useTableDestroyAction }}',
|
||||
type: 'link',
|
||||
confirm: {
|
||||
title: '删除数据',
|
||||
content: '删除后无法恢复,确定要删除吗?',
|
||||
title: "{{ t('Delete record') }}",
|
||||
content: "{{ t('Are you sure you want to delete it?') }}",
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -1206,6 +1211,7 @@ function generateMenuActionSchema(type) {
|
||||
}
|
||||
|
||||
function AddActionButton() {
|
||||
const { t } = useTranslation();
|
||||
const [visible, setVisible] = useState(false);
|
||||
const displayed = useDisplayedMapContext();
|
||||
const { appendChild, remove } = useDesignable();
|
||||
@ -1222,12 +1228,12 @@ function AddActionButton() {
|
||||
onVisibleChange={setVisible}
|
||||
overlay={
|
||||
<Menu>
|
||||
<Menu.ItemGroup title={'启用操作'}>
|
||||
<Menu.ItemGroup title={t('Enable actions')}>
|
||||
{[
|
||||
{ title: '筛选', name: 'filter' },
|
||||
{ title: '导出', name: 'export' },
|
||||
{ title: '添加', name: 'create' },
|
||||
{ title: '删除', name: 'destroy' },
|
||||
{ title: t('Filter'), name: 'filter' },
|
||||
{ title: t('Export'), name: 'export' },
|
||||
{ title: t('Add new'), name: 'create' },
|
||||
{ title: t('Delete'), name: 'destroy' },
|
||||
].map((item) => (
|
||||
<SwitchMenuItem
|
||||
key={item.name}
|
||||
@ -1250,10 +1256,10 @@ function AddActionButton() {
|
||||
))}
|
||||
</Menu.ItemGroup>
|
||||
<Menu.Divider />
|
||||
<Menu.SubMenu title={'自定义'}>
|
||||
<Menu.Item style={{ minWidth: 120 }}>函数操作</Menu.Item>
|
||||
<Menu.Item>弹窗表单</Menu.Item>
|
||||
<Menu.Item>复杂弹窗</Menu.Item>
|
||||
<Menu.SubMenu disabled title={t('Customize')}>
|
||||
<Menu.Item style={{ minWidth: 120 }}>{t('Function')}</Menu.Item>
|
||||
<Menu.Item>{t('Popup form')}</Menu.Item>
|
||||
<Menu.Item>{t('Flexible popup')}</Menu.Item>
|
||||
</Menu.SubMenu>
|
||||
</Menu>
|
||||
}
|
||||
@ -1264,7 +1270,7 @@ function AddActionButton() {
|
||||
type={'dashed'}
|
||||
icon={<SettingOutlined />}
|
||||
>
|
||||
配置操作
|
||||
{t('Configure actions')}
|
||||
</Button>
|
||||
</Dropdown>
|
||||
);
|
||||
@ -1451,6 +1457,8 @@ const fieldsToSortColumns = (fields: any[]) => {
|
||||
Table.Filter = observer((props: any) => {
|
||||
const { service } = useTable();
|
||||
const { fieldNames = [] } = props;
|
||||
const compile = useCompile();
|
||||
const { t } = useTranslation();
|
||||
const { schema, DesignableBar } = useDesignable();
|
||||
const form = useMemo(() => createForm(), []);
|
||||
const { fields = [] } = useCollectionContext();
|
||||
@ -1498,7 +1506,7 @@ Table.Filter = observer((props: any) => {
|
||||
});
|
||||
}}
|
||||
>
|
||||
提交
|
||||
{t('Submit')}
|
||||
</Submit>
|
||||
</FormButtonGroup>
|
||||
</FormProvider>
|
||||
@ -1506,7 +1514,7 @@ Table.Filter = observer((props: any) => {
|
||||
}
|
||||
>
|
||||
<Button icon={<IconPicker type={icon} />}>
|
||||
{count > 0 ? `${count} 个筛选项` : schema.title}
|
||||
{count > 0 ? t('{{count}} filter items', { count }) : compile(schema.title)}
|
||||
<DesignableBar />
|
||||
</Button>
|
||||
</Popover>
|
||||
@ -1514,6 +1522,7 @@ Table.Filter = observer((props: any) => {
|
||||
});
|
||||
|
||||
Table.Filter.DesignableBar = () => {
|
||||
const { t } = useTranslation();
|
||||
const { schema, remove, refresh, insertAfter } = useDesignable();
|
||||
const [visible, setVisible] = useState(false);
|
||||
const displayed = useDisplayedMapContext();
|
||||
@ -1542,7 +1551,7 @@ Table.Filter.DesignableBar = () => {
|
||||
}}
|
||||
overlay={
|
||||
<Menu>
|
||||
<Menu.ItemGroup title={'可筛选字段'}>
|
||||
<Menu.ItemGroup title={t('Filterable fields')}>
|
||||
{fields
|
||||
.filter((collectionField) => {
|
||||
const option = interfaces.get(collectionField.interface);
|
||||
@ -1576,7 +1585,7 @@ Table.Filter.DesignableBar = () => {
|
||||
<Menu.Item
|
||||
onClick={async (e) => {
|
||||
setVisible(false);
|
||||
const values = await FormDialog('编辑按钮', () => {
|
||||
const values = await FormDialog(t('Edit button'), () => {
|
||||
return (
|
||||
<FormLayout layout={'vertical'}>
|
||||
<SchemaField
|
||||
@ -1585,14 +1594,14 @@ Table.Filter.DesignableBar = () => {
|
||||
properties: {
|
||||
title: {
|
||||
type: 'string',
|
||||
title: '按钮名称',
|
||||
title: t('Display name'),
|
||||
required: true,
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input',
|
||||
},
|
||||
icon: {
|
||||
type: 'string',
|
||||
title: '按钮图标',
|
||||
title: t('Icon'),
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'IconPicker',
|
||||
},
|
||||
@ -1615,7 +1624,7 @@ Table.Filter.DesignableBar = () => {
|
||||
refresh();
|
||||
}}
|
||||
>
|
||||
编辑按钮
|
||||
{t('Edit button')}
|
||||
</Menu.Item>
|
||||
<Menu.Divider />
|
||||
<Menu.Item
|
||||
@ -1630,7 +1639,7 @@ Table.Filter.DesignableBar = () => {
|
||||
setVisible(false);
|
||||
}}
|
||||
>
|
||||
隐藏
|
||||
{t('Hide')}
|
||||
</Menu.Item>
|
||||
</Menu>
|
||||
}
|
||||
@ -1644,6 +1653,7 @@ Table.Filter.DesignableBar = () => {
|
||||
};
|
||||
|
||||
Table.ExportActionDesignableBar = () => {
|
||||
const { t } = useTranslation();
|
||||
const { schema, remove, refresh, insertAfter } = useDesignable();
|
||||
const [visible, setVisible] = useState(false);
|
||||
const displayed = useDisplayedMapContext();
|
||||
@ -1672,7 +1682,7 @@ Table.ExportActionDesignableBar = () => {
|
||||
}}
|
||||
overlay={
|
||||
<Menu>
|
||||
<Menu.ItemGroup title={'导出字段'}>
|
||||
<Menu.ItemGroup title={t('Export fields')}>
|
||||
{fields.map((collectionField) => (
|
||||
<SwitchMenuItem
|
||||
title={collectionField?.uiSchema?.title}
|
||||
@ -1700,7 +1710,7 @@ Table.ExportActionDesignableBar = () => {
|
||||
<Menu.Item
|
||||
onClick={async (e) => {
|
||||
setVisible(false);
|
||||
const values = await FormDialog('编辑按钮', () => {
|
||||
const values = await FormDialog(t('Edit button'), () => {
|
||||
return (
|
||||
<FormLayout layout={'vertical'}>
|
||||
<SchemaField
|
||||
@ -1709,14 +1719,14 @@ Table.ExportActionDesignableBar = () => {
|
||||
properties: {
|
||||
title: {
|
||||
type: 'string',
|
||||
title: '按钮名称',
|
||||
title: t('Display name'),
|
||||
required: true,
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input',
|
||||
},
|
||||
icon: {
|
||||
type: 'string',
|
||||
title: '按钮图标',
|
||||
title: t('Icon'),
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'IconPicker',
|
||||
},
|
||||
@ -1739,7 +1749,7 @@ Table.ExportActionDesignableBar = () => {
|
||||
refresh();
|
||||
}}
|
||||
>
|
||||
编辑按钮
|
||||
{t('Edit button')}
|
||||
</Menu.Item>
|
||||
<Menu.Divider />
|
||||
<Menu.Item
|
||||
@ -1754,7 +1764,7 @@ Table.ExportActionDesignableBar = () => {
|
||||
setVisible(false);
|
||||
}}
|
||||
>
|
||||
隐藏
|
||||
{t('Hide')}
|
||||
</Menu.Item>
|
||||
</Menu>
|
||||
}
|
||||
@ -1769,9 +1779,10 @@ Table.ExportActionDesignableBar = () => {
|
||||
|
||||
Table.Operation = observer((props: any) => {
|
||||
const { designable, schema } = useDesignable();
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<div className={'nb-table-column'}>
|
||||
操作
|
||||
{t('Operations')}
|
||||
<Table.Operation.DesignableBar path={props.path} />
|
||||
</div>
|
||||
);
|
||||
@ -1788,6 +1799,7 @@ Table.Operation.Cell = observer((props: any) => {
|
||||
});
|
||||
|
||||
Table.Operation.DesignableBar = () => {
|
||||
const { t } = useTranslation();
|
||||
const { schema: columnSchema } = useDesignable();
|
||||
const groupSchema = Object.values(columnSchema.properties || {}).shift();
|
||||
const groupPath = getSchemaPath(groupSchema);
|
||||
@ -1821,11 +1833,11 @@ Table.Operation.DesignableBar = () => {
|
||||
}}
|
||||
overlay={
|
||||
<Menu>
|
||||
<Menu.ItemGroup title={'启用操作'}>
|
||||
<Menu.ItemGroup title={t('Enable actions')}>
|
||||
{[
|
||||
{ title: '查看', name: 'view' },
|
||||
{ title: '编辑', name: 'update' },
|
||||
{ title: '删除', name: 'destroy' },
|
||||
{ title: t('View'), name: 'view' },
|
||||
{ title: t('Edit'), name: 'update' },
|
||||
{ title: t('Delete'), name: 'destroy' },
|
||||
].map((item) => (
|
||||
<SwitchMenuItem
|
||||
key={item.name}
|
||||
@ -1845,10 +1857,12 @@ Table.Operation.DesignableBar = () => {
|
||||
))}
|
||||
</Menu.ItemGroup>
|
||||
<Menu.Divider />
|
||||
<Menu.SubMenu disabled title={'自定义'}>
|
||||
<Menu.Item style={{ minWidth: 120 }}>函数操作</Menu.Item>
|
||||
<Menu.Item>弹窗表单</Menu.Item>
|
||||
<Menu.Item>复杂弹窗</Menu.Item>
|
||||
<Menu.SubMenu disabled title={t('Customize')}>
|
||||
<Menu.Item style={{ minWidth: 120 }}>
|
||||
{t('Function')}
|
||||
</Menu.Item>
|
||||
<Menu.Item>{t('Popup form')}</Menu.Item>
|
||||
<Menu.Item>{t('Flexible popup')}</Menu.Item>
|
||||
</Menu.SubMenu>
|
||||
</Menu>
|
||||
}
|
||||
@ -1864,6 +1878,7 @@ Table.Operation.DesignableBar = () => {
|
||||
Table.Action = () => null;
|
||||
|
||||
Table.Action.DesignableBar = () => {
|
||||
const { t } = useTranslation();
|
||||
const { schema, remove, refresh, insertAfter } = useDesignable();
|
||||
const [visible, setVisible] = useState(false);
|
||||
const isPopup = Object.keys(schema.properties || {}).length > 0;
|
||||
@ -1894,7 +1909,7 @@ Table.Action.DesignableBar = () => {
|
||||
<Menu.Item
|
||||
onClick={async (e) => {
|
||||
setVisible(false);
|
||||
const values = await FormDialog('编辑按钮', () => {
|
||||
const values = await FormDialog(t('Edit button'), () => {
|
||||
return (
|
||||
<FormLayout layout={'vertical'}>
|
||||
<SchemaField
|
||||
@ -1903,14 +1918,14 @@ Table.Action.DesignableBar = () => {
|
||||
properties: {
|
||||
title: {
|
||||
type: 'string',
|
||||
title: '按钮名称',
|
||||
title: t('Display name'),
|
||||
required: true,
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input',
|
||||
},
|
||||
icon: {
|
||||
type: 'string',
|
||||
title: '按钮图标',
|
||||
title: t('Icon'),
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'IconPicker',
|
||||
},
|
||||
@ -1933,11 +1948,12 @@ Table.Action.DesignableBar = () => {
|
||||
refresh();
|
||||
}}
|
||||
>
|
||||
编辑按钮
|
||||
{t('Edit button')}
|
||||
</Menu.Item>
|
||||
{isPopup && (
|
||||
<Menu.Item>
|
||||
在{' '}
|
||||
<Trans t={t}>
|
||||
Open in
|
||||
<Select
|
||||
bordered={false}
|
||||
size={'small'}
|
||||
@ -1953,21 +1969,21 @@ Table.Action.DesignableBar = () => {
|
||||
}}
|
||||
>
|
||||
<Select.Option value={'Action.Modal'}>
|
||||
对话框
|
||||
Modal
|
||||
</Select.Option>
|
||||
<Select.Option value={'Action.Drawer'}>
|
||||
抽屉
|
||||
Drawer
|
||||
</Select.Option>
|
||||
<Select.Option value={'Action.Window'}>
|
||||
窗口
|
||||
Window
|
||||
</Select.Option>
|
||||
</Select>{' '}
|
||||
内打开
|
||||
</Select>
|
||||
</Trans>
|
||||
</Menu.Item>
|
||||
)}
|
||||
{!inActionBar && (
|
||||
<Menu.Item>
|
||||
点击表格行时触发
|
||||
{t('Trigger on click the table row')}
|
||||
<Switch size={'small'} defaultChecked />
|
||||
</Menu.Item>
|
||||
)}
|
||||
@ -1984,7 +2000,7 @@ Table.Action.DesignableBar = () => {
|
||||
setVisible(false);
|
||||
}}
|
||||
>
|
||||
隐藏
|
||||
{t('Hide')}
|
||||
</Menu.Item>
|
||||
</Menu>
|
||||
}
|
||||
@ -2052,6 +2068,7 @@ Table.Cell = observer((props: any) => {
|
||||
Table.Column = observer((props: any) => {
|
||||
const collectionField = useContext(CollectionFieldContext);
|
||||
const { schema, DesignableBar } = useDesignable();
|
||||
const compile = useCompile();
|
||||
const displayed = useDisplayedMapContext();
|
||||
useEffect(() => {
|
||||
if (collectionField?.name) {
|
||||
@ -2060,7 +2077,7 @@ Table.Column = observer((props: any) => {
|
||||
}, [collectionField, schema]);
|
||||
return (
|
||||
<div className={'nb-table-column'}>
|
||||
{schema.title || collectionField?.uiSchema?.title}
|
||||
{compile(schema.title || collectionField?.uiSchema?.title)}
|
||||
<DesignableBar />
|
||||
</div>
|
||||
);
|
||||
@ -2068,6 +2085,7 @@ Table.Column = observer((props: any) => {
|
||||
|
||||
Table.Column.DesignableBar = () => {
|
||||
const field = useField();
|
||||
const { t } = useTranslation();
|
||||
const { service, refresh: refreshTable } = useTable();
|
||||
// const fieldSchema = useFieldSchema();
|
||||
const { schema, remove, refresh, insertAfter } = useDesignable();
|
||||
@ -2098,7 +2116,7 @@ Table.Column.DesignableBar = () => {
|
||||
<Menu.Item
|
||||
onClick={async (e) => {
|
||||
setVisible(false);
|
||||
const values = await FormDialog('自定义列名称', () => {
|
||||
const values = await FormDialog(t('Custom name'), () => {
|
||||
return (
|
||||
<FormLayout layout={'vertical'}>
|
||||
<SchemaField
|
||||
@ -2107,14 +2125,14 @@ Table.Column.DesignableBar = () => {
|
||||
properties: {
|
||||
fieldName: {
|
||||
type: 'string',
|
||||
title: '原字段名称',
|
||||
title: t('Original name'),
|
||||
'x-read-pretty': true,
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input',
|
||||
},
|
||||
title: {
|
||||
type: 'string',
|
||||
title: '自定义列名称',
|
||||
title: t('Custom name'),
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input',
|
||||
},
|
||||
@ -2139,7 +2157,7 @@ Table.Column.DesignableBar = () => {
|
||||
});
|
||||
}}
|
||||
>
|
||||
自定义列名称
|
||||
{t('Custom column name')}
|
||||
</Menu.Item>
|
||||
{collectionField?.interface === 'linkTo' && (
|
||||
<Menu.Item>
|
||||
@ -2149,14 +2167,14 @@ Table.Column.DesignableBar = () => {
|
||||
justifyContent: 'space-between',
|
||||
}}
|
||||
>
|
||||
标签字段{' '}
|
||||
{t('Label field')}{' '}
|
||||
<Select
|
||||
value={
|
||||
schema?.['x-component-props']?.['fieldNames']?.[
|
||||
'label'
|
||||
]
|
||||
}
|
||||
placeholder={'默认为 ID 字段'}
|
||||
placeholder={t('Default is the ID field')}
|
||||
onChange={async (value) => {
|
||||
set(
|
||||
schema['x-component-props'],
|
||||
@ -2203,7 +2221,7 @@ Table.Column.DesignableBar = () => {
|
||||
// await removeSchema(s);
|
||||
}}
|
||||
>
|
||||
隐藏
|
||||
{t('Hide')}
|
||||
</Menu.Item>
|
||||
</Menu>
|
||||
}
|
||||
@ -2226,6 +2244,8 @@ Table.SortHandle = observer((props: any) => {
|
||||
});
|
||||
|
||||
Table.DesignableBar = observer((props) => {
|
||||
const { t } = useTranslation();
|
||||
const compile = useCompile();
|
||||
const field = useField();
|
||||
const { schema, refresh, deepRemove } = useDesignable();
|
||||
const [visible, setVisible] = useState(false);
|
||||
@ -2239,7 +2259,7 @@ Table.DesignableBar = observer((props) => {
|
||||
return (
|
||||
<div className={cls('designable-bar', { active: visible })}>
|
||||
<div className={'designable-info'}>
|
||||
{collection?.title || collection?.name}
|
||||
{compile(collection?.title || collection?.name)}
|
||||
</div>
|
||||
<span
|
||||
onClick={(e) => {
|
||||
@ -2269,7 +2289,7 @@ Table.DesignableBar = observer((props) => {
|
||||
}}
|
||||
>
|
||||
<div className={'nb-space-between'}>
|
||||
显示序号{' '}
|
||||
{t('Display order number')}{' '}
|
||||
<Switch
|
||||
size={'small'}
|
||||
checked={field.componentProps.showIndex}
|
||||
@ -2289,7 +2309,8 @@ Table.DesignableBar = observer((props) => {
|
||||
}}
|
||||
>
|
||||
<div className={'nb-space-between'}>
|
||||
启用拖拽排序{' '}
|
||||
{t('Enable drag and drop sorting')}
|
||||
|
||||
<Switch
|
||||
size={'small'}
|
||||
checked={field.componentProps.dragSort}
|
||||
@ -2314,7 +2335,9 @@ Table.DesignableBar = observer((props) => {
|
||||
};
|
||||
},
|
||||
);
|
||||
const values = await FormDialog('设置默认排序', () => {
|
||||
const values = await FormDialog(
|
||||
t('Set default sorting rules'),
|
||||
() => {
|
||||
return (
|
||||
<FormLayout layout={'vertical'}>
|
||||
<SchemaField
|
||||
@ -2342,7 +2365,9 @@ Table.DesignableBar = observer((props) => {
|
||||
type: 'string',
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Select',
|
||||
enum: fieldsToSortColumns(fields),
|
||||
enum: fieldsToSortColumns(
|
||||
fields,
|
||||
),
|
||||
'x-component-props': {
|
||||
style: {
|
||||
width: 260,
|
||||
@ -2357,9 +2382,12 @@ Table.DesignableBar = observer((props) => {
|
||||
optionType: 'button',
|
||||
},
|
||||
enum: [
|
||||
{ label: '正序', value: 'asc' },
|
||||
{
|
||||
label: '倒序',
|
||||
label: t('ASC'),
|
||||
value: 'asc',
|
||||
},
|
||||
{
|
||||
label: t('DESC'),
|
||||
value: 'desc',
|
||||
},
|
||||
],
|
||||
@ -2377,7 +2405,7 @@ Table.DesignableBar = observer((props) => {
|
||||
properties: {
|
||||
add: {
|
||||
type: 'void',
|
||||
title: '添加排序字段',
|
||||
title: t('Add sort field'),
|
||||
'x-component': 'ArrayItems.Addition',
|
||||
},
|
||||
},
|
||||
@ -2387,7 +2415,8 @@ Table.DesignableBar = observer((props) => {
|
||||
/>
|
||||
</FormLayout>
|
||||
);
|
||||
}).open({
|
||||
},
|
||||
).open({
|
||||
initialValues: {
|
||||
defaultSort,
|
||||
},
|
||||
@ -2404,14 +2433,14 @@ Table.DesignableBar = observer((props) => {
|
||||
console.log('defaultSort', sort);
|
||||
}}
|
||||
>
|
||||
设置默认排序
|
||||
{t('Set default sorting rules')}
|
||||
</Menu.Item>
|
||||
)}
|
||||
<Menu.Item
|
||||
key={'defaultFilter'}
|
||||
onClick={async () => {
|
||||
const { defaultFilter } = await FormDialog(
|
||||
'设置数据范围',
|
||||
t('Set the data scope'),
|
||||
() => {
|
||||
return (
|
||||
<FormLayout layout={'vertical'}>
|
||||
@ -2443,16 +2472,22 @@ Table.DesignableBar = observer((props) => {
|
||||
setVisible(false);
|
||||
}}
|
||||
>
|
||||
设置数据范围
|
||||
{t('Set the data scope')}
|
||||
</Menu.Item>
|
||||
<Menu.Item key={'defaultPageSize'}>
|
||||
每页默认显示{' '}
|
||||
<Trans>
|
||||
{'Display '}
|
||||
<Select
|
||||
bordered={false}
|
||||
size={'small'}
|
||||
onChange={(value) => {
|
||||
const componentProps = schema['x-component-props'] || {};
|
||||
set(componentProps, 'pagination.defaultPageSize', value);
|
||||
const componentProps =
|
||||
schema['x-component-props'] || {};
|
||||
set(
|
||||
componentProps,
|
||||
'pagination.defaultPageSize',
|
||||
value,
|
||||
);
|
||||
set(componentProps, 'pagination.pageSize', value);
|
||||
schema['x-component-props'] = componentProps;
|
||||
field.componentProps.pagination.pageSize = value;
|
||||
@ -2467,16 +2502,17 @@ Table.DesignableBar = observer((props) => {
|
||||
<Select.Option value={20}>20</Select.Option>
|
||||
<Select.Option value={50}>50</Select.Option>
|
||||
<Select.Option value={100}>100</Select.Option>
|
||||
</Select>{' '}
|
||||
条
|
||||
</Select>
|
||||
{' items per page'}
|
||||
</Trans>
|
||||
</Menu.Item>
|
||||
<Menu.Divider />
|
||||
<Menu.Item
|
||||
key={'delete'}
|
||||
onClick={async () => {
|
||||
Modal.confirm({
|
||||
title: '删除区块',
|
||||
content: '删除后无法恢复,确定要删除吗?',
|
||||
title: t('Delete block'),
|
||||
content: t('Are you sure you want to delete it?'),
|
||||
onOk: async () => {
|
||||
const removed = deepRemove();
|
||||
// console.log({ removed })
|
||||
@ -2487,7 +2523,7 @@ Table.DesignableBar = observer((props) => {
|
||||
});
|
||||
}}
|
||||
>
|
||||
删除
|
||||
{t('Delete')}
|
||||
</Menu.Item>
|
||||
</Menu>
|
||||
}
|
||||
|
@ -26,6 +26,8 @@ import { DragHandle, SortableItem } from '../../components/Sortable';
|
||||
import { DndContext, DragOverlay } from '@dnd-kit/core';
|
||||
import { FormDialog, FormLayout } from '@formily/antd';
|
||||
import IconPicker from '../../components/icon-picker';
|
||||
import { useCompile } from '../../hooks/useCompile';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const useTabs = ({ singleton }) => {
|
||||
const tabsField = useField();
|
||||
@ -65,6 +67,7 @@ export const Tabs: any = observer((props: any) => {
|
||||
const tabs = useTabs({ singleton });
|
||||
const [dragOverlayContent, setDragOverlayContent] = useState('');
|
||||
const { createSchema, removeSchema, updateSchema } = useClient();
|
||||
const { t } = useTranslation();
|
||||
|
||||
const moveToAfter = (path1, path2) => {
|
||||
if (!path1 || !path2) {
|
||||
@ -126,7 +129,7 @@ export const Tabs: any = observer((props: any) => {
|
||||
type={'dashed'}
|
||||
icon={<PlusOutlined />}
|
||||
onClick={async () => {
|
||||
const values = await FormDialog('添加标签页', () => {
|
||||
const values = await FormDialog('Add tab', () => {
|
||||
return (
|
||||
<FormLayout layout={'vertical'}>
|
||||
<SchemaField
|
||||
@ -135,14 +138,14 @@ export const Tabs: any = observer((props: any) => {
|
||||
properties: {
|
||||
title: {
|
||||
type: 'string',
|
||||
title: '标签名称',
|
||||
title: t('Display name'),
|
||||
required: true,
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input',
|
||||
},
|
||||
icon: {
|
||||
type: 'string',
|
||||
title: '标签图标',
|
||||
title: t('Icon'),
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'IconPicker',
|
||||
},
|
||||
@ -179,7 +182,7 @@ export const Tabs: any = observer((props: any) => {
|
||||
await createSchema(data);
|
||||
}}
|
||||
>
|
||||
添加标签页
|
||||
{t('Add tab')}
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
@ -207,17 +210,19 @@ export const Tabs: any = observer((props: any) => {
|
||||
|
||||
Tabs.TabPane = observer((props: any) => {
|
||||
const { schema, DesignableBar } = useDesignable();
|
||||
const compile = useCompile();
|
||||
const title = compile(schema.title);
|
||||
return (
|
||||
<SortableItem
|
||||
id={schema.name}
|
||||
data={{
|
||||
title: schema.title,
|
||||
title,
|
||||
path: getSchemaPath(schema),
|
||||
}}
|
||||
>
|
||||
<div className={'nb-tab-pane'}>
|
||||
<IconPicker type={props.icon} />
|
||||
{schema.title} <DesignableBar />
|
||||
{title} <DesignableBar />
|
||||
</div>
|
||||
</SortableItem>
|
||||
);
|
||||
@ -228,6 +233,7 @@ Tabs.DesignableBar = () => {
|
||||
const [visible, setVisible] = useState(false);
|
||||
const field = useField();
|
||||
const { createSchema, removeSchema, updateSchema } = useClient();
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<div className={cls('designable-bar', { active: visible })}>
|
||||
<span
|
||||
@ -256,7 +262,7 @@ Tabs.DesignableBar = () => {
|
||||
updateSchema(schema);
|
||||
}}
|
||||
>
|
||||
禁用标签页 <span style={{ marginRight: 24 }}></span>{' '}
|
||||
{t('Disable tabs')} <span style={{ marginRight: 24 }}></span>{' '}
|
||||
<Switch
|
||||
size={'small'}
|
||||
checked={!!field.componentProps.singleton}
|
||||
@ -278,6 +284,7 @@ Tabs.TabPane.DesignableBar = () => {
|
||||
const [visible, setVisible] = useState(false);
|
||||
const field = useField();
|
||||
const { createSchema, removeSchema, updateSchema } = useClient();
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<div className={cls('designable-bar', { active: visible })}>
|
||||
<span
|
||||
@ -299,7 +306,7 @@ Tabs.TabPane.DesignableBar = () => {
|
||||
<Menu.Item
|
||||
onClick={async () => {
|
||||
setVisible(false);
|
||||
const values = await FormDialog('编辑标签页', () => {
|
||||
const values = await FormDialog(t('Edit tab'), () => {
|
||||
return (
|
||||
<FormLayout layout={'vertical'}>
|
||||
<SchemaField
|
||||
@ -308,14 +315,14 @@ Tabs.TabPane.DesignableBar = () => {
|
||||
properties: {
|
||||
title: {
|
||||
type: 'string',
|
||||
title: '标签名称',
|
||||
title: t('Display name'),
|
||||
required: true,
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input',
|
||||
},
|
||||
icon: {
|
||||
type: 'string',
|
||||
title: '标签图标',
|
||||
title: t('Icon'),
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'IconPicker',
|
||||
},
|
||||
@ -339,15 +346,15 @@ Tabs.TabPane.DesignableBar = () => {
|
||||
updateSchema(schema);
|
||||
}}
|
||||
>
|
||||
编辑标签页
|
||||
{t('Edit tab')}
|
||||
</Menu.Item>
|
||||
<Menu.Divider />
|
||||
<Menu.Item
|
||||
onClick={async () => {
|
||||
setVisible(false);
|
||||
Modal.confirm({
|
||||
title: '删除标签页',
|
||||
content: '删除后无法恢复,确定要删除吗?',
|
||||
title: t('Delete tab'),
|
||||
content: t('Are you sure you want to delete it?'),
|
||||
onOk: async () => {
|
||||
const data = remove();
|
||||
await removeSchema(data);
|
||||
@ -355,7 +362,7 @@ Tabs.TabPane.DesignableBar = () => {
|
||||
});
|
||||
}}
|
||||
>
|
||||
删除
|
||||
{t('Delete')}
|
||||
</Menu.Item>
|
||||
</Menu>
|
||||
}
|
||||
|
@ -28,6 +28,7 @@ import DownloadOutlined from '@ant-design/icons/DownloadOutlined';
|
||||
import './style.less';
|
||||
import cls from 'classnames';
|
||||
import { saveAs } from 'file-saver';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const toArr = (value) => {
|
||||
if (!isValid(value)) {
|
||||
@ -301,6 +302,7 @@ Upload.Attachment = connect(
|
||||
const images = fileList;
|
||||
const [photoIndex, setPhotoIndex] = useState(0);
|
||||
const [visible, setVisible] = useState(false);
|
||||
const { t } = useTranslation();
|
||||
useEffect(() => {
|
||||
if (sync) {
|
||||
setFileList(toFileList(value));
|
||||
@ -346,7 +348,7 @@ Upload.Attachment = connect(
|
||||
onClick={handleClick}
|
||||
>
|
||||
{file.status === 'uploading'
|
||||
? '上传中...'
|
||||
? t('Uploading')
|
||||
: file.title}
|
||||
</a>
|
||||
</span>
|
||||
@ -427,7 +429,7 @@ Upload.Attachment = connect(
|
||||
{!disabled && (multiple || toArr(value).length < 1) && (
|
||||
<span>
|
||||
<PlusOutlined />
|
||||
<br /> 上传
|
||||
<br /> {t('Upload')}
|
||||
</span>
|
||||
)}
|
||||
</AntdUpload>
|
||||
|
@ -11,11 +11,12 @@ const program = new commander.Command(packageJson.name)
|
||||
.version(packageJson.version)
|
||||
.option('--simple', 'create nocobase app without install dependencies')
|
||||
.option('--quickstart', 'create quickstart nocobase app')
|
||||
.option('--lang [lang]', 'language settings')
|
||||
.arguments('<project-directory>')
|
||||
.usage(`${chalk.green('<project-directory>')}`)
|
||||
.action(async (directory, options) => {
|
||||
console.log(
|
||||
`Creating a new Nocobase application at ${chalk.green(directory)}.`,
|
||||
`Creating a new NocoBase application at ${chalk.green(directory)}.`,
|
||||
);
|
||||
console.log('Creating files.');
|
||||
|
||||
@ -65,7 +66,7 @@ const program = new commander.Command(packageJson.name)
|
||||
|
||||
if (options.quickstart) {
|
||||
// Using Sqlite as Database
|
||||
const prefix = chalk.yellow('Nocobase init');
|
||||
const prefix = chalk.yellow('NocoBase init');
|
||||
const initLoader = ora(prefix).start();
|
||||
|
||||
try {
|
||||
@ -76,7 +77,7 @@ const program = new commander.Command(packageJson.name)
|
||||
.join(' ')}`;
|
||||
};
|
||||
|
||||
const init = runInit(fullPath);
|
||||
const init = runInit(fullPath, ['--import-demo', `--lang=${options.lang||'en-US'}`]);
|
||||
init.stderr.on('data', initLog);
|
||||
init.stdout.on('data', initLog);
|
||||
await init;
|
||||
|
@ -23,6 +23,10 @@ export function runStart(path) {
|
||||
return runYarn(path, ['run', 'start']);
|
||||
}
|
||||
|
||||
export function runInit(path) {
|
||||
return runYarn(path, ['run', 'nocobase', 'init', hasYarn() ? '--import-demo' : '-- --import-demo']);
|
||||
export function runInit(path, args: any[] = []) {
|
||||
if (!hasYarn()) {
|
||||
args.unshift('--');
|
||||
}
|
||||
console.log('run init', args);
|
||||
return runYarn(path, ['run', 'nocobase', 'init', ...args]);
|
||||
}
|
||||
|
1567
packages/plugin-client/src/db/en-US/part1/01-ui_schemas.sql
Normal file
1567
packages/plugin-client/src/db/en-US/part1/01-ui_schemas.sql
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,6 @@
|
||||
DELETE FROM "collections";
|
||||
INSERT INTO "collections" ("name", "logging", "title", "privilege", "sortable", "options", "sort", "created_at", "updated_at", "ui_schema_key") VALUES
|
||||
('users', '1', '{{t("Users")}}', 'undelete', '"sort"', '{"createdBy":false,"updatedBy":false}', 2, '2021-09-02 15:07:56.914+00', '2021-09-15 00:59:20.676+00', NULL),
|
||||
('t_fsveob6p269', '1', 'Customers', NULL, '"sort"', '{}', 5, '2021-09-12 01:05:52.722+00', '2021-09-18 04:15:23.113+00', NULL),
|
||||
('t_geso7fru7a9', '1', 'Orders', NULL, '"sort"', '{}', 4, '2021-09-12 01:06:05.19+00', '2021-09-18 04:15:42.566+00', NULL),
|
||||
('t_2uhu4szs1kq', '1', 'Tasks', NULL, '"sort"', '{}', 3, '2021-09-03 08:17:30.495+00', '2021-09-18 04:15:42.572+00', NULL);
|
52
packages/plugin-client/src/db/en-US/part1/03-fields.sql
Normal file
52
packages/plugin-client/src/db/en-US/part1/03-fields.sql
Normal file
@ -0,0 +1,52 @@
|
||||
DELETE FROM "fields";
|
||||
INSERT INTO "fields" ("key", "name", "interface", "data_type", "privilege", "state", "options", "sort", "created_at", "updated_at", "parent_key", "collection_name", "ui_schema_key", "reverse_key") VALUES
|
||||
('aun85p76s0v', 'f_l8uuiwcnlw9', 'textarea', 'text', NULL, 1, '{}', 8, '2021-09-12 08:18:46.92+00', '2021-09-12 08:18:46.935+00', NULL, 't_2uhu4szs1kq', 'c2pallk0lge', NULL),
|
||||
('sj5p2y4ac06', '70enejazumv', 'updatedAt', 'date', 'undelete', 1, '{"field":"updated_at"}', 2, '2021-09-03 08:17:30.543+00', '2021-09-03 08:17:30.555+00', NULL, 't_2uhu4szs1kq', 'lchrxtjm3d5', NULL),
|
||||
('1fvb1qre4ut', 'baa90jd887d', 'updatedBy', 'belongsTo', 'undelete', 1, '{"target":"users","foreignKey":"updated_by_id"}', 3, '2021-09-03 08:17:30.579+00', '2021-09-18 04:16:11.834+00', NULL, 't_2uhu4szs1kq', 'd3zwndj0gdt', NULL),
|
||||
('78h1q25dt1h', 'wtojfhp8nwl', 'createdBy', 'belongsTo', 'undelete', 1, '{"target":"users","foreignKey":"created_by_id"}', 2, '2021-09-03 08:17:30.563+00', '2021-09-18 04:16:11.834+00', NULL, 't_2uhu4szs1kq', 'uxcvj4473q9', NULL),
|
||||
('s30o2rkxcht', 'f_hwenour8ara', 'string', 'string', NULL, 1, '{}', 5, '2021-09-03 08:18:44.958+00', '2021-09-03 08:18:44.975+00', NULL, 't_2uhu4szs1kq', 'c6qmyf4uzl9', NULL),
|
||||
('e76mvcf7a1r', 'f_hznqtmqljb2', 'datetime', 'date', NULL, 1, '{}', 6, '2021-09-03 08:18:44.984+00', '2021-09-03 08:18:45+00', NULL, 't_2uhu4szs1kq', '7u0cu6nfu44', NULL),
|
||||
('c385a9rhd6d', 'f_u4i0jrp4uo6', 'radioGroup', 'string', NULL, 1, '{}', 7, '2021-09-03 08:18:45.009+00', '2021-09-03 08:18:45.028+00', NULL, 't_2uhu4szs1kq', '5de6xmem8vw', NULL),
|
||||
('8ms3ivkxaku', '8ke6k4er30w', 'createdAt', 'date', 'undelete', 1, '{"field":"created_at"}', 1, '2021-09-03 08:17:30.522+00', '2021-09-03 08:17:30.536+00', NULL, 't_2uhu4szs1kq', 'y9y4mgjy6ot', NULL),
|
||||
('ymwwuuje5cf', 'vygajfyejo0', 'updatedBy', 'belongsTo', 'undelete', 1, '{"target":"users","foreignKey":"updated_by_id"}', 3, '2021-09-12 01:05:52.791+00', '2021-09-18 04:16:11.834+00', NULL, 't_fsveob6p269', 'g6fgjhxwqdt', NULL),
|
||||
('kru7yomwffj', 'f_kk4nspj1i28', 'textarea', 'text', NULL, 1, '{}', 13, '2021-09-12 01:13:43.315+00', '2021-09-14 02:50:54.757+00', NULL, 't_fsveob6p269', 'ic1crmml3ww', NULL),
|
||||
('xjnnqtckv6o', 'f_x9kmuovlm79', 'radioGroup', 'string', NULL, 1, '{}', 11, '2021-09-12 01:13:43.241+00', '2021-09-14 02:50:54.738+00', NULL, 't_fsveob6p269', 'cntdgyegzk1', NULL),
|
||||
('hfry2ook2w4', 'f_n6snaop9d4y', 'textarea', 'string', NULL, 1, '{}', 10, '2021-09-12 01:17:01.062+00', '2021-09-14 02:50:54.728+00', NULL, 't_fsveob6p269', 'o21p57oi4ci', NULL),
|
||||
('zobi3o3dqzp', 'f_61znsfh307m', 'select', 'string', NULL, 1, '{}', 8, '2021-09-12 01:17:01.042+00', '2021-09-14 02:50:54.697+00', NULL, 't_fsveob6p269', 'zncs2fmi3md', NULL),
|
||||
('gjc3mks1xvj', 'f_bysgds7j36p', 'datetime', 'date', NULL, 1, '{}', 9, '2021-09-12 01:13:43.26+00', '2021-09-14 02:50:54.713+00', NULL, 't_fsveob6p269', 'wy9l25k1k8n', NULL),
|
||||
('lie1tta3peq', 'f_3det6kr3vn8', 'phone', 'string', NULL, 1, '{}', 7, '2021-09-12 01:13:43.221+00', '2021-09-14 02:50:54.686+00', NULL, 't_fsveob6p269', 'd0vxh9zspr0', NULL),
|
||||
('9cpd377df7t', 'f_tdoe0q00xc6', 'attachment', 'belongsToMany', NULL, 1, '{"target":"attachments","through":"t_jh7a28dsfzi","foreignKey":"f_xg3mysbjfra","otherKey":"f_gc7ppj0b7n1","sourceKey":"id","targetKey":"id"}', 12, '2021-09-12 01:13:43.292+00', '2021-09-12 08:41:20.155+00', NULL, 't_fsveob6p269', 'mz5lwuvl3ne', NULL),
|
||||
('mnglxpxjqs4', 'f_vgw4f62h16e', 'string', 'string', NULL, 1, '{}', 6, '2021-09-12 01:13:43.204+00', '2021-09-12 01:13:43.215+00', NULL, 't_fsveob6p269', 'r9i0nuz6gaa', NULL),
|
||||
('f_c8mes0kp1zt', 'f_c8mes0kp1zt', 'linkTo', 'belongsToMany', NULL, 1, '{"through":"t_bphcojtl8bx","foreignKey":"f_cn6a3p0wq2p","otherKey":"f_4x6u1waa8r6","sourceKey":"id","targetKey":"id","target":"t_geso7fru7a9"}', 5, '2021-09-12 01:09:26.259+00', '2021-09-12 01:13:43.195+00', NULL, 't_fsveob6p269', 'h73wygfixrg', 'nb09uq85geu'),
|
||||
('bz701wfev96', 'xkllcgbvvmt', 'createdBy', 'belongsTo', 'undelete', 1, '{"target":"users","foreignKey":"created_by_id"}', 2, '2021-09-12 01:05:52.77+00', '2021-09-18 04:16:11.834+00', NULL, 't_fsveob6p269', 'si4x29vvkeb', NULL),
|
||||
('mqcm1jb1ziw', '77trwzoaaei', 'createdAt', 'date', 'undelete', 1, '{"field":"created_at"}', 1, '2021-09-12 01:05:52.734+00', '2021-09-12 01:05:52.746+00', NULL, 't_fsveob6p269', '6zt8a6vfmeg', NULL),
|
||||
('2abol7bhbmj', 'uahfxi6okcs', 'updatedAt', 'date', 'undelete', 1, '{"field":"updated_at"}', 2, '2021-09-12 01:05:52.753+00', '2021-09-12 01:05:52.765+00', NULL, 't_fsveob6p269', 'q1bwolkkq5w', NULL),
|
||||
('19r6wt5b4m3', 'f_nlgk67tpdql', 'select', 'string', NULL, 1, '{}', 7, '2021-09-12 01:09:26.235+00', '2021-09-12 01:09:26.245+00', NULL, 't_geso7fru7a9', 'e5r226qqi20', NULL),
|
||||
('nb09uq85geu', 'f_kkopbnfdd0v', 'linkTo', 'belongsToMany', NULL, 1, '{"through":"t_bphcojtl8bx","foreignKey":"f_4x6u1waa8r6","otherKey":"f_cn6a3p0wq2p","sourceKey":"id","targetKey":"id","target":"t_fsveob6p269"}', 6, '2021-09-12 01:09:26.221+00', '2021-09-12 01:09:26.278+00', NULL, 't_geso7fru7a9', 'kmx147xwkrp', 'f_c8mes0kp1zt'),
|
||||
('nv0iw8wdxmz', '5bjnabydou3', 'createdAt', 'date', 'undelete', 1, '{"field":"created_at"}', 1, '2021-09-12 01:06:05.199+00', '2021-09-12 01:06:05.21+00', NULL, 't_geso7fru7a9', 'u1767w73vdn', NULL),
|
||||
('lu1ibrb0yi2', '44fpkg5ga5n', 'updatedAt', 'date', 'undelete', 1, '{"field":"updated_at"}', 2, '2021-09-12 01:06:05.215+00', '2021-09-12 01:06:05.225+00', NULL, 't_geso7fru7a9', 'fmweeu589m9', NULL),
|
||||
('fp2hcdcmxzm', 'qbe1q17p9kh', 'updatedBy', 'belongsTo', 'undelete', 1, '{"target":"users","foreignKey":"updated_by_id"}', 3, '2021-09-12 01:06:05.245+00', '2021-09-18 04:16:11.834+00', NULL, 't_geso7fru7a9', 'dzc486mzccr', NULL),
|
||||
('qpme60wf4lt', '1jkpjg7vkgi', 'createdBy', 'belongsTo', 'undelete', 1, '{"target":"users","foreignKey":"created_by_id"}', 2, '2021-09-12 01:06:05.23+00', '2021-09-18 04:16:11.834+00', NULL, 't_geso7fru7a9', 'bi9n4qdvvk2', NULL),
|
||||
('0qx4mudmft8', 'f_umjewufbyhj', 'datetime', 'date', NULL, 1, '{}', 5, '2021-09-12 01:09:26.202+00', '2021-09-12 01:09:26.215+00', NULL, 't_geso7fru7a9', 'yo6wjwgsfx2', NULL),
|
||||
('ckyhgqq0jru', 'f_niymyj0no38', 'string', 'string', NULL, 1, '{}', 8, '2021-09-12 07:36:53.506+00', '2021-09-12 07:36:53.518+00', NULL, 't_geso7fru7a9', 'x6j2o6xw1by', NULL),
|
||||
('f_80zv5suy9t6', 'email', 'email', 'string', 'undelete', 1, '{"unique":true}', 4, '2021-09-02 15:07:57.001+00', '2021-09-18 04:16:11.839+00', NULL, 'users', '5nqs5glgn5c', NULL),
|
||||
('f_dpll75sxhu6', 'token', 'password', 'string', 'undelete', 0, '{"unique":true,"hidden":true}', 5, '2021-09-02 15:07:57.052+00', '2021-09-02 15:07:57.052+00', NULL, 'users', NULL, NULL),
|
||||
('f_v3pog2zsalc', 'reset_token', 'password', 'string', 'undelete', 0, '{"unique":true,"hidden":true}', 6, '2021-09-02 15:07:57.059+00', '2021-09-02 15:07:57.059+00', NULL, 'users', NULL, NULL),
|
||||
('f_6rhh0scyw9k', 'nickname', 'string', 'string', NULL, 1, '{}', 1, '2021-09-02 15:07:56.974+00', '2021-09-12 00:56:41.776+00', NULL, 'users', 'dtu7erjj0q8', NULL),
|
||||
('f_j367murpzm9', 'password', 'password', 'password', 'undelete', 1, '{}', 2, '2021-09-02 15:07:57.029+00', '2021-09-18 04:16:11.834+00', NULL, 'users', 'a65exd8qcuo', NULL),
|
||||
('lmls9t34zne', 'f_xmjn5cfl9co', 'textarea', 'text', NULL, 1, '{}', 10, '2021-09-02 22:28:32.838+00', '2021-09-02 22:28:32.855+00', NULL, NULL, 'hej1gpzthf3', NULL),
|
||||
('sq3hj75dnmk', 'f_jdlw4uf6vfv', 'number', 'float', NULL, 1, '{}', 9, '2021-09-02 22:28:32.82+00', '2021-09-02 22:28:32.83+00', NULL, NULL, 'e5t9w7t3rxu', NULL),
|
||||
('xwhnxsil7b1', 'f_n0snwtdes3r', 'chinaRegion', 'belongsToMany', NULL, 1, '{"target":"china_regions","targetKey":"code","through":"t_by1bsepp8p4","foreignKey":"f_vqbqkbjmucq","otherKey":"f_ux2lh2en547","sourceKey":"id"}', 8, '2021-09-02 22:28:32.8+00', '2021-09-02 22:28:32.814+00', NULL, NULL, '4an73nd4bxh', NULL),
|
||||
('wolxy2l6xp2', 'f_jbqopur80lk', 'attachment', 'belongsToMany', NULL, 1, '{"target":"attachments","through":"t_mrsootcimgg","foreignKey":"f_moakulo9ak1","otherKey":"f_27xvqwj1o9s","sourceKey":"id","targetKey":"id"}', 7, '2021-09-02 22:28:32.777+00', '2021-09-02 22:28:32.792+00', NULL, NULL, '4blpztuxkha', NULL),
|
||||
('2wpjada7upn', 'f_lov82rwvxgk', 'multipleSelect', 'json', NULL, 1, '{}', 6, '2021-09-02 22:27:03.764+00', '2021-09-02 22:27:03.776+00', NULL, NULL, 'exjytl34657', NULL),
|
||||
('ybbxmw9ifwf', 'f_lwyvh77c122', 'string', 'string', NULL, 1, '{}', 5, '2021-09-02 22:27:03.741+00', '2021-09-02 22:27:03.758+00', NULL, NULL, 'xe5j6tk6y52', NULL),
|
||||
('cy37tmd1aa5', '2e5im9hsrau', 'updatedAt', 'date', 'undelete', 1, '{"field":"updated_at"}', 2, '2021-09-02 22:24:30.263+00', '2021-09-02 22:24:30.282+00', NULL, NULL, 'ue90wlv7r26', NULL),
|
||||
('9zmg4gsrbs0', 'ccdop3v4iqw', 'createdAt', 'date', 'undelete', 1, '{"field":"created_at"}', 1, '2021-09-02 22:24:30.239+00', '2021-09-02 22:24:30.255+00', NULL, NULL, 'qc0b0d2xfo4', NULL),
|
||||
('f_1eni2gp5w3g', 'action_logs', 'linkTo', 'hasMany', NULL, 0, '{"target":"action_logs","title":"数据动态","foreignKey":"index","scope":{"collection_name":"t_n93qitmhzty"},"constraints":false}', 7, '2021-09-02 22:24:30.219+00', '2021-09-02 22:24:30.219+00', NULL, NULL, NULL, NULL),
|
||||
('exfseozu257', '3s4pr34nuvz', 'updatedBy', 'belongsTo', 'undelete', 1, '{"target":"users","foreignKey":"updated_by_id"}', 3, '2021-09-12 01:06:55.172+00', '2021-09-18 04:16:11.834+00', NULL, NULL, 'k40ozwnisyr', NULL),
|
||||
('f_u5fajgprjha', 'action_logs', 'linkTo', 'hasMany', NULL, 0, '{"target":"action_logs","title":"数据动态","foreignKey":"index","scope":{"collection_name":"users"},"constraints":false}', 1, '2021-09-02 15:07:56.957+00', '2021-09-02 15:07:57.071+00', NULL, NULL, NULL, NULL),
|
||||
('b818d9mhozu', '8ly3cyiosfe', 'createdBy', 'belongsTo', 'undelete', 1, '{"target":"users","foreignKey":"created_by_id"}', 2, '2021-09-02 22:24:30.286+00', '2021-09-18 04:16:11.834+00', NULL, NULL, '32q17i8jcg9', NULL),
|
||||
('x3rcr6i0hy1', 'c9mtu486512', 'updatedBy', 'belongsTo', 'undelete', 1, '{"target":"users","foreignKey":"updated_by_id"}', 3, '2021-09-02 22:24:30.301+00', '2021-09-18 04:16:11.834+00', NULL, NULL, '1keis1kmsh9', NULL),
|
||||
('t6knha71oq1', 'fcgtvpd3jr9', 'createdBy', 'belongsTo', 'undelete', 1, '{"target":"users","foreignKey":"created_by_id"}', 2, '2021-09-12 01:06:55.154+00', '2021-09-18 04:16:11.834+00', NULL, NULL, 'ya58lec57fp', NULL),
|
||||
('drhtax7pxlw', 'nbxtd3jzbw1', 'updatedAt', 'date', 'undelete', 1, '{"field":"updated_at"}', 2, '2021-09-12 01:06:55.14+00', '2021-09-12 01:06:55.149+00', NULL, NULL, '1l9qav1f97v', NULL),
|
||||
('sbrf1cdkpb9', 'h1f9o1xvevb', 'createdAt', 'date', 'undelete', 1, '{"field":"created_at"}', 1, '2021-09-12 01:06:55.123+00', '2021-09-12 01:06:55.133+00', NULL, NULL, 'oo7ejuze28i', NULL);
|
7
packages/plugin-client/src/db/en-US/part1/04-routes.sql
Normal file
7
packages/plugin-client/src/db/en-US/part1/04-routes.sql
Normal file
@ -0,0 +1,7 @@
|
||||
DELETE FROM "routes";
|
||||
INSERT INTO "routes" ("key", "type", "options", "sort", "created_at", "updated_at", "parent_key", "ui_schema_key") VALUES
|
||||
('r_94b8nz6evyh', 'redirect', '{"from":"/","to":"/admin","exact":true}', 1, '2021-09-02 15:07:57.162+00', '2021-09-02 15:07:57.162+00', NULL, NULL),
|
||||
('r_w1sa2lfk44v', 'route', '{"path":"/admin/:name(.+)?","component":"AdminLayout","title":"Admin"}', 2, '2021-09-02 15:07:57.17+00', '2021-09-02 15:07:57.185+00', NULL, 'qqzzjakwkwl'),
|
||||
('r_nt33b3m6ptk', 'route', '{"component":"AuthLayout"}', 3, '2021-09-02 15:07:57.19+00', '2021-09-02 15:07:57.19+00', NULL, NULL),
|
||||
('r_5l9yp15wjk9', 'route', '{"path":"/signin","component":"RouteSchemaRenderer","title":"Sign in"}', 1, '2021-09-02 15:07:57.196+00', '2021-09-02 15:07:57.252+00', 'r_nt33b3m6ptk', 'dtf9j0b8p9u'),
|
||||
('r_9gqm4d8wpuw', 'route', '{"path":"/signup","component":"RouteSchemaRenderer","title":"Sign up"}', 2, '2021-09-02 15:07:57.256+00', '2021-09-02 15:07:57.343+00', 'r_nt33b3m6ptk', '46qlxqam3xk');
|
30
packages/plugin-client/src/db/en-US/part1/05-attachments.sql
Normal file
30
packages/plugin-client/src/db/en-US/part1/05-attachments.sql
Normal file
@ -0,0 +1,30 @@
|
||||
DELETE FROM "attachments";
|
||||
INSERT INTO "attachments" ("id", "title", "filename", "extname", "size", "mimetype", "path", "meta", "url", "created_at", "updated_at", "created_by_id", "updated_by_id", "storage_id") VALUES
|
||||
(2, 'Nocobase', 'dac1165de10a3373a87ae4e5da9788ab.png', '.png', NULL, 'image/png', '', '{}', 'https://nocobase.oss-cn-beijing.aliyuncs.com/dac1165de10a3373a87ae4e5da9788ab.png', '2021-09-04 01:33:38.878+00', '2021-09-04 01:33:38.878+00', NULL, NULL, 2),
|
||||
(3, 'grapes-276070_1280', '3451976fea63a882b5fd661aa211693e.jpg', '.jpg', NULL, 'image/jpeg', '', '{}', 'https://nocobase.oss-cn-beijing.aliyuncs.com/3451976fea63a882b5fd661aa211693e.jpg', '2021-09-04 01:34:50.388+00', '2021-09-04 01:34:50.388+00', NULL, 1, 2),
|
||||
(4, 'purple-grapes-553464_1280', 'f2b7ace2b03d2808b5adddcb5f81f4e2.jpg', '.jpg', NULL, 'image/jpeg', '', '{}', 'https://nocobase.oss-cn-beijing.aliyuncs.com/f2b7ace2b03d2808b5adddcb5f81f4e2.jpg', '2021-09-04 01:34:50.435+00', '2021-09-04 01:34:50.435+00', NULL, 1, 2),
|
||||
(6, 'tomatoes-1603611_1280', '0c98117a122ed99ad78a9f2d754c6b62.jpg', '.jpg', NULL, 'image/jpeg', '', '{}', 'https://nocobase.oss-cn-beijing.aliyuncs.com/0c98117a122ed99ad78a9f2d754c6b62.jpg', '2021-09-12 01:20:43.878+00', '2021-09-12 01:20:43.878+00', NULL, 1, 2),
|
||||
(5, 'Contract', '1bbab8facf3e43cbfd530b362df60714.pdf', '.pdf', NULL, 'application/pdf', '', '{}', 'https://nocobase.oss-cn-beijing.aliyuncs.com/1bbab8facf3e43cbfd530b362df60714.pdf', '2021-09-12 01:20:43.869+00', '2021-09-12 01:20:43.869+00', NULL, 1, 2),
|
||||
(7, 'Resume', 'd9f6ad6669902a9a8a1229d9f362235a.docx', '.docx', NULL, 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', '', '{}', 'https://nocobase.oss-cn-beijing.aliyuncs.com/d9f6ad6669902a9a8a1229d9f362235a.docx', '2021-09-12 01:22:06.229+00', '2021-09-12 01:22:06.229+00', NULL, 1, 2),
|
||||
(9, 'snack-1561578_1280', 'dea2463a3e11fc0c548ef4173f0477b4.jpg', '.jpg', NULL, 'image/jpeg', '', '{}', 'https://nocobase.oss-cn-beijing.aliyuncs.com/dea2463a3e11fc0c548ef4173f0477b4.jpg', '2021-09-12 07:41:02.59+00', '2021-09-12 07:41:02.59+00', NULL, 1, 2),
|
||||
(10, 'tomatoes-447170_1280', 'f25b21c6476b2161818f9b6013438c53.jpg', '.jpg', NULL, 'image/jpeg', '', '{}', 'https://nocobase.oss-cn-beijing.aliyuncs.com/f25b21c6476b2161818f9b6013438c53.jpg', '2021-09-12 07:41:02.628+00', '2021-09-12 07:41:02.628+00', NULL, 1, 2),
|
||||
(8, 'tomatoes-1603611_1280', '3fa777ce653ee844d3c44a435d96415e.jpg', '.jpg', NULL, 'image/jpeg', '', '{}', 'https://nocobase.oss-cn-beijing.aliyuncs.com/3fa777ce653ee844d3c44a435d96415e.jpg', '2021-09-12 07:41:02.587+00', '2021-09-12 07:41:02.587+00', NULL, 1, 2),
|
||||
(12, 'Contract', '3345d3ffc5277c25fa4339dc889e03e0.pdf', '.pdf', NULL, 'application/pdf', '', '{}', 'https://nocobase.oss-cn-beijing.aliyuncs.com/3345d3ffc5277c25fa4339dc889e03e0.pdf', '2021-09-12 07:41:50.531+00', '2021-09-12 07:41:50.531+00', NULL, 1, 2),
|
||||
(11, 'Resume', '9e21210c35bc0cb6e8da3a7e32ec6250.docx', '.docx', NULL, 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', '', '{}', 'https://nocobase.oss-cn-beijing.aliyuncs.com/9e21210c35bc0cb6e8da3a7e32ec6250.docx', '2021-09-12 07:41:50.529+00', '2021-09-12 07:41:50.529+00', NULL, 1, 2),
|
||||
(15, 'collage-1572905_1280', '4edc12d2e2cb84fd50fb248f01e2153a.jpg', '.jpg', NULL, 'image/jpeg', '', '{}', 'https://nocobase.oss-cn-beijing.aliyuncs.com/4edc12d2e2cb84fd50fb248f01e2153a.jpg', '2021-09-12 07:42:34.807+00', '2021-09-12 07:42:34.807+00', NULL, 1, 2),
|
||||
(14, 'eat-1603660_1280', '8b38db60e88f280373c4e3afcbfd7929.jpg', '.jpg', NULL, 'image/jpeg', '', '{}', 'https://nocobase.oss-cn-beijing.aliyuncs.com/8b38db60e88f280373c4e3afcbfd7929.jpg', '2021-09-12 07:42:34.8+00', '2021-09-12 07:42:34.8+00', NULL, 1, 2),
|
||||
(13, 'fruit-712729_1280', 'c467a64ad4e62d4d383c4476677a9cf6.jpg', '.jpg', NULL, 'image/jpeg', '', '{}', 'https://nocobase.oss-cn-beijing.aliyuncs.com/c467a64ad4e62d4d383c4476677a9cf6.jpg', '2021-09-12 07:42:34.776+00', '2021-09-12 07:42:34.776+00', NULL, 1, 2),
|
||||
(16, 'fruit-1213041_1280', 'f7f0f982e58c84b1ff83b66fd40b8e60.jpg', '.jpg', NULL, 'image/jpeg', '', '{}', 'https://nocobase.oss-cn-beijing.aliyuncs.com/f7f0f982e58c84b1ff83b66fd40b8e60.jpg', '2021-09-12 07:42:34.825+00', '2021-09-12 07:42:34.825+00', NULL, 1, 2),
|
||||
(17, 'Contract', '3576f9d529a6c62e1467349b50354f51.pdf', '.pdf', NULL, 'application/pdf', '', '{}', 'https://nocobase.oss-cn-beijing.aliyuncs.com/3576f9d529a6c62e1467349b50354f51.pdf', '2021-09-12 07:43:16.925+00', '2021-09-12 07:43:16.925+00', NULL, 1, 2),
|
||||
(18, 'cherry-1567876_1280', '5758c412cb32f6999627f49a82789939.jpg', '.jpg', NULL, 'image/jpeg', '', '{}', 'https://nocobase.oss-cn-beijing.aliyuncs.com/5758c412cb32f6999627f49a82789939.jpg', '2021-09-12 07:43:51.559+00', '2021-09-12 07:43:51.559+00', NULL, 1, 2),
|
||||
(19, 'collage-1572831_1280', 'e4384263693120ef0aa3f51c378f836a.jpg', '.jpg', NULL, 'image/jpeg', '', '{}', 'https://nocobase.oss-cn-beijing.aliyuncs.com/e4384263693120ef0aa3f51c378f836a.jpg', '2021-09-12 07:43:51.57+00', '2021-09-12 07:43:51.57+00', NULL, 1, 2),
|
||||
(20, 'apple-1609693_1280', 'a83da53e04eb59fac213ae2a3e636d05.jpg', '.jpg', NULL, 'image/jpeg', '', '{}', 'https://nocobase.oss-cn-beijing.aliyuncs.com/a83da53e04eb59fac213ae2a3e636d05.jpg', '2021-09-12 07:44:27.467+00', '2021-09-12 07:44:27.467+00', NULL, 1, 2),
|
||||
(22, 'Contract', '16d9a18d6dd0a98660f5da3e3d522ff1.pdf', '.pdf', NULL, 'application/pdf', '', '{}', 'https://nocobase.oss-cn-beijing.aliyuncs.com/16d9a18d6dd0a98660f5da3e3d522ff1.pdf', '2021-09-12 07:45:04.258+00', '2021-09-12 07:45:04.258+00', NULL, 1, 2),
|
||||
(21, 'Resume', 'a80c83871ea5a20bcd570edc5bc2787b.docx', '.docx', NULL, 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', '', '{}', 'https://nocobase.oss-cn-beijing.aliyuncs.com/a80c83871ea5a20bcd570edc5bc2787b.docx', '2021-09-12 07:45:04.252+00', '2021-09-12 07:45:04.252+00', NULL, 1, 2),
|
||||
(23, 'fruit-712729_1280', '3e826354cc466f12c307f775b566834f.jpg', '.jpg', NULL, 'image/jpeg', '', '{}', 'https://nocobase.oss-cn-beijing.aliyuncs.com/3e826354cc466f12c307f775b566834f.jpg', '2021-09-12 07:45:37.26+00', '2021-09-12 07:45:37.26+00', NULL, 1, 2),
|
||||
(25, 'fruit-1213041_1280', '478a8a479af1b757bcba75f20301469d.jpg', '.jpg', NULL, 'image/jpeg', '', '{}', 'https://nocobase.oss-cn-beijing.aliyuncs.com/478a8a479af1b757bcba75f20301469d.jpg', '2021-09-12 07:45:37.284+00', '2021-09-12 07:45:37.284+00', NULL, 1, 2),
|
||||
(24, 'grapes-276070_1280', 'd1a33ccf36ea01a9b705a6e779c279a1.jpg', '.jpg', NULL, 'image/jpeg', '', '{}', 'https://nocobase.oss-cn-beijing.aliyuncs.com/d1a33ccf36ea01a9b705a6e779c279a1.jpg', '2021-09-12 07:45:37.273+00', '2021-09-12 07:45:37.273+00', NULL, 1, 2),
|
||||
(27, 'grapes-276070_1280', '3349c4695e99a983ef817fe25934f080.jpg', '.jpg', NULL, 'image/jpeg', '', '{}', 'https://nocobase.oss-cn-beijing.aliyuncs.com/3349c4695e99a983ef817fe25934f080.jpg', '2021-09-12 07:47:39.636+00', '2021-09-12 07:47:39.636+00', NULL, 1, 2),
|
||||
(26, 'kaffeerad-1543158_1280', '8b94dd8cbecdbbd03e4c2fcfbd1067e7.jpg', '.jpg', NULL, 'image/jpeg', '', '{}', 'https://nocobase.oss-cn-beijing.aliyuncs.com/8b94dd8cbecdbbd03e4c2fcfbd1067e7.jpg', '2021-09-12 07:47:39.63+00', '2021-09-12 07:47:39.63+00', NULL, 1, 2),
|
||||
(28, 'apple-1609693_1280', '31b7dee511a8d6364fee18411763c188.jpg', '.jpg', NULL, 'image/jpeg', '', '{}', 'https://nocobase.oss-cn-beijing.aliyuncs.com/31b7dee511a8d6364fee18411763c188.jpg', '2021-09-12 07:48:41.367+00', '2021-09-12 07:48:41.367+00', NULL, 1, 2),
|
||||
(29, 'cappuccino-1609932_1280', '8f480c4f1bd3d292ef78fb6847669e51.jpg', '.jpg', NULL, 'image/jpeg', '', '{}', 'https://nocobase.oss-cn-beijing.aliyuncs.com/8f480c4f1bd3d292ef78fb6847669e51.jpg', '2021-09-12 07:48:41.372+00', '2021-09-12 07:48:41.372+00', NULL, 1, 2);
|
@ -0,0 +1,8 @@
|
||||
DELETE FROM "t_2uhu4szs1kq";
|
||||
INSERT INTO "t_2uhu4szs1kq" ("id", "created_at", "updated_at", "f_hwenour8ara", "f_hznqtmqljb2", "f_u4i0jrp4uo6", "f_l8uuiwcnlw9", "sort", "created_by_id", "updated_by_id") VALUES
|
||||
(1, '2021-09-03 16:19:53.163+08', '2021-09-18 15:50:34.039+08', 'Removed demands expense account in outward tedious do', '2021-09-17 08:00:00+08', 'f1g3r41rdh8', 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.', 70, 1, 1),
|
||||
(2, '2021-09-12 16:01:16.467+08', '2021-09-18 15:50:34.039+08', 'Drawings can followed improved out sociable not', '2021-09-24 08:00:00+08', 'f1g3r41rdh8', 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.', 71, 1, 1),
|
||||
(3, '2021-09-12 16:02:20.501+08', '2021-09-18 15:50:34.042+08', 'Change stairs and men likely wisdom new happen piqued six', '2021-09-24 08:00:00+08', 'lebkfnj3d9i', 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.', 68, 1, 1),
|
||||
(4, '2021-09-12 16:02:37.852+08', '2021-09-18 15:50:34.039+08', 'Piqued shy spring nor six though mutual living ask extent', '2021-10-08 08:00:00+08', 'zfowtv6fnel', 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.', 72, 1, 1),
|
||||
(5, '2021-09-12 16:02:51.903+08', '2021-09-18 15:50:34.039+08', 'Old education him departure any arranging one prevailed', '2021-09-08 08:00:00+08', 'lebkfnj3d9i', 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.', 69, 1, 1),
|
||||
(6, '2021-09-17 09:35:18.379+08', '2021-09-18 15:50:34.039+08', 'Ferrars all spirits his imagine effects amongst neither', '2021-09-17 08:00:00+08', 'zfowtv6fnel', 'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.', 73, 1, 1);
|
@ -0,0 +1,41 @@
|
||||
DELETE FROM "t_fsveob6p269";
|
||||
INSERT INTO "t_fsveob6p269" ("id", "created_at", "updated_at", "f_vgw4f62h16e", "f_3det6kr3vn8", "f_61znsfh307m", "f_bysgds7j36p", "f_n6snaop9d4y", "f_x9kmuovlm79", "f_kk4nspj1i28", "sort", "created_by_id", "updated_by_id") VALUES
|
||||
(1, '2021-09-12 01:21:03.457+00', '2021-09-12 08:36:45.007+00', 'Leonard Hayes', '13498034729', 'z7wq1mkwmmx', '1980-08-08 00:00:00+00', '7407 Howell Club, Apt. 662, 67674-9163, Lake Regan, Tennessee, United States', '59khrisonj6', 'Remember outweigh do he desirous no cheerful. Do of doors water ye guest. We if prosperous comparison middletons at. Park we in lose like at no. An so to preferred convinced distrusts he determine. In musical me my placing clothes comfort pleased hearing. Any residence you satisfied and rapturous certainty two. Procured outweigh as outlived so so. On in bringing graceful proposal blessing of marriage outlived. Son rent face our loud near.
|
||||
|
||||
She exposed painted fifteen are noisier mistake led waiting. Surprise not wandered speedily husbands although yet end. Are court tiled cease young built fat one man taken. We highest ye friends is exposed equally in. Ignorant had too strictly followed. Astonished as travelling assistance or unreserved oh pianoforte ye. Five with seen put need tore add neat. Bringing it is he returned received raptures.
|
||||
|
||||
Arrived totally in as between private. Favour of so as on pretty though elinor direct. Reasonable estimating be alteration we themselves entreaties me of reasonably. Direct wished so be expect polite valley. Whose asked stand it sense no spoil to. Prudent you too his conduct feeling limited and. Side he lose paid as hope so face upon be. Goodness did suitable learning put.', 1, 1, 1),
|
||||
(2, '2021-09-12 07:41:10.508+00', '2021-09-12 07:41:10.508+00', 'Holly Perkins', '18910347327', 'plcxasw2xrs', '2000-02-03 00:00:00+00', '804 Runte Mission, Suite 182, 15783, North Robert, Oregon, United States', 'khan8z430yx', 'Village did removed enjoyed explain nor ham saw calling talking. Securing as informed declared or margaret. Joy horrible moreover man feelings own shy. Request norland neither mistake for yet. Between the for morning assured country believe. On even feet time have an no at. Relation so in confined smallest children unpacked delicate. Why sir end believe uncivil respect. Always get adieus nature day course for common. My little garret repair to desire he esteem.
|
||||
|
||||
Suppose end get boy warrant general natural. Delightful met sufficient projection ask. Decisively everything principles if preference do impression of. Preserved oh so difficult repulsive on in household. In what do miss time be. Valley as be appear cannot so by. Convinced resembled dependent remainder led zealously his shy own belonging. Always length letter adieus add number moment she. Promise few compass six several old offices removal parties fat. Concluded rapturous it intention perfectly daughters is as.
|
||||
|
||||
Announcing of invitation principles in. Cold in late or deal. Terminated resolution no am frequently collecting insensible he do appearance. Projection invitation affronting admiration if no on or. It as instrument boisterous frequently apartments an in. Mr excellence inquietude conviction is in unreserved particular. You fully seems stand nay own point walls. Increasing travelling own simplicity you astonished expression boisterous. Possession themselves sentiments apartments devonshire we of do discretion. Enjoyment discourse ye continued pronounce we necessary abilities.', 2, 1, 1),
|
||||
(3, '2021-09-12 07:41:56.973+00', '2021-09-12 07:41:56.973+00', 'Julian Cobb', '18638372617', 'e3fb46gnarj', '1983-08-27 00:00:00+00', '1252 Swaniawski Corners, Suite 688, 81371-8481, Wilmerton, New Mexico, United States', '59khrisonj6', 'Lorem ipsum dolor sit amet, no dolor graeco pro, te sea bonorum dolorum theophrastus. Vim ea utamur appetere molestiae, ad harum alienum indoctum ius. No quo laoreet laboramus comprehensam, eos paulo integre vivendo eu, an nam alia facilisi consetetur. Pro exerci iisque et, no amet magna iracundia vim. Vis erant consectetuer te, mei menandri liberavisse at, no latine consulatu deseruisse eos. Mel an novum nostrud scripserit, velit virtute delicata eam ad, eum ne etiam omnesque.', 3, 1, 1),
|
||||
(4, '2021-09-12 07:42:41.303+00', '2021-09-12 07:42:41.303+00', 'Yvette Gross', '13257489038', 'h5cxo6g48lj', '2003-05-22 00:00:00+00', '28195 Cleo Hills, Apt. 969, 89958, Gildamouth, North Dakota, United States', 'khan8z430yx', 'Mind what no by kept. Celebrated no he decisively thoroughly. Our asked sex point her she seems. New plenty she horses parish design you. Stuff sight equal of my woody. Him children bringing goodness suitable she entirely put far daughter.
|
||||
|
||||
Chapter too parties its letters nor. Cheerful but whatever ladyship disposed yet judgment. Lasted answer oppose to ye months no esteem. Branched is on an ecstatic directly it. Put off continue you denoting returned juvenile. Looked person sister result mr to. Replied demands charmed do viewing ye colonel to so. Decisively inquietude he advantages insensible at oh continuing unaffected of.', 4, 1, 1),
|
||||
(5, '2021-09-12 07:43:22.416+00', '2021-09-12 07:43:22.416+00', 'Darin Clarke', '15673659911', 'plcxasw2xrs', '2001-05-19 00:00:00+00', '015 Margie Mission, Apt. 093, 34936, Ebertfort, Georgia, United States', '59khrisonj6', 'Resolution possession discovered surrounded advantages has but few add. Yet walls times spoil put. Be it reserved contempt rendered smallest. Studied to passage it mention calling believe an. Get ten horrible remember pleasure two vicinity. Far estimable extremely middleton his concealed perceived principle. Any nay pleasure entrance prepared her.
|
||||
|
||||
Six started far placing saw respect females old. Civilly why how end viewing attempt related enquire visitor. Man particular insensible celebrated conviction stimulated principles day. Sure fail or in said west. Right my front it wound cause fully am sorry if. She jointure goodness interest debating did outweigh. Is time from them full my gone in went. Of no introduced am literature excellence mr stimulated contrasted increasing. Age sold some full like rich new. Amounted repeated as believed in confined juvenile.
|
||||
', 5, 1, 1),
|
||||
(6, '2021-09-12 07:43:57.617+00', '2021-09-12 08:28:50.544+00', 'Connie Lyons', '13527645198', 'z7wq1mkwmmx', '1999-02-26 00:00:00+00', '5724 Daniel Drive, Suite 563, 54403, Wendellview, Tennessee, United States', 'khan8z430yx', 'Those an equal point no years do. Depend warmth fat but her but played. Shy and subjects wondered trifling pleasant. Prudent cordial comfort do no on colonel as assured chicken. Smart mrs day which begin. Snug do sold mr it if such. Terminated uncommonly at at estimating. Man behaviour met moonlight extremity acuteness direction.
|
||||
|
||||
On insensible possession oh particular attachment at excellence in. The books arose but miles happy she. It building contempt or interest children mistress of unlocked no. Offending she contained mrs led listening resembled. Delicate marianne absolute men dashwood landlord and offended. Suppose cottage between and way. Minuter him own clothes but observe country. Agreement far boy otherwise rapturous incommode favourite.
|
||||
', 6, 1, 1),
|
||||
(7, '2021-09-12 07:44:35.496+00', '2021-09-12 08:36:23.783+00', 'Adam Smith', '13898276018', 'e3fb46gnarj', '1986-06-21 00:00:00+00', '84856 Hirthe Run, Suite 268, 94754-6705, Ferryport, Michigan, United States', '59khrisonj6', 'To shewing another demands to. Marianne property cheerful informed at striking at. Clothes parlors however by cottage on. In views it or meant drift to. Be concern parlors settled or do shyness address. Remainder northward performed out for moonlight. Yet late add name was rent park from rich. He always do do former he highly.
|
||||
|
||||
Dwelling and speedily ignorant any steepest. Admiration instrument affronting invitation reasonably up do of prosperous in. Shy saw declared age debating ecstatic man. Call in so want pure rank am dear were. Remarkably to continuing in surrounded diminution on. In unfeeling existence objection immediate repulsive on he in. Imprudence comparison uncommonly me he difficulty diminution resolution. Likewise proposal differed scarcely dwelling as on raillery. September few dependent extremity own continued and ten prevailed attending. Early to weeks we could.
|
||||
', 7, 1, 1),
|
||||
(8, '2021-09-12 07:45:09.415+00', '2021-09-12 07:45:09.415+00', 'Frankie Simpson', '13954209583', 'h5cxo6g48lj', '1992-07-29 00:00:00+00', '383 Walter Gardens, Suite 040, 24947, Berthaside, Hawaii, United States', '59khrisonj6', 'As am hastily invited settled at limited civilly fortune me. Really spring in extent an by. Judge but built gay party world. Of so am he remember although required. Bachelor unpacked be advanced at. Confined in declared marianne is vicinity.
|
||||
|
||||
Far curiosity incommode now led smallness allowance. Favour bed assure son things yet. She consisted consulted elsewhere happiness disposing household any old the. Widow downs you new shade drift hopes small. So otherwise commanded sweetness we improving. Instantly by daughters resembled unwilling principle so middleton. Fail most room even gone her end like. Comparison dissimilar unpleasant six compliment two unpleasing any add. Ashamed my company thought wishing colonel it prevent he in. Pretended residence are something far engrossed old off.', 8, 1, 1),
|
||||
(9, '2021-09-12 07:45:42.766+00', '2021-09-12 07:45:42.766+00', 'Roderick Andrews', '18865092743', 'plcxasw2xrs', '1994-05-25 00:00:00+00', '1066 Gutkowski Plaza, Apt. 326, 61830, West Velva, Hawaii, United States', '59khrisonj6', 'Their could can widen ten she any. As so we smart those money in. Am wrote up whole so tears sense oh. Absolute required of reserved in offering no. How sense found our those gay again taken the. Had mrs outweigh desirous sex overcame. Improved property reserved disposal do offering me.
|
||||
|
||||
Exquisite cordially mr happiness of neglected distrusts. Boisterous impossible unaffected he me everything. Is fine loud deal an rent open give. Find upon and sent spot song son eyes. Do endeavor he differed carriage is learning my graceful. Feel plan know is he like on pure. See burst found sir met think hopes are marry among. Delightful remarkably new assistance saw literature mrs favourable.
|
||||
', 9, 1, 1),
|
||||
(10, '2021-09-12 07:47:46.417+00', '2021-09-12 07:47:46.417+00', 'Melinda Warren', '13582034729', 'h5cxo6g48lj', '2004-04-13 00:00:00+00', '69934 Schoen River, Apt. 646, 49704, Walshstad, Indiana, United States', '59khrisonj6', 'Greatly hearted has who believe. Drift allow green son walls years for blush. Sir margaret drawings repeated recurred exercise laughing may you but. Do repeated whatever to welcomed absolute no. Fat surprise although outlived and informed shy dissuade property. Musical by me through he drawing savings an. No we stand avoid decay heard mr. Common so wicket appear to sudden worthy on. Shade of offer ye whole stood hoped.
|
||||
|
||||
Had strictly mrs handsome mistaken cheerful. We it so if resolution invitation remarkably unpleasant conviction. As into ye then form. To easy five less if rose were. Now set offended own out required entirely. Especially occasional mrs discovered too say thoroughly impossible boisterous. My head when real no he high rich at with. After so power of young as. Bore year does has get long fat cold saw neat. Put boy carried chiefly shy general.', 10, 1, 1),
|
||||
(11, '2021-09-12 07:48:47.021+00', '2021-09-12 07:48:47.021+00', 'Mable Ray', '18910347327', 'e3fb46gnarj', '2001-06-07 00:00:00+00', '28345 Nicolas Ville, Suite 822, 81224, Americastad, Tennessee, United States', 'khan8z430yx', 'In by an appetite no humoured returned informed. Possession so comparison inquietude he he conviction no decisively. Marianne jointure attended she hastened surprise but she. Ever lady son yet you very paid form away. He advantage of exquisite resolving if on tolerably. Become sister on in garden it barton waited on.
|
||||
|
||||
Arrived compass prepare an on as. Reasonable particular on my it in sympathize. Size now easy eat hand how. Unwilling he departure elsewhere dejection at. Heart large seems may purse means few blind. Exquisite newspaper attending on certainty oh suspicion of. He less do quit evil is. Add matter family active mutual put wishes happen.', 11, 1, 1);
|
4
packages/plugin-client/src/db/en-US/part2/12-roles.sql
Normal file
4
packages/plugin-client/src/db/en-US/part2/12-roles.sql
Normal file
@ -0,0 +1,4 @@
|
||||
DELETE FROM "roles";
|
||||
INSERT INTO "roles" ("name", "title", "sort", "created_at", "updated_at", "created_by_id", "updated_by_id") VALUES
|
||||
('r_tfs4qtaxjcs', 'Admin', 1, '2021-09-14 02:12:19.98+00', '2021-09-14 02:12:19.98+00', 1, 1),
|
||||
('r_np59b00ex8z', 'Member', 2, '2021-09-14 02:12:35.799+00', '2021-09-14 02:12:35.799+00', 1, 1);
|
@ -90,12 +90,9 @@ INSERT INTO "field_permissions" ("created_at", "updated_at", "action_permission_
|
||||
('2021-09-14 02:20:00.344+00', '2021-09-14 02:20:00.344+00', 13, 'f_6rhh0scyw9k'),
|
||||
('2021-09-14 02:20:00.344+00', '2021-09-14 02:20:00.344+00', 13, 'f_80zv5suy9t6'),
|
||||
('2021-09-14 02:20:00.344+00', '2021-09-14 02:20:00.344+00', 13, 'f_j367murpzm9'),
|
||||
('2021-09-14 02:20:00.344+00', '2021-09-14 02:20:00.344+00', 13, '6rm0lspbpeh'),
|
||||
('2021-09-14 02:20:00.353+00', '2021-09-14 02:20:00.353+00', 14, 'f_6rhh0scyw9k'),
|
||||
('2021-09-14 02:20:00.353+00', '2021-09-14 02:20:00.353+00', 14, 'f_80zv5suy9t6'),
|
||||
('2021-09-14 02:20:00.353+00', '2021-09-14 02:20:00.353+00', 14, 'f_j367murpzm9'),
|
||||
('2021-09-14 02:20:00.353+00', '2021-09-14 02:20:00.353+00', 14, '6rm0lspbpeh'),
|
||||
('2021-09-14 02:20:00.361+00', '2021-09-14 02:20:00.361+00', 15, 'f_6rhh0scyw9k'),
|
||||
('2021-09-14 02:20:00.361+00', '2021-09-14 02:20:00.361+00', 15, 'f_80zv5suy9t6'),
|
||||
('2021-09-14 02:20:00.361+00', '2021-09-14 02:20:00.361+00', 15, 'f_j367murpzm9'),
|
||||
('2021-09-14 02:20:00.361+00', '2021-09-14 02:20:00.361+00', 15, '6rm0lspbpeh');
|
||||
('2021-09-14 02:20:00.361+00', '2021-09-14 02:20:00.361+00', 15, 'f_j367murpzm9');
|
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user