lots of updates
This commit is contained in:
parent
78740f9905
commit
057dc8406a
@ -534,7 +534,7 @@ export async function sort(ctx: Context, next: Next) {
|
|||||||
const Model = ctx.db.getModel(resourceName);
|
const Model = ctx.db.getModel(resourceName);
|
||||||
const table = ctx.db.getTable(resourceName);
|
const table = ctx.db.getTable(resourceName);
|
||||||
|
|
||||||
const { sticky, field, target } = values;
|
const { sticky, field, target, insertAfter } = values;
|
||||||
if (!values.field || typeof target === 'undefined') {
|
if (!values.field || typeof target === 'undefined') {
|
||||||
return next();
|
return next();
|
||||||
}
|
}
|
||||||
@ -592,11 +592,11 @@ export async function sort(ctx: Context, next: Next) {
|
|||||||
if (sameScope) {
|
if (sameScope) {
|
||||||
const direction = source[sortAttr] < targetObject[sortAttr] ? {
|
const direction = source[sortAttr] < targetObject[sortAttr] ? {
|
||||||
sourceOp: Op.gt,
|
sourceOp: Op.gt,
|
||||||
targetOp: Op.lte,
|
targetOp: insertAfter ? Op.lt : Op.lte,
|
||||||
increment: -1
|
increment: -1
|
||||||
} : {
|
} : {
|
||||||
sourceOp: Op.lt,
|
sourceOp: Op.lt,
|
||||||
targetOp: Op.gte,
|
targetOp: insertAfter ? Op.gt : Op.gte,
|
||||||
increment: 1
|
increment: 1
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -617,6 +617,8 @@ export async function sort(ctx: Context, next: Next) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log({ insertAfter, updateWhere })
|
||||||
|
|
||||||
await Model.increment(sortAttr, {
|
await Model.increment(sortAttr, {
|
||||||
by: increment,
|
by: increment,
|
||||||
where: updateWhere,
|
where: updateWhere,
|
||||||
@ -624,7 +626,7 @@ export async function sort(ctx: Context, next: Next) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
Object.assign(updates, {
|
Object.assign(updates, {
|
||||||
[sortAttr]: targetObject[sortAttr]
|
[sortAttr]: insertAfter ? targetObject[sortAttr] + 1 : targetObject[sortAttr]
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
Object.assign(updates, {
|
Object.assign(updates, {
|
||||||
|
@ -0,0 +1,68 @@
|
|||||||
|
import { DatabaseOutlined } from '@ant-design/icons';
|
||||||
|
import { SchemaRenderer } from '../../../';
|
||||||
|
import Modal from 'antd/lib/modal/Modal';
|
||||||
|
import React from 'react';
|
||||||
|
import { useState } from 'react';
|
||||||
|
import schema from './schema';
|
||||||
|
import { Button, Dropdown, Menu } from 'antd';
|
||||||
|
import { useMemo } from 'react';
|
||||||
|
import { createForm } from '@formily/core';
|
||||||
|
|
||||||
|
export default () => {
|
||||||
|
const form = useMemo(
|
||||||
|
() =>
|
||||||
|
createForm({
|
||||||
|
initialValues: {
|
||||||
|
title: '数据表名称',
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
const [visible, setVisible] = useState(false);
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Button
|
||||||
|
onClick={() => {
|
||||||
|
setVisible(true);
|
||||||
|
}}
|
||||||
|
type={'primary'}
|
||||||
|
>
|
||||||
|
<DatabaseOutlined />
|
||||||
|
</Button>
|
||||||
|
<Modal
|
||||||
|
title={
|
||||||
|
<>
|
||||||
|
<Dropdown
|
||||||
|
overlay={
|
||||||
|
<Menu
|
||||||
|
onClick={(info) => {
|
||||||
|
form.setValues({
|
||||||
|
title: `数据表${info.key}`,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Menu.Item key={1}>数据表1</Menu.Item>
|
||||||
|
<Menu.Item key={2}>数据表2</Menu.Item>
|
||||||
|
<Menu.Divider></Menu.Divider>
|
||||||
|
<Menu.Item key={5}>新建数据表</Menu.Item>
|
||||||
|
</Menu>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<span style={{cursor: 'pointer'}}>数据表3</span>
|
||||||
|
</Dropdown>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
visible={visible}
|
||||||
|
onOk={async () => {
|
||||||
|
await form.submit();
|
||||||
|
setVisible(false);
|
||||||
|
}}
|
||||||
|
onCancel={() => {
|
||||||
|
setVisible(false);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<SchemaRenderer form={form} schema={schema} />
|
||||||
|
</Modal>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
@ -0,0 +1,49 @@
|
|||||||
|
import { ISchema } from "@formily/react";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
type: 'object',
|
||||||
|
properties: {
|
||||||
|
form: {
|
||||||
|
type: 'void',
|
||||||
|
"x-component": 'FormLayout',
|
||||||
|
"x-component-props": {
|
||||||
|
layout: 'vertical',
|
||||||
|
},
|
||||||
|
properties: {
|
||||||
|
title: {
|
||||||
|
type: 'string',
|
||||||
|
title: '数据表名称',
|
||||||
|
required: true,
|
||||||
|
'x-decorator': 'FormItem',
|
||||||
|
'x-component': 'Input',
|
||||||
|
},
|
||||||
|
fields: {
|
||||||
|
type: 'array',
|
||||||
|
title: '字段',
|
||||||
|
'x-decorator': 'FormItem',
|
||||||
|
'x-component': 'DatabaseField',
|
||||||
|
default: [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
interface: 'string',
|
||||||
|
dataType: 'string',
|
||||||
|
name: 'title',
|
||||||
|
ui: {
|
||||||
|
title: '标题',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
dataType: 'text',
|
||||||
|
interface: 'textarea',
|
||||||
|
name: 'content',
|
||||||
|
ui: {
|
||||||
|
title: '内容',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} as ISchema;
|
@ -23,7 +23,7 @@ import './style.less';
|
|||||||
|
|
||||||
import { uid } from '@formily/shared';
|
import { uid } from '@formily/shared';
|
||||||
import { ISchema } from '@formily/react';
|
import { ISchema } from '@formily/react';
|
||||||
import datatable from './datatable';
|
import DataTableConfig from './DataTableConfig';
|
||||||
|
|
||||||
function LayoutWithMenu({ schema }) {
|
function LayoutWithMenu({ schema }) {
|
||||||
const match = useRouteMatch<any>();
|
const match = useRouteMatch<any>();
|
||||||
@ -31,8 +31,15 @@ function LayoutWithMenu({ schema }) {
|
|||||||
const sideMenuRef = useRef();
|
const sideMenuRef = useRef();
|
||||||
const [activeKey, setActiveKey] = useState(match.params.name);
|
const [activeKey, setActiveKey] = useState(match.params.name);
|
||||||
const onSelect = (info) => {
|
const onSelect = (info) => {
|
||||||
console.log('LayoutWithMenu', schema);
|
console.log('LayoutWithMenu', info);
|
||||||
setActiveKey(info.key);
|
if (!info.schema) {
|
||||||
|
setActiveKey(null);
|
||||||
|
} else if (info.schema['x-component'] === 'Menu.SubMenu') {
|
||||||
|
// 实际应该取第一个子元素
|
||||||
|
setActiveKey(null);
|
||||||
|
} else {
|
||||||
|
setActiveKey(info.schema.key);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
console.log({ match });
|
console.log({ match });
|
||||||
return (
|
return (
|
||||||
@ -46,7 +53,7 @@ function LayoutWithMenu({ schema }) {
|
|||||||
selectedKeys: [activeKey].filter(Boolean),
|
selectedKeys: [activeKey].filter(Boolean),
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<SchemaRenderer schema={datatable} />
|
<DataTableConfig />
|
||||||
</Layout.Header>
|
</Layout.Header>
|
||||||
<Layout>
|
<Layout>
|
||||||
<Layout.Sider
|
<Layout.Sider
|
||||||
@ -75,31 +82,7 @@ function Content({ activeKey }) {
|
|||||||
return <Spin />;
|
return <Spin />;
|
||||||
}
|
}
|
||||||
|
|
||||||
const schema: ISchema = {
|
return <SchemaRenderer schema={data} />;
|
||||||
type: 'void',
|
|
||||||
name: uid(),
|
|
||||||
'x-component': 'Grid',
|
|
||||||
properties: {
|
|
||||||
[`row_${uid()}`]: {
|
|
||||||
type: 'void',
|
|
||||||
'x-component': 'Grid.Row',
|
|
||||||
properties: {
|
|
||||||
[`col_${uid()}`]: {
|
|
||||||
type: 'void',
|
|
||||||
'x-component': 'Grid.Col',
|
|
||||||
properties: {
|
|
||||||
[uid()]: {
|
|
||||||
type: 'void',
|
|
||||||
'x-component': 'AddNew.BlockItem',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
return <SchemaRenderer schema={schema} />;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function AdminLayout({ route }: any) {
|
export function AdminLayout({ route }: any) {
|
||||||
|
@ -154,14 +154,24 @@ export function addPropertyAfter(target: Schema, data: ISchema) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setKeys(schema: ISchema, parentKey = null) {
|
||||||
|
if (!schema['key']) {
|
||||||
|
schema['key'] = uid();
|
||||||
|
}
|
||||||
|
if (parentKey && !schema['parentKey']) {
|
||||||
|
schema['parentKey'] = parentKey;
|
||||||
|
}
|
||||||
|
Object.keys(schema.properties || {}).forEach((name) => {
|
||||||
|
setKeys(schema.properties[name], schema['key']);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
export function useDesignable(path?: any) {
|
export function useDesignable(path?: any) {
|
||||||
const { schema, refresh } = useContext(DesignableContext);
|
const { schema, refresh } = useContext(DesignableContext);
|
||||||
const schemaPath = path || useSchemaPath();
|
const schemaPath = path || useSchemaPath();
|
||||||
console.log({ schemaPath });
|
|
||||||
const fieldSchema = useFieldSchema();
|
const fieldSchema = useFieldSchema();
|
||||||
const currentSchema =
|
const currentSchema =
|
||||||
findPropertyByPath(schema, schemaPath) || ({} as Schema);
|
findPropertyByPath(schema, schemaPath) || ({} as Schema);
|
||||||
console.log({ currentSchema });
|
|
||||||
// console.log('useDesignable', { schema, schemaPath, currentSchema });
|
// console.log('useDesignable', { schema, schemaPath, currentSchema });
|
||||||
const options = useContext(SchemaOptionsContext);
|
const options = useContext(SchemaOptionsContext);
|
||||||
const DesignableBar =
|
const DesignableBar =
|
||||||
@ -184,9 +194,11 @@ export function useDesignable(path?: any) {
|
|||||||
}
|
}
|
||||||
if (target['key']) {
|
if (target['key']) {
|
||||||
property['parentKey'] = target['key'];
|
property['parentKey'] = target['key'];
|
||||||
if (!property['key']) {
|
setKeys(property);
|
||||||
property['key'] = uid();
|
property['__prepend__'] = true;
|
||||||
}
|
// if (!property['key']) {
|
||||||
|
// property['key'] = uid();
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
const properties = {};
|
const properties = {};
|
||||||
properties[property.name] = property;
|
properties[property.name] = property;
|
||||||
@ -214,9 +226,10 @@ export function useDesignable(path?: any) {
|
|||||||
}
|
}
|
||||||
if (target['key']) {
|
if (target['key']) {
|
||||||
property['parentKey'] = target['key'];
|
property['parentKey'] = target['key'];
|
||||||
if (!property['key']) {
|
// if (!property['key']) {
|
||||||
property['key'] = uid();
|
// property['key'] = uid();
|
||||||
}
|
// }
|
||||||
|
setKeys(property);
|
||||||
}
|
}
|
||||||
target.addProperty(property.name, property);
|
target.addProperty(property.name, property);
|
||||||
// BUG: 空 properties 时,addProperty 无反应。
|
// BUG: 空 properties 时,addProperty 无反应。
|
||||||
@ -241,9 +254,8 @@ export function useDesignable(path?: any) {
|
|||||||
console.log('target.parentKey', target);
|
console.log('target.parentKey', target);
|
||||||
if (target['parentKey']) {
|
if (target['parentKey']) {
|
||||||
property['parentKey'] = target['parentKey'];
|
property['parentKey'] = target['parentKey'];
|
||||||
if (!property['key']) {
|
setKeys(property);
|
||||||
property['key'] = uid();
|
property['__insertAfter__'] = target['key'];
|
||||||
}
|
|
||||||
}
|
}
|
||||||
addPropertyAfter(target, property);
|
addPropertyAfter(target, property);
|
||||||
refresh();
|
refresh();
|
||||||
@ -263,9 +275,8 @@ export function useDesignable(path?: any) {
|
|||||||
}
|
}
|
||||||
if (target['parentKey']) {
|
if (target['parentKey']) {
|
||||||
property['parentKey'] = target['parentKey'];
|
property['parentKey'] = target['parentKey'];
|
||||||
if (!property['key']) {
|
setKeys(property);
|
||||||
property['key'] = uid();
|
property['__insertBefore__'] = target['key'];
|
||||||
}
|
|
||||||
}
|
}
|
||||||
addPropertyBefore(target, property);
|
addPropertyBefore(target, property);
|
||||||
refresh();
|
refresh();
|
||||||
@ -280,17 +291,20 @@ export function useDesignable(path?: any) {
|
|||||||
console.error('target schema does not exist.');
|
console.error('target schema does not exist.');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const removed = [];
|
||||||
const remove = (s: Schema) => {
|
const remove = (s: Schema) => {
|
||||||
if (!s.parent) {
|
if (!s.parent) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
s.parent.removeProperty(s.name);
|
s.parent.removeProperty(s.name);
|
||||||
|
removed.push(s);
|
||||||
if (Object.keys(s.parent.properties || {}).length === 0) {
|
if (Object.keys(s.parent.properties || {}).length === 0) {
|
||||||
remove(s.parent);
|
remove(s.parent);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
remove(target);
|
remove(target);
|
||||||
refresh();
|
refresh();
|
||||||
|
return removed;
|
||||||
},
|
},
|
||||||
remove(targetPath?: any) {
|
remove(targetPath?: any) {
|
||||||
let target = currentSchema;
|
let target = currentSchema;
|
||||||
|
@ -38,7 +38,7 @@ const App = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Router initialEntries={['/login']}>
|
<Router initialEntries={['/admin']}>
|
||||||
<RouteSwitch routes={data} />
|
<RouteSwitch routes={data} />
|
||||||
</Router>
|
</Router>
|
||||||
</div>
|
</div>
|
||||||
|
@ -46,8 +46,9 @@ import {
|
|||||||
DownOutlined,
|
DownOutlined,
|
||||||
DatabaseOutlined,
|
DatabaseOutlined,
|
||||||
} from '@ant-design/icons';
|
} from '@ant-design/icons';
|
||||||
import { useDesignable, useSchemaPath } from '../';
|
import { createSchema, useDesignable, useSchemaPath } from '../';
|
||||||
import { uid } from '@formily/shared';
|
import { uid } from '@formily/shared';
|
||||||
|
import { request } from '../../demos/api';
|
||||||
|
|
||||||
const generateGridBlock = (schema: ISchema) => {
|
const generateGridBlock = (schema: ISchema) => {
|
||||||
const name = schema.name || uid();
|
const name = schema.name || uid();
|
||||||
@ -88,7 +89,6 @@ AddNew.BlockItem = observer((props: any) => {
|
|||||||
const { ghost, defaultAction } = props;
|
const { ghost, defaultAction } = props;
|
||||||
const { schema, insertBefore, insertAfter } = useDesignable();
|
const { schema, insertBefore, insertAfter } = useDesignable();
|
||||||
const path = useSchemaPath();
|
const path = useSchemaPath();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dropdown
|
<Dropdown
|
||||||
overlay={
|
overlay={
|
||||||
@ -108,7 +108,7 @@ AddNew.BlockItem = observer((props: any) => {
|
|||||||
<Menu.Item>新增数据表</Menu.Item>
|
<Menu.Item>新增数据表</Menu.Item>
|
||||||
</Menu.SubMenu>
|
</Menu.SubMenu>
|
||||||
<Menu.Item
|
<Menu.Item
|
||||||
onClick={() => {
|
onClick={async () => {
|
||||||
let data: ISchema = {
|
let data: ISchema = {
|
||||||
type: 'void',
|
type: 'void',
|
||||||
title: uid(),
|
title: uid(),
|
||||||
@ -116,6 +116,9 @@ AddNew.BlockItem = observer((props: any) => {
|
|||||||
'x-decorator': 'BlockItem',
|
'x-decorator': 'BlockItem',
|
||||||
'x-component': 'Markdown',
|
'x-component': 'Markdown',
|
||||||
};
|
};
|
||||||
|
if (schema['key']) {
|
||||||
|
data['key'] = uid();
|
||||||
|
}
|
||||||
console.log('isGridBlock(schema)', isGridBlock(schema));
|
console.log('isGridBlock(schema)', isGridBlock(schema));
|
||||||
if (isGridBlock(schema)) {
|
if (isGridBlock(schema)) {
|
||||||
path.pop();
|
path.pop();
|
||||||
@ -123,11 +126,13 @@ AddNew.BlockItem = observer((props: any) => {
|
|||||||
data = generateGridBlock(data);
|
data = generateGridBlock(data);
|
||||||
}
|
}
|
||||||
if (data) {
|
if (data) {
|
||||||
|
let s;
|
||||||
if (defaultAction === 'insertAfter') {
|
if (defaultAction === 'insertAfter') {
|
||||||
insertAfter(data, [...path]);
|
s = insertAfter(data, [...path]);
|
||||||
} else {
|
} else {
|
||||||
insertBefore(data, [...path]);
|
s = insertBefore(data, [...path]);
|
||||||
}
|
}
|
||||||
|
await createSchema(s);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
@ -21,7 +21,7 @@ import {
|
|||||||
import './style.less';
|
import './style.less';
|
||||||
import cls from 'classnames';
|
import cls from 'classnames';
|
||||||
|
|
||||||
import { useDesignable, useSchemaPath } from '../';
|
import { createSchema, useDesignable, useSchemaPath } from '../';
|
||||||
import {
|
import {
|
||||||
useDrag,
|
useDrag,
|
||||||
useDrop,
|
useDrop,
|
||||||
@ -93,10 +93,10 @@ export const Grid: any = observer((props) => {
|
|||||||
<RowDivider
|
<RowDivider
|
||||||
key={`${schema.name}_0`}
|
key={`${schema.name}_0`}
|
||||||
name={`${schema.name}_0`}
|
name={`${schema.name}_0`}
|
||||||
onDrop={(e) => {
|
onDrop={async (e) => {
|
||||||
const blockSchema = e.dragItem.schema;
|
const blockSchema = e.dragItem.schema;
|
||||||
const path = [...e.dragItem.path];
|
const path = [...e.dragItem.path];
|
||||||
prepend({
|
const data = prepend({
|
||||||
type: 'void',
|
type: 'void',
|
||||||
'x-component': 'Grid.Row',
|
'x-component': 'Grid.Row',
|
||||||
properties: {
|
properties: {
|
||||||
@ -109,6 +109,8 @@ export const Grid: any = observer((props) => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
await createSchema(data);
|
||||||
|
console.log('prepend', data);
|
||||||
deepRemove(path);
|
deepRemove(path);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
@ -121,10 +123,10 @@ export const Grid: any = observer((props) => {
|
|||||||
<RowDivider
|
<RowDivider
|
||||||
key={`${schema.name}_${index + 1}`}
|
key={`${schema.name}_${index + 1}`}
|
||||||
name={`${schema.name}_${index + 1}`}
|
name={`${schema.name}_${index + 1}`}
|
||||||
onDrop={(e) => {
|
onDrop={async (e) => {
|
||||||
const blockSchema = e.dragItem.schema;
|
const blockSchema = e.dragItem.schema;
|
||||||
const path = [...e.dragItem.path];
|
const path = [...e.dragItem.path];
|
||||||
insertAfter(
|
const data = insertAfter(
|
||||||
{
|
{
|
||||||
type: 'void',
|
type: 'void',
|
||||||
'x-component': 'Grid.Row',
|
'x-component': 'Grid.Row',
|
||||||
@ -140,6 +142,8 @@ export const Grid: any = observer((props) => {
|
|||||||
},
|
},
|
||||||
[...gridPath, key],
|
[...gridPath, key],
|
||||||
);
|
);
|
||||||
|
await createSchema(data);
|
||||||
|
console.log('insertAfter', data);
|
||||||
deepRemove(path);
|
deepRemove(path);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
@ -170,15 +174,16 @@ Grid.Row = observer((props) => {
|
|||||||
<ColumnSizeContext.Provider value={len}>
|
<ColumnSizeContext.Provider value={len}>
|
||||||
<ColDivider
|
<ColDivider
|
||||||
name={`${schema.name}_0`}
|
name={`${schema.name}_0`}
|
||||||
onDrop={(e) => {
|
onDrop={async (e) => {
|
||||||
const blockSchema = e.dragItem.schema;
|
const blockSchema = e.dragItem.schema;
|
||||||
prepend({
|
const data = prepend({
|
||||||
type: 'void',
|
type: 'void',
|
||||||
'x-component': 'Grid.Col',
|
'x-component': 'Grid.Col',
|
||||||
properties: {
|
properties: {
|
||||||
[blockSchema.name]: blockSchema,
|
[blockSchema.name]: blockSchema,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
await createSchema(data);
|
||||||
const path = [...e.dragItem.path];
|
const path = [...e.dragItem.path];
|
||||||
deepRemove(path);
|
deepRemove(path);
|
||||||
}}
|
}}
|
||||||
@ -190,9 +195,9 @@ Grid.Row = observer((props) => {
|
|||||||
<ColDivider
|
<ColDivider
|
||||||
name={`${schema.name}_${index + 1}`}
|
name={`${schema.name}_${index + 1}`}
|
||||||
resizable={index < len - 1}
|
resizable={index < len - 1}
|
||||||
onDrop={(e) => {
|
onDrop={async (e) => {
|
||||||
const blockSchema = e.dragItem.schema;
|
const blockSchema = e.dragItem.schema;
|
||||||
insertAfter(
|
const data = insertAfter(
|
||||||
{
|
{
|
||||||
type: 'void',
|
type: 'void',
|
||||||
'x-component': 'Grid.Col',
|
'x-component': 'Grid.Col',
|
||||||
@ -202,6 +207,8 @@ Grid.Row = observer((props) => {
|
|||||||
},
|
},
|
||||||
[...rowPath, key],
|
[...rowPath, key],
|
||||||
);
|
);
|
||||||
|
console.log('ColDivider', data)
|
||||||
|
await createSchema(data);
|
||||||
const path = [...e.dragItem.path];
|
const path = [...e.dragItem.path];
|
||||||
deepRemove(path);
|
deepRemove(path);
|
||||||
}}
|
}}
|
||||||
@ -242,45 +249,3 @@ Grid.Col = observer((props) => {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Grid.Block = observer((props) => {
|
|
||||||
// const schema = useFieldSchema();
|
|
||||||
// const uid = useDragDropUID();
|
|
||||||
// const path = useSchemaPath();
|
|
||||||
// const { isDragging, dragRef, previewRef } = useDrag({
|
|
||||||
// type: uid,
|
|
||||||
// onDragStart() {
|
|
||||||
// console.log('onDragStart');
|
|
||||||
// },
|
|
||||||
// onDragEnd(event) {
|
|
||||||
// console.log('onDragEnd', event.data);
|
|
||||||
// },
|
|
||||||
// onDrag(event) {
|
|
||||||
// // console.log('onDrag');
|
|
||||||
// },
|
|
||||||
// item: {
|
|
||||||
// path,
|
|
||||||
// schema: schema.toJSON(),
|
|
||||||
// },
|
|
||||||
// });
|
|
||||||
// const { isOver, onTopHalf, dropRef } = useDrop({
|
|
||||||
// uid: schema.name,
|
|
||||||
// accept: uid,
|
|
||||||
// data: {},
|
|
||||||
// canDrop: !isDragging,
|
|
||||||
// });
|
|
||||||
// return (
|
|
||||||
// <GridBlockContext.Provider value={{ dragRef }}>
|
|
||||||
// <div
|
|
||||||
// ref={mergeRefs([previewRef, dropRef])}
|
|
||||||
// className={cls('nb-grid-block', {
|
|
||||||
// 'top-half': onTopHalf,
|
|
||||||
// hover: isOver,
|
|
||||||
// dragging: isDragging,
|
|
||||||
// })}
|
|
||||||
// >
|
|
||||||
// {props.children}
|
|
||||||
// </div>
|
|
||||||
// </GridBlockContext.Provider>
|
|
||||||
// );
|
|
||||||
// });
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { ISchema } from '@formily/react';
|
||||||
import { createContext } from 'react';
|
import { createContext } from 'react';
|
||||||
|
|
||||||
export * from '../components/schema-renderer';
|
export * from '../components/schema-renderer';
|
||||||
@ -16,3 +17,28 @@ export const request = extend({
|
|||||||
prefix: 'http://localhost:23003/api/',
|
prefix: 'http://localhost:23003/api/',
|
||||||
timeout: 1000,
|
timeout: 1000,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
export async function createSchema(schema: ISchema) {
|
||||||
|
if (!schema['key']) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return await request('ui_schemas:create', {
|
||||||
|
method: 'post',
|
||||||
|
data: schema.toJSON(),
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export async function removeSchema(schema: ISchema) {
|
||||||
|
if (!schema['key']) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await request('ui_schemas:destroy', {
|
||||||
|
method: 'post',
|
||||||
|
params: {
|
||||||
|
filter: {
|
||||||
|
key: schema['key'],
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { connect, mapProps, mapReadPretty } from '@formily/react';
|
import { connect, mapProps, mapReadPretty, useFieldSchema } from '@formily/react';
|
||||||
import { Input as AntdInput } from 'antd';
|
import { Input as AntdInput } from 'antd';
|
||||||
import { InputProps, TextAreaProps } from 'antd/lib/input';
|
import { InputProps, TextAreaProps } from 'antd/lib/input';
|
||||||
import { Display } from '../display';
|
import { Display } from '../display';
|
||||||
@ -7,7 +7,10 @@ import { LoadingOutlined } from '@ant-design/icons';
|
|||||||
import micromark from 'micromark';
|
import micromark from 'micromark';
|
||||||
|
|
||||||
export const Markdown = connect(
|
export const Markdown = connect(
|
||||||
AntdInput.TextArea,
|
(props) => {
|
||||||
|
const schema = useFieldSchema();
|
||||||
|
return <AntdInput.TextArea defaultValue={schema.name} {...props}/>
|
||||||
|
},
|
||||||
mapProps((props: any, field) => {
|
mapProps((props: any, field) => {
|
||||||
return {
|
return {
|
||||||
...props,
|
...props,
|
||||||
|
71
packages/client/src/schemas/menu/defaultSchemas.ts
Normal file
71
packages/client/src/schemas/menu/defaultSchemas.ts
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
import { ISchema } from '@formily/react';
|
||||||
|
import { uid } from '@formily/shared';
|
||||||
|
|
||||||
|
export const defaultSchemas = {
|
||||||
|
MixMenu: {
|
||||||
|
type: 'void',
|
||||||
|
'x-component': 'Menu',
|
||||||
|
'x-designable-bar': 'Menu.DesignableBar',
|
||||||
|
'x-component-props': {
|
||||||
|
sideMenuRef: '{{ sideMenuRef }}',
|
||||||
|
mode: 'mix',
|
||||||
|
theme: 'dark',
|
||||||
|
// onSelect: '{{ onSelect }}',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'Menu.Item': {
|
||||||
|
type: 'void',
|
||||||
|
'x-designable-bar': 'Menu.DesignableBar',
|
||||||
|
'x-component': 'Menu.Item',
|
||||||
|
},
|
||||||
|
'Menu.Link': {
|
||||||
|
type: 'void',
|
||||||
|
'x-designable-bar': 'Menu.DesignableBar',
|
||||||
|
'x-component': 'Menu.Link',
|
||||||
|
properties: {
|
||||||
|
[uid()]: {
|
||||||
|
type: 'void',
|
||||||
|
name: uid(),
|
||||||
|
'x-component': 'Grid',
|
||||||
|
properties: {
|
||||||
|
[`row_${uid()}`]: {
|
||||||
|
type: 'void',
|
||||||
|
'x-component': 'Grid.Row',
|
||||||
|
'x-component-props': {
|
||||||
|
locked: true,
|
||||||
|
},
|
||||||
|
properties: {
|
||||||
|
[`col_${uid()}`]: {
|
||||||
|
type: 'void',
|
||||||
|
'x-component': 'Grid.Col',
|
||||||
|
properties: {
|
||||||
|
[uid()]: {
|
||||||
|
type: 'void',
|
||||||
|
'x-component': 'AddNew.BlockItem',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'Menu.URL': {
|
||||||
|
type: 'void',
|
||||||
|
'x-designable-bar': 'Menu.DesignableBar',
|
||||||
|
'x-component': 'Menu.URL',
|
||||||
|
},
|
||||||
|
'Menu.SubMenu': {
|
||||||
|
type: 'void',
|
||||||
|
'x-designable-bar': 'Menu.DesignableBar',
|
||||||
|
'x-component': 'Menu.SubMenu',
|
||||||
|
},
|
||||||
|
'Menu.Action': {
|
||||||
|
type: 'void',
|
||||||
|
'x-designable-bar': 'Menu.DesignableBar',
|
||||||
|
'x-component': 'Menu.Action',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default defaultSchemas;
|
@ -35,21 +35,21 @@ import cls from 'classnames';
|
|||||||
import { useDesignable } from '../../components/schema-renderer';
|
import { useDesignable } from '../../components/schema-renderer';
|
||||||
import { MenuOutlined, PlusOutlined } from '@ant-design/icons';
|
import { MenuOutlined, PlusOutlined } from '@ant-design/icons';
|
||||||
import { IconPicker } from '../../components/icon-picker';
|
import { IconPicker } from '../../components/icon-picker';
|
||||||
import { useDefaultAction, VisibleContext } from '..';
|
import { createSchema, removeSchema, useDefaultAction, VisibleContext } from '..';
|
||||||
import { useMount } from 'ahooks';
|
import { useMount } from 'ahooks';
|
||||||
import './style.less';
|
import './style.less';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
import { useSchemaPath } from '@nocobase/client/lib';
|
import { findPropertyByPath, useSchemaPath } from '@nocobase/client/lib';
|
||||||
import { request } from '../';
|
import { request } from '../';
|
||||||
|
import defaultSchemas from './defaultSchemas';
|
||||||
|
import { get } from 'lodash';
|
||||||
|
|
||||||
export const MenuModeContext = createContext(null);
|
export const MenuModeContext = createContext(null);
|
||||||
|
|
||||||
function useSelectedKey() {}
|
|
||||||
|
|
||||||
const SideMenu = (props: any) => {
|
const SideMenu = (props: any) => {
|
||||||
const { visible, selectedKey, onSelect, path } = props;
|
const { selectedKey, onSelect, path } = props;
|
||||||
const { schema } = useDesignable();
|
const { schema } = useDesignable();
|
||||||
if (!selectedKey || !visible) {
|
if (!selectedKey) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const child = schema.properties && schema.properties[selectedKey];
|
const child = schema.properties && schema.properties[selectedKey];
|
||||||
@ -108,7 +108,9 @@ export const Menu: any = observer((props: any) => {
|
|||||||
if (mode === 'mix') {
|
if (mode === 'mix') {
|
||||||
setSelectedKey(info.key);
|
setSelectedKey(info.key);
|
||||||
}
|
}
|
||||||
onSelect && onSelect(info);
|
const selectedSchema = schema.properties[info.key];
|
||||||
|
console.log({ selectedSchema })
|
||||||
|
onSelect && onSelect({ ...info, schema: selectedSchema });
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<RecursionField schema={schema} onlyRenderProperties />
|
<RecursionField schema={schema} onlyRenderProperties />
|
||||||
@ -120,8 +122,12 @@ export const Menu: any = observer((props: any) => {
|
|||||||
<div ref={ref}>
|
<div ref={ref}>
|
||||||
<SideMenu
|
<SideMenu
|
||||||
path={path}
|
path={path}
|
||||||
onSelect={onSelect}
|
onSelect={(info) => {
|
||||||
visible={mode === 'mix'}
|
const keyPath = [selectedKey, ...info.keyPath];
|
||||||
|
const selectedSchema = findPropertyByPath(schema, keyPath);
|
||||||
|
console.log('keyPath', keyPath, selectedSchema);
|
||||||
|
onSelect && onSelect({ ...info, keyPath, schema: selectedSchema });
|
||||||
|
}}
|
||||||
selectedKey={selectedKey}
|
selectedKey={selectedKey}
|
||||||
sideMenuRef={sideMenuRef}
|
sideMenuRef={sideMenuRef}
|
||||||
/>
|
/>
|
||||||
@ -131,62 +137,6 @@ export const Menu: any = observer((props: any) => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
Menu.AddNew = observer((props: any) => {
|
|
||||||
const { appendChild } = useDesignable(props.path);
|
|
||||||
return (
|
|
||||||
<AntdMenu.ItemGroup
|
|
||||||
className={'nb-menu-add-new'}
|
|
||||||
title={
|
|
||||||
<Dropdown
|
|
||||||
overlay={
|
|
||||||
<AntdMenu>
|
|
||||||
<AntdMenu.Item
|
|
||||||
onClick={async () => {
|
|
||||||
const data = appendChild({
|
|
||||||
type: 'void',
|
|
||||||
title: uid(),
|
|
||||||
'x-component': 'Menu.Item',
|
|
||||||
'x-designable-bar': 'Menu.DesignableBar',
|
|
||||||
});
|
|
||||||
if (data['key']) {
|
|
||||||
await request('ui_schemas:create', {
|
|
||||||
method: 'post',
|
|
||||||
data: data.toJSON(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
新建菜单
|
|
||||||
</AntdMenu.Item>
|
|
||||||
<AntdMenu.Item
|
|
||||||
onClick={async () => {
|
|
||||||
const data = appendChild({
|
|
||||||
type: 'void',
|
|
||||||
key: uid(),
|
|
||||||
title: uid(),
|
|
||||||
'x-component': 'Menu.SubMenu',
|
|
||||||
'x-designable-bar': 'Menu.DesignableBar',
|
|
||||||
});
|
|
||||||
if (data['key']) {
|
|
||||||
await request('ui_schemas:create', {
|
|
||||||
method: 'post',
|
|
||||||
data: data.toJSON(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
新建菜单组
|
|
||||||
</AntdMenu.Item>
|
|
||||||
</AntdMenu>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<a>{props.children}</a>
|
|
||||||
</Dropdown>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
Menu.Divider = observer(AntdMenu.Divider);
|
Menu.Divider = observer(AntdMenu.Divider);
|
||||||
|
|
||||||
Menu.Item = observer((props: any) => {
|
Menu.Item = observer((props: any) => {
|
||||||
@ -288,6 +238,47 @@ Menu.SubMenu = observer((props: any) => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Menu.AddNew = observer((props: any) => {
|
||||||
|
const { appendChild } = useDesignable(props.path);
|
||||||
|
return (
|
||||||
|
<AntdMenu.ItemGroup
|
||||||
|
className={'nb-menu-add-new'}
|
||||||
|
title={
|
||||||
|
<Dropdown
|
||||||
|
overlay={
|
||||||
|
<AntdMenu>
|
||||||
|
<AntdMenu.Item
|
||||||
|
onClick={async () => {
|
||||||
|
const data = appendChild({
|
||||||
|
...defaultSchemas['Menu.Link'],
|
||||||
|
title: uid(),
|
||||||
|
});
|
||||||
|
await createSchema(data);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
新建菜单
|
||||||
|
</AntdMenu.Item>
|
||||||
|
<AntdMenu.Item
|
||||||
|
onClick={async () => {
|
||||||
|
const data = appendChild({
|
||||||
|
...defaultSchemas['Menu.SubMenu'],
|
||||||
|
title: uid(),
|
||||||
|
});
|
||||||
|
await createSchema(data);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
新建菜单组
|
||||||
|
</AntdMenu.Item>
|
||||||
|
</AntdMenu>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<a>{props.children}</a>
|
||||||
|
</Dropdown>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
Menu.DesignableBar = (props) => {
|
Menu.DesignableBar = (props) => {
|
||||||
const field = useField();
|
const field = useField();
|
||||||
const [visible, setVisible] = useState(false);
|
const [visible, setVisible] = useState(false);
|
||||||
@ -328,51 +319,32 @@ Menu.DesignableBar = (props) => {
|
|||||||
<AntdMenu.Item
|
<AntdMenu.Item
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
const s = insertAfter({
|
const s = insertAfter({
|
||||||
type: 'void',
|
...defaultSchemas['Menu.Link'],
|
||||||
title: uid(),
|
title: uid(),
|
||||||
'x-component': 'Menu.SubMenu',
|
|
||||||
});
|
});
|
||||||
console.log('s.s.s.s', s);
|
await createSchema(s);
|
||||||
if (s['key']) {
|
|
||||||
await request('ui_schemas:create', {
|
|
||||||
method: 'post',
|
|
||||||
data: s.toJSON(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
新建分组
|
新建菜单项
|
||||||
</AntdMenu.Item>
|
</AntdMenu.Item>
|
||||||
<AntdMenu.Item
|
<AntdMenu.Item
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
const s = insertAfter({
|
const s = insertAfter({
|
||||||
type: 'void',
|
...defaultSchemas['Menu.SubMenu'],
|
||||||
title: uid(),
|
title: uid(),
|
||||||
'x-component': 'Menu.Item',
|
|
||||||
});
|
});
|
||||||
if (s['key']) {
|
await createSchema(s);
|
||||||
await request('ui_schemas:create', {
|
|
||||||
method: 'post',
|
|
||||||
data: s.toJSON(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
新建菜单
|
新建菜单分组
|
||||||
</AntdMenu.Item>
|
</AntdMenu.Item>
|
||||||
<AntdMenu.Item
|
<AntdMenu.Item
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
const s = appendChild({
|
const s = appendChild({
|
||||||
type: 'void',
|
...defaultSchemas['Menu.Link'],
|
||||||
title: uid(),
|
title: uid(),
|
||||||
'x-component': 'Menu.Item',
|
|
||||||
});
|
});
|
||||||
if (s['key']) {
|
await createSchema(s);
|
||||||
await request('ui_schemas:create', {
|
|
||||||
method: 'post',
|
|
||||||
data: s.toJSON(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
在菜单组里新增
|
在菜单组里新增
|
||||||
@ -382,8 +354,9 @@ Menu.DesignableBar = (props) => {
|
|||||||
Modal.confirm({
|
Modal.confirm({
|
||||||
title: '删除菜单',
|
title: '删除菜单',
|
||||||
content: '确认删除此菜单项吗?',
|
content: '确认删除此菜单项吗?',
|
||||||
onOk: () => {
|
onOk: async () => {
|
||||||
remove();
|
const target = remove();
|
||||||
|
await removeSchema(target);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
|
@ -1,35 +0,0 @@
|
|||||||
import { Model, ModelCtor } from '@nocobase/database';
|
|
||||||
import { actions } from '@nocobase/actions';
|
|
||||||
|
|
||||||
export default async (ctx: actions.Context, next: actions.Next) => {
|
|
||||||
const { resourceKey, filter } = ctx.action.params;
|
|
||||||
const UISchema = ctx.db.getModel('ui_schemas');
|
|
||||||
if (resourceKey) {
|
|
||||||
const schema = await UISchema.findByPk(resourceKey);
|
|
||||||
const property = schema.toProperty();
|
|
||||||
const properties = await schema.getProperties();
|
|
||||||
if (Object.keys(properties).length) {
|
|
||||||
property.properties = properties;
|
|
||||||
}
|
|
||||||
ctx.body = property;
|
|
||||||
} else {
|
|
||||||
const schemas = await UISchema.findAll(UISchema.parseApiJson({
|
|
||||||
filter,
|
|
||||||
}));
|
|
||||||
let properties = {};
|
|
||||||
for (const schema of schemas) {
|
|
||||||
const property = schema.toProperty();
|
|
||||||
const properties = await schema.getProperties();
|
|
||||||
if (Object.keys(properties).length) {
|
|
||||||
property.properties = properties;
|
|
||||||
}
|
|
||||||
properties[property.name] = property;
|
|
||||||
}
|
|
||||||
ctx.body = {
|
|
||||||
type: 'object',
|
|
||||||
properties,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
await next();
|
|
||||||
}
|
|
91
packages/plugin-ui-schema/src/actions/index.ts
Normal file
91
packages/plugin-ui-schema/src/actions/index.ts
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
import { Model, ModelCtor } from '@nocobase/database';
|
||||||
|
import { actions, middlewares } from '@nocobase/actions';
|
||||||
|
import { sort } from '@nocobase/actions/src/actions/common';
|
||||||
|
import { cloneDeep, omit } from 'lodash';
|
||||||
|
|
||||||
|
export const create = async (ctx: actions.Context, next: actions.Next) => {
|
||||||
|
const values = cloneDeep(ctx.action.params.values);
|
||||||
|
ctx.action.mergeParams(
|
||||||
|
{
|
||||||
|
values: omit(values, [
|
||||||
|
'__insertAfter__',
|
||||||
|
'__insertBefore__',
|
||||||
|
'__prepend__',
|
||||||
|
'_isJSONSchemaObject',
|
||||||
|
]),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
payload: 'replace',
|
||||||
|
},
|
||||||
|
);
|
||||||
|
await actions.common.create(ctx, async () => {});
|
||||||
|
const targetKey = values['__insertAfter__'] || values['__insertBefore__'];
|
||||||
|
if (targetKey) {
|
||||||
|
console.log({
|
||||||
|
associatedKey: values.parentKey,
|
||||||
|
resourceKey: ctx.body.key,
|
||||||
|
values: {
|
||||||
|
field: 'sort',
|
||||||
|
target: {
|
||||||
|
key: targetKey,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
ctx.action.mergeParams(
|
||||||
|
{
|
||||||
|
associatedKey: values.parentKey,
|
||||||
|
resourceKey: ctx.body.key,
|
||||||
|
values: {
|
||||||
|
field: 'sort',
|
||||||
|
insertAfter: !!values['__insertAfter__'],
|
||||||
|
target: {
|
||||||
|
key: targetKey,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
payload: 'replace',
|
||||||
|
},
|
||||||
|
);
|
||||||
|
await middlewares.associated(ctx, async () => {});
|
||||||
|
await sort(ctx, async () => {});
|
||||||
|
}
|
||||||
|
await next();
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getTree = async (ctx: actions.Context, next: actions.Next) => {
|
||||||
|
const { resourceKey, filter } = ctx.action.params;
|
||||||
|
const UISchema = ctx.db.getModel('ui_schemas');
|
||||||
|
if (resourceKey) {
|
||||||
|
const schema = await UISchema.findByPk(resourceKey);
|
||||||
|
const property = schema.toProperty();
|
||||||
|
const properties = await schema.getProperties();
|
||||||
|
if (Object.keys(properties).length) {
|
||||||
|
property.properties = properties;
|
||||||
|
}
|
||||||
|
ctx.body = property;
|
||||||
|
} else {
|
||||||
|
const schemas = await UISchema.findAll(
|
||||||
|
UISchema.parseApiJson({
|
||||||
|
filter,
|
||||||
|
sort: ['sort'],
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
console.log({ schemas });
|
||||||
|
let properties = {};
|
||||||
|
for (const schema of schemas) {
|
||||||
|
const property = schema.toProperty();
|
||||||
|
const childProperties = await schema.getProperties();
|
||||||
|
if (Object.keys(childProperties).length) {
|
||||||
|
property.properties = childProperties;
|
||||||
|
}
|
||||||
|
properties[property.name] = property;
|
||||||
|
}
|
||||||
|
ctx.body = {
|
||||||
|
type: 'object',
|
||||||
|
properties,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
await next();
|
||||||
|
};
|
@ -10,6 +10,11 @@ export default {
|
|||||||
name: 'key',
|
name: 'key',
|
||||||
primaryKey: true,
|
primaryKey: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
type: 'sort',
|
||||||
|
name: 'sort',
|
||||||
|
scope: ['parentKey'],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
type: 'string',
|
type: 'string',
|
||||||
name: 'name',
|
name: 'name',
|
||||||
|
@ -7,6 +7,13 @@ export class UISchema extends Model {
|
|||||||
const attributes = this.toAttributes(value);
|
const attributes = this.toAttributes(value);
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
const model: Model = await super.create(attributes, options);
|
const model: Model = await super.create(attributes, options);
|
||||||
|
if (value['__prepend__']) {
|
||||||
|
console.log('__prepend__', model.parentKey);
|
||||||
|
} else if (value['__insertAfter__']) {
|
||||||
|
console.log('__insertAfter__', model.parentKey);
|
||||||
|
} else if (value['__insertBefore__']) {
|
||||||
|
console.log('__insertBefore__', model.parentKey);
|
||||||
|
}
|
||||||
if (!attributes.children) {
|
if (!attributes.children) {
|
||||||
attributes.children = this.properties2children(attributes.properties);
|
attributes.children = this.properties2children(attributes.properties);
|
||||||
await model.updateAssociation('children', attributes.children, options);
|
await model.updateAssociation('children', attributes.children, options);
|
||||||
@ -48,7 +55,9 @@ export class UISchema extends Model {
|
|||||||
|
|
||||||
async getProperties() {
|
async getProperties() {
|
||||||
const properties = {};
|
const properties = {};
|
||||||
const children: UISchema[] = await this.getChildren();
|
const children: UISchema[] = await this.getChildren({
|
||||||
|
order: [['sort', 'asc']],
|
||||||
|
});
|
||||||
for (const child of children) {
|
for (const child of children) {
|
||||||
const property = child.toProperty();
|
const property = child.toProperty();
|
||||||
const childProperties = await child.getProperties();
|
const childProperties = await child.getProperties();
|
||||||
|
@ -2,7 +2,7 @@ import path from 'path';
|
|||||||
import { Application } from '@nocobase/server';
|
import { Application } from '@nocobase/server';
|
||||||
import { registerModels, Table } from '@nocobase/database';
|
import { registerModels, Table } from '@nocobase/database';
|
||||||
import * as models from './models';
|
import * as models from './models';
|
||||||
import getTree from './actions/getTree';
|
import { create, getTree } from './actions';
|
||||||
|
|
||||||
export default async function (this: Application, options = {}) {
|
export default async function (this: Application, options = {}) {
|
||||||
const database = this.database;
|
const database = this.database;
|
||||||
@ -12,11 +12,6 @@ export default async function (this: Application, options = {}) {
|
|||||||
directory: path.resolve(__dirname, 'collections'),
|
directory: path.resolve(__dirname, 'collections'),
|
||||||
});
|
});
|
||||||
|
|
||||||
// database.getModel('ui_schemas').beforeCreate((model) => {
|
this.resourcer.registerActionHandler('ui_schemas:create', create);
|
||||||
// if (!model.get('name')) {
|
|
||||||
// model.set('name', model.get('key'));
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
|
|
||||||
this.resourcer.registerActionHandler('ui_schemas:getTree', getTree);
|
this.resourcer.registerActionHandler('ui_schemas:getTree', getTree);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user