updates...
This commit is contained in:
parent
057dc8406a
commit
63538cf240
@ -1,68 +0,0 @@
|
||||
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>
|
||||
</>
|
||||
);
|
||||
};
|
@ -1,49 +0,0 @@
|
||||
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;
|
@ -1,56 +0,0 @@
|
||||
|
||||
export const schema = {
|
||||
type: 'void',
|
||||
name: 'action1',
|
||||
// title: 'ModalForm',
|
||||
'x-component': 'Action',
|
||||
'x-component-props': {
|
||||
type: 'primary',
|
||||
icon: 'DatabaseOutlined',
|
||||
},
|
||||
properties: {
|
||||
modal1: {
|
||||
type: 'void',
|
||||
title: '对话框标题',
|
||||
'x-decorator': 'Form',
|
||||
'x-component': 'Action.Modal',
|
||||
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: '内容',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default schema;
|
45
packages/client/src/components/admin-layout/datatable.tsx
Normal file
45
packages/client/src/components/admin-layout/datatable.tsx
Normal file
@ -0,0 +1,45 @@
|
||||
import { SchemaRenderer } from '@nocobase/client/lib';
|
||||
import React from 'react';
|
||||
|
||||
export default () => {
|
||||
const schema = {
|
||||
type: 'array',
|
||||
name: 'collections',
|
||||
'x-component': 'DatabaseCollection',
|
||||
'x-component-props': {},
|
||||
default: [
|
||||
{
|
||||
name: 'test1',
|
||||
title: '数据表 1',
|
||||
},
|
||||
{
|
||||
name: 'test2',
|
||||
title: '数据表 2',
|
||||
},
|
||||
],
|
||||
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,
|
||||
},
|
||||
fields: {
|
||||
type: 'array',
|
||||
title: '数据表字段',
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'DatabaseField',
|
||||
default: [],
|
||||
},
|
||||
},
|
||||
};
|
||||
return <SchemaRenderer schema={schema} />;
|
||||
};
|
@ -23,7 +23,7 @@ import './style.less';
|
||||
|
||||
import { uid } from '@formily/shared';
|
||||
import { ISchema } from '@formily/react';
|
||||
import DataTableConfig from './DataTableConfig';
|
||||
import Database from './datatable';
|
||||
|
||||
function LayoutWithMenu({ schema }) {
|
||||
const match = useRouteMatch<any>();
|
||||
@ -53,7 +53,7 @@ function LayoutWithMenu({ schema }) {
|
||||
selectedKeys: [activeKey].filter(Boolean),
|
||||
}}
|
||||
/>
|
||||
<DataTableConfig />
|
||||
<Database />
|
||||
</Layout.Header>
|
||||
<Layout>
|
||||
<Layout.Sider
|
||||
|
@ -18,20 +18,20 @@
|
||||
// }
|
||||
// }
|
||||
|
||||
.ant-collapse {
|
||||
border: 1px solid #d9d9d9 !important;
|
||||
border-bottom: 0 !important;
|
||||
> .ant-collapse-item {
|
||||
border-bottom: 1px solid #d9d9d9 !important;
|
||||
}
|
||||
.ant-collapse-content {
|
||||
border-top: 1px solid #d9d9d9 !important;
|
||||
}
|
||||
.ant-collapse-content > .ant-collapse-content-box {
|
||||
padding: 24px !important;
|
||||
padding-bottom: 0 !important;
|
||||
}
|
||||
}
|
||||
// .ant-collapse {
|
||||
// border: 1px solid #d9d9d9 !important;
|
||||
// border-bottom: 0 !important;
|
||||
// > .ant-collapse-item {
|
||||
// border-bottom: 1px solid #d9d9d9 !important;
|
||||
// }
|
||||
// .ant-collapse-content {
|
||||
// border-top: 1px solid #d9d9d9 !important;
|
||||
// }
|
||||
// .ant-collapse-content > .ant-collapse-content-box {
|
||||
// padding: 24px !important;
|
||||
// padding-bottom: 0 !important;
|
||||
// }
|
||||
// }
|
||||
|
||||
.database-sider {
|
||||
background: #fafafa;
|
||||
|
@ -27,7 +27,7 @@ import { AddNew } from '../../schemas/add-new';
|
||||
import { Cascader } from '../../schemas/cascader';
|
||||
import { Checkbox } from '../../schemas/checkbox';
|
||||
import { ColorSelect } from '../../schemas/color-select';
|
||||
import { DatabaseField } from '../../schemas/database-field';
|
||||
import { DatabaseField, DatabaseCollection } from '../../schemas/database-field';
|
||||
import { DatePicker } from '../../schemas/date-picker';
|
||||
import { Filter } from '../../schemas/filter';
|
||||
import { Form } from '../../schemas/form';
|
||||
@ -79,6 +79,7 @@ export const SchemaField = createSchemaField({
|
||||
Checkbox,
|
||||
ColorSelect,
|
||||
DatabaseField,
|
||||
DatabaseCollection,
|
||||
DatePicker,
|
||||
Filter,
|
||||
Form,
|
||||
|
@ -1,55 +1,46 @@
|
||||
import React from 'react';
|
||||
import { createForm } from '@formily/core';
|
||||
import { SchemaRenderer } from '../../';
|
||||
import { observer, connect, useField } from '@formily/react';
|
||||
import { observer, connect, useField, ISchema } from '@formily/react';
|
||||
|
||||
const schema = {
|
||||
type: 'void',
|
||||
name: 'action1',
|
||||
title: 'ModalForm',
|
||||
'x-component': 'Action',
|
||||
const schema: ISchema = {
|
||||
type: 'array',
|
||||
name: 'collections',
|
||||
'x-component': 'DatabaseCollection',
|
||||
'x-component-props': {},
|
||||
properties: {
|
||||
modal1: {
|
||||
type: 'void',
|
||||
title: '对话框标题',
|
||||
'x-decorator': 'Form',
|
||||
'x-component': 'Action.Modal',
|
||||
properties: {
|
||||
title: {
|
||||
type: 'string',
|
||||
title: '数据表名称',
|
||||
required: true,
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'Input',
|
||||
},
|
||||
fields: {
|
||||
type: 'array',
|
||||
'x-component': 'DatabaseField',
|
||||
default: [
|
||||
{
|
||||
id: 1,
|
||||
interface: 'string',
|
||||
dataType: 'string',
|
||||
name: 'title',
|
||||
ui: {
|
||||
title: '标题',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
dataType: 'text',
|
||||
interface: 'textarea',
|
||||
name: 'content',
|
||||
ui: {
|
||||
title: '内容',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
default: [
|
||||
{
|
||||
name: 'test1',
|
||||
title: '数据表 1',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'test2',
|
||||
title: '数据表 2',
|
||||
}
|
||||
],
|
||||
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,
|
||||
},
|
||||
fields: {
|
||||
type: 'array',
|
||||
title: '数据表字段',
|
||||
'x-decorator': 'FormItem',
|
||||
'x-component': 'DatabaseField',
|
||||
default: [],
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const form = createForm();
|
||||
|
@ -7,17 +7,177 @@ import {
|
||||
ISchema,
|
||||
Schema,
|
||||
useFieldSchema,
|
||||
useForm,
|
||||
} from '@formily/react';
|
||||
import { ArrayCollapse } from '@formily/antd';
|
||||
import { ArrayCollapse, FormLayout } from '@formily/antd';
|
||||
import { uid } from '@formily/shared';
|
||||
import '@formily/antd/lib/form-tab/style';
|
||||
import { Collapse, Button, Dropdown, Menu, Tag } from 'antd';
|
||||
import {
|
||||
Collapse,
|
||||
Button,
|
||||
Dropdown,
|
||||
Menu,
|
||||
Tag,
|
||||
Select,
|
||||
Divider,
|
||||
Input,
|
||||
} from 'antd';
|
||||
import { options, interfaces } from './interfaces';
|
||||
import { DeleteOutlined } from '@ant-design/icons';
|
||||
import {
|
||||
DeleteOutlined,
|
||||
DatabaseOutlined,
|
||||
PlusOutlined,
|
||||
CloseOutlined,
|
||||
} from '@ant-design/icons';
|
||||
import cls from 'classnames';
|
||||
import './style.less';
|
||||
import Modal from 'antd/lib/modal/Modal';
|
||||
import { get } from 'lodash';
|
||||
import { useEffect } from 'react';
|
||||
import { useRequest } from 'ahooks';
|
||||
import { createOrUpdateCollection, deleteCollection } from '..';
|
||||
|
||||
export const DatabaseCollection = observer((props) => {
|
||||
const field = useField<Formily.Core.Models.ArrayField>();
|
||||
const [visible, setVisible] = useState(false);
|
||||
const [open, setOpen] = useState(false);
|
||||
const schema = useFieldSchema();
|
||||
const [activeIndex, setActiveIndex] = useState(0);
|
||||
const form = useForm();
|
||||
const [newValue, setNewValue] = useState('');
|
||||
|
||||
useRequest('collections:list?sort=-created_at', {
|
||||
formatResult: (result) => result?.data,
|
||||
onSuccess(data) {
|
||||
field.setValue(data);
|
||||
console.log('onSuccess', data);
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Button
|
||||
onClick={() => {
|
||||
setVisible(true);
|
||||
}}
|
||||
type={'primary'}
|
||||
>
|
||||
<DatabaseOutlined />
|
||||
</Button>
|
||||
<Modal
|
||||
title={
|
||||
<div style={{ textAlign: 'center' }}>
|
||||
<Select
|
||||
value={activeIndex}
|
||||
style={{ minWidth: 300, textAlign: 'center' }}
|
||||
onChange={(value) => {
|
||||
setActiveIndex(value as any);
|
||||
}}
|
||||
open={open}
|
||||
onDropdownVisibleChange={setOpen}
|
||||
optionLabelProp={'label'}
|
||||
dropdownRender={(menu) => {
|
||||
return (
|
||||
<div>
|
||||
{menu}
|
||||
<Divider style={{ margin: '5px 0 4px' }} />
|
||||
<div
|
||||
style={{
|
||||
cursor: 'pointer',
|
||||
padding: '5px 12px',
|
||||
}}
|
||||
>
|
||||
<Input.Search
|
||||
size={'middle'}
|
||||
placeholder={'新增数据表'}
|
||||
enterButton={<PlusOutlined />}
|
||||
value={newValue}
|
||||
onChange={(e) => {
|
||||
setNewValue(e.target.value);
|
||||
}}
|
||||
onSearch={async (value) => {
|
||||
const data = {
|
||||
name: uid(),
|
||||
title: value,
|
||||
};
|
||||
field.push(data);
|
||||
setActiveIndex(field.value.length - 1);
|
||||
setOpen(false);
|
||||
setNewValue('');
|
||||
await createOrUpdateCollection(data);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}}
|
||||
>
|
||||
{field.value?.map((item, index) => {
|
||||
return (
|
||||
<Select.Option value={index} label={item.title || '未命名'}>
|
||||
<div
|
||||
style={{
|
||||
display: 'flex',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'center',
|
||||
}}
|
||||
>
|
||||
{item.title || '未命名'}
|
||||
<DeleteOutlined
|
||||
onClick={async (e) => {
|
||||
e.stopPropagation();
|
||||
field.remove(index);
|
||||
if (activeIndex === index) {
|
||||
setActiveIndex(0);
|
||||
} else if (activeIndex > index) {
|
||||
setActiveIndex(activeIndex - 1);
|
||||
}
|
||||
await deleteCollection(item.name);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</Select.Option>
|
||||
);
|
||||
})}
|
||||
</Select>
|
||||
</div>
|
||||
}
|
||||
visible={visible}
|
||||
onCancel={() => {
|
||||
setVisible(false);
|
||||
}}
|
||||
onOk={async () => {
|
||||
try {
|
||||
form.clearErrors();
|
||||
await form.validate(`${field.address.entire}.${activeIndex}.*`);
|
||||
setVisible(false);
|
||||
await createOrUpdateCollection(field.value[activeIndex]);
|
||||
console.log(
|
||||
`${field.address.entire}.${activeIndex}.*`,
|
||||
field.value[activeIndex],
|
||||
);
|
||||
} catch (error) {}
|
||||
}}
|
||||
>
|
||||
<FormLayout layout={'vertical'}>
|
||||
<RecursionField
|
||||
name={activeIndex}
|
||||
schema={
|
||||
new Schema({
|
||||
type: 'object',
|
||||
properties: schema.properties,
|
||||
})
|
||||
}
|
||||
/>
|
||||
</FormLayout>
|
||||
</Modal>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
export const DatabaseField: any = observer((props) => {
|
||||
const field = useField<Formily.Core.Models.ArrayField>();
|
||||
console.log('DatabaseField', field.componentProps);
|
||||
console.log('DatabaseField', field.value);
|
||||
const [activeKey, setActiveKey] = useState(null);
|
||||
return (
|
||||
<div>
|
||||
@ -26,6 +186,7 @@ export const DatabaseField: any = observer((props) => {
|
||||
onChange={(key) => {
|
||||
setActiveKey(key);
|
||||
}}
|
||||
className={cls({ empty: !field.value?.length })}
|
||||
accordion
|
||||
>
|
||||
{field.value?.map((item, index) => {
|
||||
@ -35,9 +196,13 @@ export const DatabaseField: any = observer((props) => {
|
||||
<Collapse.Panel
|
||||
header={
|
||||
<>
|
||||
{(item.ui && item.ui.title) || <i style={{color: 'rgba(0, 0, 0, 0.25)'}}>未命名</i>}{' '}
|
||||
{(item.ui && item.ui.title) || (
|
||||
<i style={{ color: 'rgba(0, 0, 0, 0.25)' }}>未命名</i>
|
||||
)}{' '}
|
||||
<Tag>{schema.title}</Tag>
|
||||
<span style={{ color: 'rgba(0, 0, 0, 0.25)', fontSize: 14 }}>{item.name}</span>
|
||||
<span style={{ color: 'rgba(0, 0, 0, 0.25)', fontSize: 14 }}>
|
||||
{item.name}
|
||||
</span>
|
||||
</>
|
||||
}
|
||||
extra={[
|
||||
@ -97,13 +262,11 @@ export const DatabaseField: any = observer((props) => {
|
||||
console.log('info.key', info.key, schema);
|
||||
}}
|
||||
>
|
||||
{options.map(option => (
|
||||
{options.map((option) => (
|
||||
<Menu.ItemGroup title={option.label}>
|
||||
{
|
||||
option.children.map(item => (
|
||||
<Menu.Item key={item.name}>{item.title}</Menu.Item>
|
||||
))
|
||||
}
|
||||
{option.children.map((item) => (
|
||||
<Menu.Item key={item.name}>{item.title}</Menu.Item>
|
||||
))}
|
||||
</Menu.ItemGroup>
|
||||
))}
|
||||
</Menu>
|
||||
|
3
packages/client/src/schemas/database-field/style.less
Normal file
3
packages/client/src/schemas/database-field/style.less
Normal file
@ -0,0 +1,3 @@
|
||||
.ant-collapse.empty {
|
||||
border: 0;
|
||||
}
|
@ -21,7 +21,7 @@ import {
|
||||
import './style.less';
|
||||
import cls from 'classnames';
|
||||
|
||||
import { createSchema, useDesignable, useSchemaPath } from '../';
|
||||
import { createSchema, removeSchema, useDesignable, useSchemaPath } from '../';
|
||||
import {
|
||||
useDrag,
|
||||
useDrop,
|
||||
@ -37,6 +37,10 @@ export const GridBlockContext = createContext({
|
||||
dragRef: null,
|
||||
});
|
||||
|
||||
function isGridRowOrCol(schema: ISchema) {
|
||||
return ['Grid.Row', 'Grid.Col'].includes(schema['x-component']);
|
||||
}
|
||||
|
||||
const RowDivider = ({ name, onDrop }) => {
|
||||
const uid = useDragDropUID();
|
||||
const { isOver, dropRef } = useDrop({
|
||||
@ -111,7 +115,11 @@ export const Grid: any = observer((props) => {
|
||||
});
|
||||
await createSchema(data);
|
||||
console.log('prepend', data);
|
||||
deepRemove(path);
|
||||
const removed = deepRemove(path);
|
||||
const last = removed.pop();
|
||||
if (isGridRowOrCol(last)) {
|
||||
await removeSchema(last);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
{schema.mapProperties((property, key, index) => {
|
||||
@ -143,8 +151,12 @@ export const Grid: any = observer((props) => {
|
||||
[...gridPath, key],
|
||||
);
|
||||
await createSchema(data);
|
||||
console.log('insertAfter', data);
|
||||
deepRemove(path);
|
||||
const removed = deepRemove(path);
|
||||
const last = removed.pop();
|
||||
if (isGridRowOrCol(last)) {
|
||||
await removeSchema(last);
|
||||
}
|
||||
console.log('insertAfter', data, removed);
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
@ -185,7 +197,11 @@ Grid.Row = observer((props) => {
|
||||
});
|
||||
await createSchema(data);
|
||||
const path = [...e.dragItem.path];
|
||||
deepRemove(path);
|
||||
const removed = deepRemove(path);
|
||||
const last = removed.pop();
|
||||
if (isGridRowOrCol(last)) {
|
||||
await removeSchema(last);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
{schema.mapProperties((property, key, index) => {
|
||||
@ -207,10 +223,14 @@ Grid.Row = observer((props) => {
|
||||
},
|
||||
[...rowPath, key],
|
||||
);
|
||||
console.log('ColDivider', data)
|
||||
console.log('ColDivider', data);
|
||||
await createSchema(data);
|
||||
const path = [...e.dragItem.path];
|
||||
deepRemove(path);
|
||||
const removed = deepRemove(path);
|
||||
const last = removed.pop();
|
||||
if (isGridRowOrCol(last)) {
|
||||
await removeSchema(last);
|
||||
}
|
||||
}}
|
||||
onDragEnd={(e) => {
|
||||
designableSchema.mapProperties((s, key, index) => {
|
||||
|
@ -18,6 +18,23 @@ export const request = extend({
|
||||
timeout: 1000,
|
||||
});
|
||||
|
||||
export async function createOrUpdateCollection(data: any) {
|
||||
return await request('collections:createOrUpdate', {
|
||||
method: 'post',
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
export async function deleteCollection(name) {
|
||||
await request('collections:destroy', {
|
||||
method: 'post',
|
||||
params: {
|
||||
filter: {
|
||||
name,
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export async function createSchema(schema: ISchema) {
|
||||
if (!schema['key']) {
|
||||
|
24
packages/plugin-collections/src/actions/index.ts
Normal file
24
packages/plugin-collections/src/actions/index.ts
Normal file
@ -0,0 +1,24 @@
|
||||
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 createOrUpdate = async (ctx: actions.Context, next: actions.Next) => {
|
||||
const { values } = ctx.action.params;
|
||||
const Collection = ctx.db.getModel('collections');
|
||||
let collection;
|
||||
if (values.name) {
|
||||
collection = await Collection.findByPk(values.name);
|
||||
}
|
||||
try {
|
||||
if (!collection) {
|
||||
collection = await Collection.create(values);
|
||||
} else {
|
||||
await collection.update(values);
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('error.errors', error.errors)
|
||||
}
|
||||
|
||||
ctx.body = collection;
|
||||
}
|
@ -2,6 +2,7 @@ import path from 'path';
|
||||
import { Application } from '@nocobase/server';
|
||||
import { registerModels, Table } from '@nocobase/database';
|
||||
import * as models from './models';
|
||||
import { createOrUpdate } from './actions';
|
||||
|
||||
export default async function (this: Application, options = {}) {
|
||||
const database = this.database;
|
||||
@ -16,4 +17,6 @@ export default async function (this: Application, options = {}) {
|
||||
model.set('name', model.get('key'));
|
||||
}
|
||||
});
|
||||
|
||||
this.resourcer.registerActionHandler('collections:createOrUpdate', createOrUpdate);
|
||||
}
|
||||
|
@ -18,14 +18,19 @@ export const create = async (ctx: actions.Context, next: actions.Next) => {
|
||||
payload: 'replace',
|
||||
},
|
||||
);
|
||||
await actions.common.create(ctx, async () => {});
|
||||
await actions.common.create(ctx, async () => { });
|
||||
const sticky = values['__prepend__'];
|
||||
const targetKey = values['__insertAfter__'] || values['__insertBefore__'];
|
||||
if (targetKey) {
|
||||
if (sticky || targetKey) {
|
||||
console.log({
|
||||
associatedKey: values.parentKey,
|
||||
resourceKey: ctx.body.key,
|
||||
values: {
|
||||
values: sticky ? {
|
||||
field: 'sort',
|
||||
sticky: true,
|
||||
} : {
|
||||
field: 'sort',
|
||||
insertAfter: !!values['__insertAfter__'],
|
||||
target: {
|
||||
key: targetKey,
|
||||
},
|
||||
@ -35,7 +40,11 @@ export const create = async (ctx: actions.Context, next: actions.Next) => {
|
||||
{
|
||||
associatedKey: values.parentKey,
|
||||
resourceKey: ctx.body.key,
|
||||
values: {
|
||||
values: sticky ? {
|
||||
field: 'sort',
|
||||
sticky: true,
|
||||
target: {},
|
||||
} : {
|
||||
field: 'sort',
|
||||
insertAfter: !!values['__insertAfter__'],
|
||||
target: {
|
||||
@ -47,8 +56,8 @@ export const create = async (ctx: actions.Context, next: actions.Next) => {
|
||||
payload: 'replace',
|
||||
},
|
||||
);
|
||||
await middlewares.associated(ctx, async () => {});
|
||||
await sort(ctx, async () => {});
|
||||
await middlewares.associated(ctx, async () => { });
|
||||
await sort(ctx, async () => { });
|
||||
}
|
||||
await next();
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user