From efb03204270ad9bd8957d040ffe38cb446328a86 Mon Sep 17 00:00:00 2001 From: chenos Date: Tue, 6 Apr 2021 12:52:59 +0800 Subject: [PATCH] refactor(app): clean up the client code --- packages/app/src/api-client.ts | 3 +- packages/app/src/app.ts | 1 + .../app/src/components/actions/Create.tsx | 49 -- .../app/src/components/actions/Destroy.tsx | 28 - .../app/src/components/actions/Filter.tsx | 75 -- .../app/src/components/actions/Update.tsx | 46 -- packages/app/src/components/actions/index.tsx | 392 ++++++++- .../app/src/components/actions/style.less | 2 +- .../AdminLoader/Drawer => drawer}/index.tsx | 2 - .../array-cards/index.tsx | 0 .../array-cards/style.ts | 0 .../array-table/index.tsx | 0 .../array-table/style.ts | 0 .../automations/index.tsx | 0 .../automations/style.less | 0 .../cascader/index.tsx | 0 .../{form.fields => fields}/cascader/style.ts | 0 .../checkbox/index.tsx | 0 .../{form.fields => fields}/checkbox/style.ts | 0 .../circle-button/index.tsx | 0 .../circle-button/style.ts | 0 .../color-select/index.tsx | 0 .../date-picker/index.tsx | 0 .../date-picker/style.ts | 0 .../drawer-select/index.tsx | 5 +- .../{form.fields => fields}/filter/index.tsx | 0 .../{form.fields => fields}/filter/style.less | 0 .../filter/useDynamicList.ts | 0 .../form-block/index.tsx | 0 .../form-block/style.ts | 0 .../form-card/index.tsx | 0 .../form-card/style.ts | 0 .../form-description/index.tsx | 0 .../form-grid-col/index.tsx | 0 .../form-grid-col/style.ts | 0 .../form-grid-row/index.tsx | 0 .../form-grid-row/style.ts | 0 .../form-item-grid/index.tsx | 0 .../form-item-grid/style.ts | 0 .../form-layout/index.tsx | 0 .../form-layout/style.ts | 0 .../form-mega-layout/index.tsx | 0 .../form-mega-layout/style.ts | 0 .../form-slot/index.ts | 0 .../form-slot/style.ts | 0 .../form-step/index.tsx | 0 .../form-step/style.ts | 0 .../form-tab/index.tsx | 0 .../{form.fields => fields}/form-tab/style.ts | 0 .../form-text-box/index.tsx | 0 .../form-text-box/style.ts | 0 .../{form.fields => fields}/icons/index.tsx | 0 .../{form.fields => fields}/index.tsx | 0 .../{form.fields => fields}/input/index.tsx | 0 .../{form.fields => fields}/input/style.ts | 0 .../markdown/index.tsx | 0 .../number-picker/index.tsx | 0 .../number-picker/style.ts | 0 .../password/index.tsx | 0 .../{form.fields => fields}/password/style.ts | 0 .../permissions/index.tsx | 0 .../{form.fields => fields}/radio/index.tsx | 0 .../{form.fields => fields}/radio/style.ts | 0 .../{form.fields => fields}/range/index.tsx | 0 .../{form.fields => fields}/range/style.ts | 0 .../{form.fields => fields}/rating/index.tsx | 0 .../{form.fields => fields}/rating/style.ts | 0 .../{form.fields => fields}/registry.ts | 2 - .../remote-select/index.tsx | 2 +- .../{form.fields => fields}/select/index.tsx | 0 .../{form.fields => fields}/select/style.ts | 0 .../{form.fields => fields}/shared.tsx | 0 .../sub-table/Table.tsx | 12 +- .../sub-table/index.tsx | 1 - .../{form.fields => fields}/switch/index.tsx | 0 .../{form.fields => fields}/switch/style.ts | 0 .../text-button/index.tsx | 0 .../text-button/style.ts | 0 .../time-picker/index.tsx | 0 .../time-picker/style.ts | 0 .../transfer/index.tsx | 0 .../{form.fields => fields}/transfer/style.ts | 0 .../{form.fields => fields}/types.ts | 0 .../{form.fields => fields}/upload/index.tsx | 0 .../{form.fields => fields}/upload/style.ts | 0 .../{form.fields => fields}/values/index.tsx | 0 .../{form.fields => fields}/values/style.less | 0 .../values/useDynamicList.ts | 0 .../{form.fields => fields}/wysiwyg/index.tsx | 0 .../form.fields/draggable-table/index.tsx | 109 --- .../components/form.fields/sub-table/Form.tsx | 163 ---- packages/app/src/components/menu/index.tsx | 124 ++- .../pages/AdminLoader/Actions/index.tsx | 378 --------- .../AdminLoader/SideMenuLayout/index.tsx | 100 --- .../AdminLoader/SideMenuLayout/style.less | 21 - .../pages/AdminLoader/TopMenuLayout/index.tsx | 97 --- .../AdminLoader/TopMenuLayout/logo-blue.svg | 1 - .../AdminLoader/TopMenuLayout/logo-white.svg | 7 - .../pages/AdminLoader/TopMenuLayout/logo.svg | 1 - .../AdminLoader/TopMenuLayout/style.less | 37 - .../pages/AdminLoader/View/Calendar/index.tsx | 272 ------ .../AdminLoader/View/Calendar/style.less | 771 ------------------ .../pages/AdminLoader/View/Table.tsx | 586 ------------- .../pages/AdminLoader/View/Wysiwyg.tsx | 32 - .../pages/AdminLoader/View/index.tsx | 91 --- .../pages/AdminLoader/View/style.less | 79 -- .../components/pages/AdminLoader/index.tsx | 8 +- .../pages/AdminLoader/menu/index.tsx | 108 --- .../pages/AdminLoader/menu/style.less | 7 - .../components/pages/AvatarDropdown/index.tsx | 3 +- .../CollectionLoader/Breadcrumb/index.tsx | 13 - .../CollectionLoader/Breadcrumb/style.less | 28 - .../CollectionLoader/CollectionIndex.tsx | 49 -- .../CollectionLoader/CollectionSingle.tsx | 102 --- .../CollectionLoader/CollectionTabPane.tsx | 46 -- .../pages/CollectionLoader/index.tsx | 68 -- .../pages/CollectionLoader/style.less | 49 -- .../pages/CollectionLoader/utils.ts | 43 - packages/app/src/components/pages/Page.tsx | 19 - .../pages/{AdminLoader => }/Page/index.tsx | 4 +- .../pages/{AdminLoader => }/Page/style.less | 0 .../app/src/components/pages/PageLoader.tsx | 5 +- .../components/pages/SideMenuLayout/index.tsx | 22 +- .../src/components/pages/TemplateLoader.tsx | 8 +- .../components/pages/TopMenuLayout/index.tsx | 24 +- .../components/pages/TopMenuLayout/style.less | 20 +- packages/app/src/components/pages/index.tsx | 4 - .../src => app/src/components}/spin/index.tsx | 0 .../View => views}/Association.tsx | 9 +- .../src/components/views/Calendar/index.tsx | 227 +++--- .../src/components/views/Calendar/style.less | 26 +- .../View => views}/Descriptions.tsx | 8 +- packages/app/src/components/views/Details.tsx | 145 ---- .../app/src/components/views/Field/index.tsx | 31 +- .../AdminLoader/View => views}/FilterForm.tsx | 2 +- .../AdminLoader/View => views}/Form.tsx | 6 +- .../src/components/views/Form/DrawerForm.tsx | 218 ----- .../src/components/views/Form/FilterForm.tsx | 49 -- .../app/src/components/views/Form/Form.tsx | 62 -- .../app/src/components/views/Form/index.tsx | 22 - .../app/src/components/views/Form/style.less | 22 - .../View => views}/Kanban/index.tsx | 9 +- .../View => views}/Kanban/style.less | 0 .../src/components/views/{Form => }/Login.tsx | 1 + .../views/{Form => }/LostPassword.tsx | 0 .../components/views/{Form => }/Register.tsx | 0 .../views/{Form => }/ResetPassword.tsx | 0 .../app/src/components/views/SimpleTable.tsx | 212 ----- .../components/views/SortableTable/index.tsx | 149 ---- .../components/views/SortableTable/style.less | 14 - .../AdminLoader/View => views}/SubTable.tsx | 13 +- packages/app/src/components/views/Table.tsx | 666 +++++++++++---- packages/app/src/components/views/Wysiwyg.tsx | 11 + .../src/components/views/fields2columns.tsx | 71 ++ packages/app/src/components/views/index.tsx | 135 +-- .../components/views/{Form => }/scopes.tsx | 2 +- packages/app/src/components/views/style.less | 117 +++ packages/app/src/pages/collection.tsx | 5 - packages/app/src/pages/default.tsx | 5 - packages/app/src/pages/index.less | 6 - packages/app/src/pages/index.tsx | 3 +- packages/app/src/pages/login.tsx | 7 +- packages/app/src/pages/lostpassword.tsx | 5 +- packages/app/src/pages/page1.tsx | 38 - packages/app/src/pages/page2.tsx | 12 - packages/app/src/pages/page3.tsx | 12 - packages/app/src/pages/page4.tsx | 12 - packages/app/src/pages/register.tsx | 5 +- packages/app/src/pages/resetpassword.tsx | 5 +- packages/client/package.json | 12 +- packages/client/src/details/index.tsx | 7 - packages/client/src/form/index.tsx | 7 - packages/client/src/index.ts | 16 - packages/client/src/table/index.tsx | 7 - 174 files changed, 1459 insertions(+), 5051 deletions(-) delete mode 100644 packages/app/src/components/actions/Create.tsx delete mode 100644 packages/app/src/components/actions/Destroy.tsx delete mode 100644 packages/app/src/components/actions/Filter.tsx delete mode 100644 packages/app/src/components/actions/Update.tsx rename packages/app/src/components/{pages/AdminLoader/Drawer => drawer}/index.tsx (98%) rename packages/app/src/components/{form.fields => fields}/array-cards/index.tsx (100%) rename packages/app/src/components/{form.fields => fields}/array-cards/style.ts (100%) rename packages/app/src/components/{form.fields => fields}/array-table/index.tsx (100%) rename packages/app/src/components/{form.fields => fields}/array-table/style.ts (100%) rename packages/app/src/components/{form.fields => fields}/automations/index.tsx (100%) rename packages/app/src/components/{form.fields => fields}/automations/style.less (100%) rename packages/app/src/components/{form.fields => fields}/cascader/index.tsx (100%) rename packages/app/src/components/{form.fields => fields}/cascader/style.ts (100%) rename packages/app/src/components/{form.fields => fields}/checkbox/index.tsx (100%) rename packages/app/src/components/{form.fields => fields}/checkbox/style.ts (100%) rename packages/app/src/components/{form.fields => fields}/circle-button/index.tsx (100%) rename packages/app/src/components/{form.fields => fields}/circle-button/style.ts (100%) rename packages/app/src/components/{form.fields => fields}/color-select/index.tsx (100%) rename packages/app/src/components/{form.fields => fields}/date-picker/index.tsx (100%) rename packages/app/src/components/{form.fields => fields}/date-picker/style.ts (100%) rename packages/app/src/components/{form.fields => fields}/drawer-select/index.tsx (97%) rename packages/app/src/components/{form.fields => fields}/filter/index.tsx (100%) rename packages/app/src/components/{form.fields => fields}/filter/style.less (100%) rename packages/app/src/components/{form.fields => fields}/filter/useDynamicList.ts (100%) rename packages/app/src/components/{form.fields => fields}/form-block/index.tsx (100%) rename packages/app/src/components/{form.fields => fields}/form-block/style.ts (100%) rename packages/app/src/components/{form.fields => fields}/form-card/index.tsx (100%) rename packages/app/src/components/{form.fields => fields}/form-card/style.ts (100%) rename packages/app/src/components/{form.fields => fields}/form-description/index.tsx (100%) rename packages/app/src/components/{form.fields => fields}/form-grid-col/index.tsx (100%) rename packages/app/src/components/{form.fields => fields}/form-grid-col/style.ts (100%) rename packages/app/src/components/{form.fields => fields}/form-grid-row/index.tsx (100%) rename packages/app/src/components/{form.fields => fields}/form-grid-row/style.ts (100%) rename packages/app/src/components/{form.fields => fields}/form-item-grid/index.tsx (100%) rename packages/app/src/components/{form.fields => fields}/form-item-grid/style.ts (100%) rename packages/app/src/components/{form.fields => fields}/form-layout/index.tsx (100%) rename packages/app/src/components/{form.fields => fields}/form-layout/style.ts (100%) rename packages/app/src/components/{form.fields => fields}/form-mega-layout/index.tsx (100%) rename packages/app/src/components/{form.fields => fields}/form-mega-layout/style.ts (100%) rename packages/app/src/components/{form.fields => fields}/form-slot/index.ts (100%) rename packages/app/src/components/{form.fields => fields}/form-slot/style.ts (100%) rename packages/app/src/components/{form.fields => fields}/form-step/index.tsx (100%) rename packages/app/src/components/{form.fields => fields}/form-step/style.ts (100%) rename packages/app/src/components/{form.fields => fields}/form-tab/index.tsx (100%) rename packages/app/src/components/{form.fields => fields}/form-tab/style.ts (100%) rename packages/app/src/components/{form.fields => fields}/form-text-box/index.tsx (100%) rename packages/app/src/components/{form.fields => fields}/form-text-box/style.ts (100%) rename packages/app/src/components/{form.fields => fields}/icons/index.tsx (100%) rename packages/app/src/components/{form.fields => fields}/index.tsx (100%) rename packages/app/src/components/{form.fields => fields}/input/index.tsx (100%) rename packages/app/src/components/{form.fields => fields}/input/style.ts (100%) rename packages/app/src/components/{form.fields => fields}/markdown/index.tsx (100%) rename packages/app/src/components/{form.fields => fields}/number-picker/index.tsx (100%) rename packages/app/src/components/{form.fields => fields}/number-picker/style.ts (100%) rename packages/app/src/components/{form.fields => fields}/password/index.tsx (100%) rename packages/app/src/components/{form.fields => fields}/password/style.ts (100%) rename packages/app/src/components/{form.fields => fields}/permissions/index.tsx (100%) rename packages/app/src/components/{form.fields => fields}/radio/index.tsx (100%) rename packages/app/src/components/{form.fields => fields}/radio/style.ts (100%) rename packages/app/src/components/{form.fields => fields}/range/index.tsx (100%) rename packages/app/src/components/{form.fields => fields}/range/style.ts (100%) rename packages/app/src/components/{form.fields => fields}/rating/index.tsx (100%) rename packages/app/src/components/{form.fields => fields}/rating/style.ts (100%) rename packages/app/src/components/{form.fields => fields}/registry.ts (96%) rename packages/app/src/components/{form.fields => fields}/remote-select/index.tsx (98%) rename packages/app/src/components/{form.fields => fields}/select/index.tsx (100%) rename packages/app/src/components/{form.fields => fields}/select/style.ts (100%) rename packages/app/src/components/{form.fields => fields}/shared.tsx (100%) rename packages/app/src/components/{form.fields => fields}/sub-table/Table.tsx (65%) rename packages/app/src/components/{form.fields => fields}/sub-table/index.tsx (90%) rename packages/app/src/components/{form.fields => fields}/switch/index.tsx (100%) rename packages/app/src/components/{form.fields => fields}/switch/style.ts (100%) rename packages/app/src/components/{form.fields => fields}/text-button/index.tsx (100%) rename packages/app/src/components/{form.fields => fields}/text-button/style.ts (100%) rename packages/app/src/components/{form.fields => fields}/time-picker/index.tsx (100%) rename packages/app/src/components/{form.fields => fields}/time-picker/style.ts (100%) rename packages/app/src/components/{form.fields => fields}/transfer/index.tsx (100%) rename packages/app/src/components/{form.fields => fields}/transfer/style.ts (100%) rename packages/app/src/components/{form.fields => fields}/types.ts (100%) rename packages/app/src/components/{form.fields => fields}/upload/index.tsx (100%) rename packages/app/src/components/{form.fields => fields}/upload/style.ts (100%) rename packages/app/src/components/{form.fields => fields}/values/index.tsx (100%) rename packages/app/src/components/{form.fields => fields}/values/style.less (100%) rename packages/app/src/components/{form.fields => fields}/values/useDynamicList.ts (100%) rename packages/app/src/components/{form.fields => fields}/wysiwyg/index.tsx (100%) delete mode 100644 packages/app/src/components/form.fields/draggable-table/index.tsx delete mode 100644 packages/app/src/components/form.fields/sub-table/Form.tsx delete mode 100644 packages/app/src/components/pages/AdminLoader/Actions/index.tsx delete mode 100644 packages/app/src/components/pages/AdminLoader/SideMenuLayout/index.tsx delete mode 100644 packages/app/src/components/pages/AdminLoader/SideMenuLayout/style.less delete mode 100644 packages/app/src/components/pages/AdminLoader/TopMenuLayout/index.tsx delete mode 100644 packages/app/src/components/pages/AdminLoader/TopMenuLayout/logo-blue.svg delete mode 100644 packages/app/src/components/pages/AdminLoader/TopMenuLayout/logo-white.svg delete mode 100644 packages/app/src/components/pages/AdminLoader/TopMenuLayout/logo.svg delete mode 100644 packages/app/src/components/pages/AdminLoader/TopMenuLayout/style.less delete mode 100644 packages/app/src/components/pages/AdminLoader/View/Calendar/index.tsx delete mode 100644 packages/app/src/components/pages/AdminLoader/View/Calendar/style.less delete mode 100644 packages/app/src/components/pages/AdminLoader/View/Table.tsx delete mode 100644 packages/app/src/components/pages/AdminLoader/View/Wysiwyg.tsx delete mode 100644 packages/app/src/components/pages/AdminLoader/View/index.tsx delete mode 100644 packages/app/src/components/pages/AdminLoader/View/style.less delete mode 100644 packages/app/src/components/pages/AdminLoader/menu/index.tsx delete mode 100644 packages/app/src/components/pages/AdminLoader/menu/style.less delete mode 100644 packages/app/src/components/pages/CollectionLoader/Breadcrumb/index.tsx delete mode 100644 packages/app/src/components/pages/CollectionLoader/Breadcrumb/style.less delete mode 100644 packages/app/src/components/pages/CollectionLoader/CollectionIndex.tsx delete mode 100644 packages/app/src/components/pages/CollectionLoader/CollectionSingle.tsx delete mode 100644 packages/app/src/components/pages/CollectionLoader/CollectionTabPane.tsx delete mode 100644 packages/app/src/components/pages/CollectionLoader/index.tsx delete mode 100644 packages/app/src/components/pages/CollectionLoader/style.less delete mode 100644 packages/app/src/components/pages/CollectionLoader/utils.ts delete mode 100644 packages/app/src/components/pages/Page.tsx rename packages/app/src/components/pages/{AdminLoader => }/Page/index.tsx (97%) rename packages/app/src/components/pages/{AdminLoader => }/Page/style.less (100%) rename packages/{client/src => app/src/components}/spin/index.tsx (100%) rename packages/app/src/components/{pages/AdminLoader/View => views}/Association.tsx (76%) rename packages/app/src/components/{pages/AdminLoader/View => views}/Descriptions.tsx (93%) delete mode 100644 packages/app/src/components/views/Details.tsx rename packages/app/src/components/{pages/AdminLoader/View => views}/FilterForm.tsx (96%) rename packages/app/src/components/{pages/AdminLoader/View => views}/Form.tsx (98%) delete mode 100644 packages/app/src/components/views/Form/DrawerForm.tsx delete mode 100644 packages/app/src/components/views/Form/FilterForm.tsx delete mode 100644 packages/app/src/components/views/Form/Form.tsx delete mode 100644 packages/app/src/components/views/Form/index.tsx delete mode 100644 packages/app/src/components/views/Form/style.less rename packages/app/src/components/{pages/AdminLoader/View => views}/Kanban/index.tsx (97%) rename packages/app/src/components/{pages/AdminLoader/View => views}/Kanban/style.less (100%) rename packages/app/src/components/views/{Form => }/Login.tsx (99%) rename packages/app/src/components/views/{Form => }/LostPassword.tsx (100%) rename packages/app/src/components/views/{Form => }/Register.tsx (100%) rename packages/app/src/components/views/{Form => }/ResetPassword.tsx (100%) delete mode 100644 packages/app/src/components/views/SimpleTable.tsx delete mode 100644 packages/app/src/components/views/SortableTable/index.tsx delete mode 100644 packages/app/src/components/views/SortableTable/style.less rename packages/app/src/components/{pages/AdminLoader/View => views}/SubTable.tsx (96%) create mode 100644 packages/app/src/components/views/Wysiwyg.tsx create mode 100644 packages/app/src/components/views/fields2columns.tsx rename packages/app/src/components/views/{Form => }/scopes.tsx (95%) delete mode 100644 packages/app/src/pages/collection.tsx delete mode 100644 packages/app/src/pages/default.tsx delete mode 100755 packages/app/src/pages/index.less delete mode 100644 packages/app/src/pages/page1.tsx delete mode 100644 packages/app/src/pages/page2.tsx delete mode 100644 packages/app/src/pages/page3.tsx delete mode 100644 packages/app/src/pages/page4.tsx delete mode 100644 packages/client/src/details/index.tsx delete mode 100644 packages/client/src/form/index.tsx delete mode 100644 packages/client/src/table/index.tsx diff --git a/packages/app/src/api-client.ts b/packages/app/src/api-client.ts index 5ef1010cd..f8e6bc9a3 100644 --- a/packages/app/src/api-client.ts +++ b/packages/app/src/api-client.ts @@ -1,5 +1,3 @@ -import { values } from 'lodash'; -import { stringify } from 'querystring'; import { request } from 'umi'; interface ActionParams { @@ -24,6 +22,7 @@ interface Resource { [name: string]: (params?: ActionParams) => Promise; } +// TODO 待改进,提供一个封装度更完整的 SDK,request 可以自由替换 class ApiClient { resource(name: string): Resource { const proxy: any = new Proxy( diff --git a/packages/app/src/app.ts b/packages/app/src/app.ts index 13a458b49..1ddd3c01a 100644 --- a/packages/app/src/app.ts +++ b/packages/app/src/app.ts @@ -32,6 +32,7 @@ export const request: RequestConfig = { ], }; +// TODO:目前这块是写在代码里的,待改进 const pathnames = ['/login', '/register', '/lostpassword', '/resetpassword']; export async function getInitialState() { diff --git a/packages/app/src/components/actions/Create.tsx b/packages/app/src/components/actions/Create.tsx deleted file mode 100644 index 4e077c85f..000000000 --- a/packages/app/src/components/actions/Create.tsx +++ /dev/null @@ -1,49 +0,0 @@ -import React, { useRef } from 'react'; -import { Button } from 'antd'; -import ViewFactory from '@/components/views'; -import { PlusOutlined } from '@ant-design/icons'; - -export function Create(props) { - console.log(props); - const { title, viewName, collection_name } = props.schema; - const { activeTab = {}, item = {}, associatedName, associatedKey } = props; - const { associationField } = activeTab; - - const params = {}; - - if (associationField && associationField.target) { - params['resourceName'] = associationField.name; - params['resourceTarget'] = associationField.target; - params['associatedName'] = associatedName; - params['associatedKey'] = associatedKey; - } else { - params['resourceName'] = props.resourceName; - params['resourceTarget'] = collection_name; - params['resourceKey'] = item.itemId; - } - - console.log(params); - - const drawerRef = useRef(); - return ( - <> - - - - ); -} - -export default Create; diff --git a/packages/app/src/components/actions/Destroy.tsx b/packages/app/src/components/actions/Destroy.tsx deleted file mode 100644 index 1d67520be..000000000 --- a/packages/app/src/components/actions/Destroy.tsx +++ /dev/null @@ -1,28 +0,0 @@ -import React, { useRef } from 'react'; -import { Button, Popconfirm } from 'antd'; -import ViewFactory from '@/components/views'; -import { DeleteOutlined } from '@ant-design/icons'; - -export function Destroy(props) { - console.log(props); - const { onTrigger } = props; - const { title, viewId, isBulk = true } = props.schema; - const drawerRef = useRef(); - return ( - <> - { - console.log('destroy', onTrigger); - onTrigger && onTrigger(); - }} - > - - - - ); -} - -export default Destroy; diff --git a/packages/app/src/components/actions/Filter.tsx b/packages/app/src/components/actions/Filter.tsx deleted file mode 100644 index 1abbc5ac0..000000000 --- a/packages/app/src/components/actions/Filter.tsx +++ /dev/null @@ -1,75 +0,0 @@ -import React, { useRef, useState } from 'react'; -import { Button, Popover } from 'antd'; -import ViewFactory from '@/components/views'; -import { FilterOutlined } from '@ant-design/icons'; - -export function Filter(props) { - console.log(props); - const drawerRef = useRef(); - const [visible, setVisible] = useState(false); - const { title, viewName, collection_name } = props.schema; - const { - filterCount, - activeTab = {}, - item = {}, - associatedName, - associatedKey, - } = props; - const { associationField } = activeTab; - - const params = {}; - - if (associationField && associationField.target) { - params['resourceName'] = associationField.target; - params['resourceTarget'] = associationField.target; - params['associatedName'] = associatedName; - params['associatedKey'] = associatedKey; - } else { - params['resourceName'] = collection_name; - params['resourceKey'] = item.itemId; - } - - return ( - <> - { - setVisible(visible); - }} - className={'filters-popover'} - style={{}} - overlayStyle={{ - minWidth: 500, - }} - content={ - <> -
setVisible(false)} - >
- - - } - > - -
- - ); -} - -export default Filter; diff --git a/packages/app/src/components/actions/Update.tsx b/packages/app/src/components/actions/Update.tsx deleted file mode 100644 index 710fca986..000000000 --- a/packages/app/src/components/actions/Update.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import React, { useRef } from 'react'; -import { Button } from 'antd'; -import ViewFactory from '@/components/views'; -import { EditOutlined } from '@ant-design/icons'; - -export function Update(props) { - const { title, viewName, resourceName, collection_name } = props.schema; - const { resourceKey, activeTab = {}, item = {} } = props; - const { associationField } = activeTab; - - const params = {}; - - if (associationField && associationField.target) { - params['resourceName'] = associationField.target; - params['resourceTarget'] = associationField.target; - params['associatedName'] = resourceName; - params['associatedKey'] = item.itemId; - } else { - params['resourceName'] = collection_name; - params['resourceKey'] = item.itemId || resourceKey; - } - const drawerRef = useRef(); - return ( - <> - - - - ); -} - -export default Update; diff --git a/packages/app/src/components/actions/index.tsx b/packages/app/src/components/actions/index.tsx index d42003f05..98c32ae9d 100644 --- a/packages/app/src/components/actions/index.tsx +++ b/packages/app/src/components/actions/index.tsx @@ -1,22 +1,363 @@ -import React from 'react'; -import Create from './Create'; -import Update from './Update'; -import Destroy from './Destroy'; -import Filter from './Filter'; -// import { Space } from 'antd'; +import React, { useState } from 'react'; +import { Space, Button, Popconfirm, Popover } from 'antd'; +import { + FilterOutlined, + PlusOutlined, + SelectOutlined, + DeleteOutlined, + PrinterOutlined, + ExportOutlined, +} from '@ant-design/icons'; +import Drawer from '@/components/drawer'; +import View from '@/components/views'; +import get from 'lodash/get'; +import set from 'lodash/set'; +import ReactToPrint from 'react-to-print'; +import api from '@/api-client'; import './style.less'; const ACTIONS = new Map(); +export function Create(props) { + const { size, onFinish, schema = {}, associatedKey, ...restProps } = props; + const { title, pageTitle, viewName, transform, componentProps = {} } = schema; + return ( + <> + + + ); +} + +export function Update(props) { + const { onFinish, data, schema = {}, associatedKey, ...restProps } = props; + const { title, viewName } = schema; + return ( + <> + + + ); +} + +export function Add(props) { + const { size, onFinish, schema = {}, associatedKey, ...restProps } = props; + console.log({ associatedKey }, 'add'); + const { filter, title, viewName, transform, componentProps = {} } = schema; + return ( + <> + + + + + + ); + }, + }); + }} + icon={} + {...componentProps} + > + {title} + + + ); +} + +export function Destroy(props) { + const { size, schema = {}, onFinish } = props; + const { title, componentProps = {} } = schema; + return ( + { + onFinish && (await onFinish()); + }} + > + + + ); +} + +export function Filter(props) { + const { schema = {}, onFinish } = props; + const { title, fields = [] } = schema; + const [visible, setVisible] = useState(false); + const [data, setData] = useState({}); + const [filterCount, setFilterCount] = useState(0); + console.log('Filter', { visible, data }); + + return ( + <> + {visible && ( +
setVisible(false)} + >
+ )} + { + setVisible(visible); + }} + className={'filters-popover'} + style={{}} + overlayStyle={{ + minWidth: 500, + }} + content={ + <> + { + if (values) { + const items = values.filter.and || values.filter.or; + setFilterCount(Array.isArray(items) ? items.length : 0); + setData(values); + onFinish && (await onFinish(values)); + } + setVisible(false); + }} + schema={{ + type: 'filterForm', + fields: [ + { + dataIndex: ['filter'], + name: 'filter', + interface: 'json', + type: 'json', + component: { + type: 'filter', + 'x-component-props': { + fields, + }, + }, + }, + ], + }} + /> + + } + > + + + + ); +} + +export function Print(props) { + const { schema = {}, contentRef } = props; + const { title, buttonProps = {} } = schema; + return ( + ( + + )} + content={() => contentRef.current} + pageStyle={` + @page { + margin: 1cm; + } + table { page-break-inside:auto } + tr { page-break-inside:avoid; page-break-after:auto } + `} + documentTitle={' '} + /> + ); +} + +export function Export(props) { + const { schema = {}, onFinish } = props; + const { title, buttonProps = {} } = schema; + return ( + + ); +} + +export function Actions(props) { + const { onTrigger = {}, actions = [], style, ...restProps } = props; + return ( + actions.length > 0 && ( +
+ {actions.map( + action => + ACTIONS.has(action.type) && ( +
+ +
+ ), + )} +
+ ) + ); +} + +export default Actions; + export function registerAction(type: string, Action: any) { ACTIONS.set(type, Action); } -registerAction('update', Update); -registerAction('create', Create); -registerAction('destroy', Destroy); -registerAction('filter', Filter); - export function getAction(type: string) { return ACTIONS.get(type); } @@ -29,25 +370,10 @@ export function Action(props) { return Component && ; } -export function Actions(props) { - const { onTrigger = {}, style, schema, actions = [], ...restProps } = props; - console.log(onTrigger); - return ( - actions.length > 0 && ( -
- {actions.map(action => ( -
- -
- ))} -
- ) - ); -} - -export default Actions; +registerAction('add', Add); +registerAction('update', Update); +registerAction('create', Create); +registerAction('destroy', Destroy); +registerAction('filter', Filter); +registerAction('print', Print); +registerAction('export', Export); diff --git a/packages/app/src/components/actions/style.less b/packages/app/src/components/actions/style.less index a38f873bd..d226bbbbf 100644 --- a/packages/app/src/components/actions/style.less +++ b/packages/app/src/components/actions/style.less @@ -12,4 +12,4 @@ left: 24px; margin-left: 0; } -} +} \ No newline at end of file diff --git a/packages/app/src/components/pages/AdminLoader/Drawer/index.tsx b/packages/app/src/components/drawer/index.tsx similarity index 98% rename from packages/app/src/components/pages/AdminLoader/Drawer/index.tsx rename to packages/app/src/components/drawer/index.tsx index 6799e49cc..31d21314f 100644 --- a/packages/app/src/components/pages/AdminLoader/Drawer/index.tsx +++ b/packages/app/src/components/drawer/index.tsx @@ -1,7 +1,5 @@ import React, { Fragment, useLayoutEffect, useRef, useState } from 'react'; import ReactDOM, { createPortal } from 'react-dom'; -import { createForm } from '@formily/core'; -// import { FormProvider } from '@formily/react' import { isNum, isStr, isBool, isFn } from '@formily/shared'; import { Modal, Drawer } from 'antd'; import { DrawerProps } from 'antd/lib/drawer'; diff --git a/packages/app/src/components/form.fields/array-cards/index.tsx b/packages/app/src/components/fields/array-cards/index.tsx similarity index 100% rename from packages/app/src/components/form.fields/array-cards/index.tsx rename to packages/app/src/components/fields/array-cards/index.tsx diff --git a/packages/app/src/components/form.fields/array-cards/style.ts b/packages/app/src/components/fields/array-cards/style.ts similarity index 100% rename from packages/app/src/components/form.fields/array-cards/style.ts rename to packages/app/src/components/fields/array-cards/style.ts diff --git a/packages/app/src/components/form.fields/array-table/index.tsx b/packages/app/src/components/fields/array-table/index.tsx similarity index 100% rename from packages/app/src/components/form.fields/array-table/index.tsx rename to packages/app/src/components/fields/array-table/index.tsx diff --git a/packages/app/src/components/form.fields/array-table/style.ts b/packages/app/src/components/fields/array-table/style.ts similarity index 100% rename from packages/app/src/components/form.fields/array-table/style.ts rename to packages/app/src/components/fields/array-table/style.ts diff --git a/packages/app/src/components/form.fields/automations/index.tsx b/packages/app/src/components/fields/automations/index.tsx similarity index 100% rename from packages/app/src/components/form.fields/automations/index.tsx rename to packages/app/src/components/fields/automations/index.tsx diff --git a/packages/app/src/components/form.fields/automations/style.less b/packages/app/src/components/fields/automations/style.less similarity index 100% rename from packages/app/src/components/form.fields/automations/style.less rename to packages/app/src/components/fields/automations/style.less diff --git a/packages/app/src/components/form.fields/cascader/index.tsx b/packages/app/src/components/fields/cascader/index.tsx similarity index 100% rename from packages/app/src/components/form.fields/cascader/index.tsx rename to packages/app/src/components/fields/cascader/index.tsx diff --git a/packages/app/src/components/form.fields/cascader/style.ts b/packages/app/src/components/fields/cascader/style.ts similarity index 100% rename from packages/app/src/components/form.fields/cascader/style.ts rename to packages/app/src/components/fields/cascader/style.ts diff --git a/packages/app/src/components/form.fields/checkbox/index.tsx b/packages/app/src/components/fields/checkbox/index.tsx similarity index 100% rename from packages/app/src/components/form.fields/checkbox/index.tsx rename to packages/app/src/components/fields/checkbox/index.tsx diff --git a/packages/app/src/components/form.fields/checkbox/style.ts b/packages/app/src/components/fields/checkbox/style.ts similarity index 100% rename from packages/app/src/components/form.fields/checkbox/style.ts rename to packages/app/src/components/fields/checkbox/style.ts diff --git a/packages/app/src/components/form.fields/circle-button/index.tsx b/packages/app/src/components/fields/circle-button/index.tsx similarity index 100% rename from packages/app/src/components/form.fields/circle-button/index.tsx rename to packages/app/src/components/fields/circle-button/index.tsx diff --git a/packages/app/src/components/form.fields/circle-button/style.ts b/packages/app/src/components/fields/circle-button/style.ts similarity index 100% rename from packages/app/src/components/form.fields/circle-button/style.ts rename to packages/app/src/components/fields/circle-button/style.ts diff --git a/packages/app/src/components/form.fields/color-select/index.tsx b/packages/app/src/components/fields/color-select/index.tsx similarity index 100% rename from packages/app/src/components/form.fields/color-select/index.tsx rename to packages/app/src/components/fields/color-select/index.tsx diff --git a/packages/app/src/components/form.fields/date-picker/index.tsx b/packages/app/src/components/fields/date-picker/index.tsx similarity index 100% rename from packages/app/src/components/form.fields/date-picker/index.tsx rename to packages/app/src/components/fields/date-picker/index.tsx diff --git a/packages/app/src/components/form.fields/date-picker/style.ts b/packages/app/src/components/fields/date-picker/style.ts similarity index 100% rename from packages/app/src/components/form.fields/date-picker/style.ts rename to packages/app/src/components/fields/date-picker/style.ts diff --git a/packages/app/src/components/form.fields/drawer-select/index.tsx b/packages/app/src/components/fields/drawer-select/index.tsx similarity index 97% rename from packages/app/src/components/form.fields/drawer-select/index.tsx rename to packages/app/src/components/fields/drawer-select/index.tsx index 8249facec..218ebe6fa 100644 --- a/packages/app/src/components/form.fields/drawer-select/index.tsx +++ b/packages/app/src/components/fields/drawer-select/index.tsx @@ -8,9 +8,8 @@ import { isStr, isArr, } from '../shared'; -import ViewFactory from '@/components/views'; -import Drawer from '@/components/pages/AdminLoader/Drawer'; -import View from '@/components/pages/AdminLoader/View'; +import Drawer from '@/components/drawer'; +import View from '@/components/views'; function transform({ value, multiple, labelField, valueField = 'id' }) { let selectedKeys = []; diff --git a/packages/app/src/components/form.fields/filter/index.tsx b/packages/app/src/components/fields/filter/index.tsx similarity index 100% rename from packages/app/src/components/form.fields/filter/index.tsx rename to packages/app/src/components/fields/filter/index.tsx diff --git a/packages/app/src/components/form.fields/filter/style.less b/packages/app/src/components/fields/filter/style.less similarity index 100% rename from packages/app/src/components/form.fields/filter/style.less rename to packages/app/src/components/fields/filter/style.less diff --git a/packages/app/src/components/form.fields/filter/useDynamicList.ts b/packages/app/src/components/fields/filter/useDynamicList.ts similarity index 100% rename from packages/app/src/components/form.fields/filter/useDynamicList.ts rename to packages/app/src/components/fields/filter/useDynamicList.ts diff --git a/packages/app/src/components/form.fields/form-block/index.tsx b/packages/app/src/components/fields/form-block/index.tsx similarity index 100% rename from packages/app/src/components/form.fields/form-block/index.tsx rename to packages/app/src/components/fields/form-block/index.tsx diff --git a/packages/app/src/components/form.fields/form-block/style.ts b/packages/app/src/components/fields/form-block/style.ts similarity index 100% rename from packages/app/src/components/form.fields/form-block/style.ts rename to packages/app/src/components/fields/form-block/style.ts diff --git a/packages/app/src/components/form.fields/form-card/index.tsx b/packages/app/src/components/fields/form-card/index.tsx similarity index 100% rename from packages/app/src/components/form.fields/form-card/index.tsx rename to packages/app/src/components/fields/form-card/index.tsx diff --git a/packages/app/src/components/form.fields/form-card/style.ts b/packages/app/src/components/fields/form-card/style.ts similarity index 100% rename from packages/app/src/components/form.fields/form-card/style.ts rename to packages/app/src/components/fields/form-card/style.ts diff --git a/packages/app/src/components/form.fields/form-description/index.tsx b/packages/app/src/components/fields/form-description/index.tsx similarity index 100% rename from packages/app/src/components/form.fields/form-description/index.tsx rename to packages/app/src/components/fields/form-description/index.tsx diff --git a/packages/app/src/components/form.fields/form-grid-col/index.tsx b/packages/app/src/components/fields/form-grid-col/index.tsx similarity index 100% rename from packages/app/src/components/form.fields/form-grid-col/index.tsx rename to packages/app/src/components/fields/form-grid-col/index.tsx diff --git a/packages/app/src/components/form.fields/form-grid-col/style.ts b/packages/app/src/components/fields/form-grid-col/style.ts similarity index 100% rename from packages/app/src/components/form.fields/form-grid-col/style.ts rename to packages/app/src/components/fields/form-grid-col/style.ts diff --git a/packages/app/src/components/form.fields/form-grid-row/index.tsx b/packages/app/src/components/fields/form-grid-row/index.tsx similarity index 100% rename from packages/app/src/components/form.fields/form-grid-row/index.tsx rename to packages/app/src/components/fields/form-grid-row/index.tsx diff --git a/packages/app/src/components/form.fields/form-grid-row/style.ts b/packages/app/src/components/fields/form-grid-row/style.ts similarity index 100% rename from packages/app/src/components/form.fields/form-grid-row/style.ts rename to packages/app/src/components/fields/form-grid-row/style.ts diff --git a/packages/app/src/components/form.fields/form-item-grid/index.tsx b/packages/app/src/components/fields/form-item-grid/index.tsx similarity index 100% rename from packages/app/src/components/form.fields/form-item-grid/index.tsx rename to packages/app/src/components/fields/form-item-grid/index.tsx diff --git a/packages/app/src/components/form.fields/form-item-grid/style.ts b/packages/app/src/components/fields/form-item-grid/style.ts similarity index 100% rename from packages/app/src/components/form.fields/form-item-grid/style.ts rename to packages/app/src/components/fields/form-item-grid/style.ts diff --git a/packages/app/src/components/form.fields/form-layout/index.tsx b/packages/app/src/components/fields/form-layout/index.tsx similarity index 100% rename from packages/app/src/components/form.fields/form-layout/index.tsx rename to packages/app/src/components/fields/form-layout/index.tsx diff --git a/packages/app/src/components/form.fields/form-layout/style.ts b/packages/app/src/components/fields/form-layout/style.ts similarity index 100% rename from packages/app/src/components/form.fields/form-layout/style.ts rename to packages/app/src/components/fields/form-layout/style.ts diff --git a/packages/app/src/components/form.fields/form-mega-layout/index.tsx b/packages/app/src/components/fields/form-mega-layout/index.tsx similarity index 100% rename from packages/app/src/components/form.fields/form-mega-layout/index.tsx rename to packages/app/src/components/fields/form-mega-layout/index.tsx diff --git a/packages/app/src/components/form.fields/form-mega-layout/style.ts b/packages/app/src/components/fields/form-mega-layout/style.ts similarity index 100% rename from packages/app/src/components/form.fields/form-mega-layout/style.ts rename to packages/app/src/components/fields/form-mega-layout/style.ts diff --git a/packages/app/src/components/form.fields/form-slot/index.ts b/packages/app/src/components/fields/form-slot/index.ts similarity index 100% rename from packages/app/src/components/form.fields/form-slot/index.ts rename to packages/app/src/components/fields/form-slot/index.ts diff --git a/packages/app/src/components/form.fields/form-slot/style.ts b/packages/app/src/components/fields/form-slot/style.ts similarity index 100% rename from packages/app/src/components/form.fields/form-slot/style.ts rename to packages/app/src/components/fields/form-slot/style.ts diff --git a/packages/app/src/components/form.fields/form-step/index.tsx b/packages/app/src/components/fields/form-step/index.tsx similarity index 100% rename from packages/app/src/components/form.fields/form-step/index.tsx rename to packages/app/src/components/fields/form-step/index.tsx diff --git a/packages/app/src/components/form.fields/form-step/style.ts b/packages/app/src/components/fields/form-step/style.ts similarity index 100% rename from packages/app/src/components/form.fields/form-step/style.ts rename to packages/app/src/components/fields/form-step/style.ts diff --git a/packages/app/src/components/form.fields/form-tab/index.tsx b/packages/app/src/components/fields/form-tab/index.tsx similarity index 100% rename from packages/app/src/components/form.fields/form-tab/index.tsx rename to packages/app/src/components/fields/form-tab/index.tsx diff --git a/packages/app/src/components/form.fields/form-tab/style.ts b/packages/app/src/components/fields/form-tab/style.ts similarity index 100% rename from packages/app/src/components/form.fields/form-tab/style.ts rename to packages/app/src/components/fields/form-tab/style.ts diff --git a/packages/app/src/components/form.fields/form-text-box/index.tsx b/packages/app/src/components/fields/form-text-box/index.tsx similarity index 100% rename from packages/app/src/components/form.fields/form-text-box/index.tsx rename to packages/app/src/components/fields/form-text-box/index.tsx diff --git a/packages/app/src/components/form.fields/form-text-box/style.ts b/packages/app/src/components/fields/form-text-box/style.ts similarity index 100% rename from packages/app/src/components/form.fields/form-text-box/style.ts rename to packages/app/src/components/fields/form-text-box/style.ts diff --git a/packages/app/src/components/form.fields/icons/index.tsx b/packages/app/src/components/fields/icons/index.tsx similarity index 100% rename from packages/app/src/components/form.fields/icons/index.tsx rename to packages/app/src/components/fields/icons/index.tsx diff --git a/packages/app/src/components/form.fields/index.tsx b/packages/app/src/components/fields/index.tsx similarity index 100% rename from packages/app/src/components/form.fields/index.tsx rename to packages/app/src/components/fields/index.tsx diff --git a/packages/app/src/components/form.fields/input/index.tsx b/packages/app/src/components/fields/input/index.tsx similarity index 100% rename from packages/app/src/components/form.fields/input/index.tsx rename to packages/app/src/components/fields/input/index.tsx diff --git a/packages/app/src/components/form.fields/input/style.ts b/packages/app/src/components/fields/input/style.ts similarity index 100% rename from packages/app/src/components/form.fields/input/style.ts rename to packages/app/src/components/fields/input/style.ts diff --git a/packages/app/src/components/form.fields/markdown/index.tsx b/packages/app/src/components/fields/markdown/index.tsx similarity index 100% rename from packages/app/src/components/form.fields/markdown/index.tsx rename to packages/app/src/components/fields/markdown/index.tsx diff --git a/packages/app/src/components/form.fields/number-picker/index.tsx b/packages/app/src/components/fields/number-picker/index.tsx similarity index 100% rename from packages/app/src/components/form.fields/number-picker/index.tsx rename to packages/app/src/components/fields/number-picker/index.tsx diff --git a/packages/app/src/components/form.fields/number-picker/style.ts b/packages/app/src/components/fields/number-picker/style.ts similarity index 100% rename from packages/app/src/components/form.fields/number-picker/style.ts rename to packages/app/src/components/fields/number-picker/style.ts diff --git a/packages/app/src/components/form.fields/password/index.tsx b/packages/app/src/components/fields/password/index.tsx similarity index 100% rename from packages/app/src/components/form.fields/password/index.tsx rename to packages/app/src/components/fields/password/index.tsx diff --git a/packages/app/src/components/form.fields/password/style.ts b/packages/app/src/components/fields/password/style.ts similarity index 100% rename from packages/app/src/components/form.fields/password/style.ts rename to packages/app/src/components/fields/password/style.ts diff --git a/packages/app/src/components/form.fields/permissions/index.tsx b/packages/app/src/components/fields/permissions/index.tsx similarity index 100% rename from packages/app/src/components/form.fields/permissions/index.tsx rename to packages/app/src/components/fields/permissions/index.tsx diff --git a/packages/app/src/components/form.fields/radio/index.tsx b/packages/app/src/components/fields/radio/index.tsx similarity index 100% rename from packages/app/src/components/form.fields/radio/index.tsx rename to packages/app/src/components/fields/radio/index.tsx diff --git a/packages/app/src/components/form.fields/radio/style.ts b/packages/app/src/components/fields/radio/style.ts similarity index 100% rename from packages/app/src/components/form.fields/radio/style.ts rename to packages/app/src/components/fields/radio/style.ts diff --git a/packages/app/src/components/form.fields/range/index.tsx b/packages/app/src/components/fields/range/index.tsx similarity index 100% rename from packages/app/src/components/form.fields/range/index.tsx rename to packages/app/src/components/fields/range/index.tsx diff --git a/packages/app/src/components/form.fields/range/style.ts b/packages/app/src/components/fields/range/style.ts similarity index 100% rename from packages/app/src/components/form.fields/range/style.ts rename to packages/app/src/components/fields/range/style.ts diff --git a/packages/app/src/components/form.fields/rating/index.tsx b/packages/app/src/components/fields/rating/index.tsx similarity index 100% rename from packages/app/src/components/form.fields/rating/index.tsx rename to packages/app/src/components/fields/rating/index.tsx diff --git a/packages/app/src/components/form.fields/rating/style.ts b/packages/app/src/components/fields/rating/style.ts similarity index 100% rename from packages/app/src/components/form.fields/rating/style.ts rename to packages/app/src/components/fields/rating/style.ts diff --git a/packages/app/src/components/form.fields/registry.ts b/packages/app/src/components/fields/registry.ts similarity index 96% rename from packages/app/src/components/form.fields/registry.ts rename to packages/app/src/components/fields/registry.ts index d59a7e74e..21a4620d7 100644 --- a/packages/app/src/components/form.fields/registry.ts +++ b/packages/app/src/components/fields/registry.ts @@ -21,7 +21,6 @@ import { Cascader } from './cascader'; import { Icon } from './icons'; import { ColorSelect } from './color-select'; import { Permissions } from './permissions'; -import { DraggableTable } from './draggable-table'; import { Values } from './values'; import { Automations } from './automations'; import { Wysiwyg } from './wysiwyg'; @@ -61,7 +60,6 @@ export const setup = () => { drawerSelect: DrawerSelect, colorSelect: ColorSelect, subTable: SubTable, - draggableTable: DraggableTable, values: Values, wysiwyg: Wysiwyg, markdown: Markdown, diff --git a/packages/app/src/components/form.fields/remote-select/index.tsx b/packages/app/src/components/fields/remote-select/index.tsx similarity index 98% rename from packages/app/src/components/form.fields/remote-select/index.tsx rename to packages/app/src/components/fields/remote-select/index.tsx index b222f6346..261e6d6e5 100644 --- a/packages/app/src/components/form.fields/remote-select/index.tsx +++ b/packages/app/src/components/fields/remote-select/index.tsx @@ -11,7 +11,7 @@ import { } from '../shared'; import { useRequest } from 'umi'; import api from '@/api-client'; -import { Spin } from '@nocobase/client'; +import { Spin } from '@/components/spin'; import get from 'lodash/get'; function RemoteSelectComponent(props) { diff --git a/packages/app/src/components/form.fields/select/index.tsx b/packages/app/src/components/fields/select/index.tsx similarity index 100% rename from packages/app/src/components/form.fields/select/index.tsx rename to packages/app/src/components/fields/select/index.tsx diff --git a/packages/app/src/components/form.fields/select/style.ts b/packages/app/src/components/fields/select/style.ts similarity index 100% rename from packages/app/src/components/form.fields/select/style.ts rename to packages/app/src/components/fields/select/style.ts diff --git a/packages/app/src/components/form.fields/shared.tsx b/packages/app/src/components/fields/shared.tsx similarity index 100% rename from packages/app/src/components/form.fields/shared.tsx rename to packages/app/src/components/fields/shared.tsx diff --git a/packages/app/src/components/form.fields/sub-table/Table.tsx b/packages/app/src/components/fields/sub-table/Table.tsx similarity index 65% rename from packages/app/src/components/form.fields/sub-table/Table.tsx rename to packages/app/src/components/fields/sub-table/Table.tsx index a7ba8c004..11aee43e9 100644 --- a/packages/app/src/components/form.fields/sub-table/Table.tsx +++ b/packages/app/src/components/fields/sub-table/Table.tsx @@ -1,15 +1,5 @@ import React, { useEffect, useRef, useState } from 'react'; -import ReactDOM from 'react-dom'; -import { Table as AntdTable, Button, Space, Popconfirm } from 'antd'; -import { Actions } from '@/components/actions'; -import ViewFactory from '@/components/views'; -import { useRequest } from 'umi'; -import api from '@/api-client'; -import { components, fields2columns } from '@/components/views/SortableTable'; -import Form from './Form'; -import { Spin } from '@nocobase/client'; -import maxBy from 'lodash/maxBy'; -import View from '@/components/pages/AdminLoader/View'; +import View from '@/components/views'; export interface SimpleTableProps { schema?: any; diff --git a/packages/app/src/components/form.fields/sub-table/index.tsx b/packages/app/src/components/fields/sub-table/index.tsx similarity index 90% rename from packages/app/src/components/form.fields/sub-table/index.tsx rename to packages/app/src/components/fields/sub-table/index.tsx index 22beddfb5..a2ceb1a6f 100644 --- a/packages/app/src/components/form.fields/sub-table/index.tsx +++ b/packages/app/src/components/fields/sub-table/index.tsx @@ -9,7 +9,6 @@ import { isStr, isArr, } from '../shared'; -import ViewFactory from '@/components/views'; import Table from './Table'; export const SubTable = connect({ diff --git a/packages/app/src/components/form.fields/switch/index.tsx b/packages/app/src/components/fields/switch/index.tsx similarity index 100% rename from packages/app/src/components/form.fields/switch/index.tsx rename to packages/app/src/components/fields/switch/index.tsx diff --git a/packages/app/src/components/form.fields/switch/style.ts b/packages/app/src/components/fields/switch/style.ts similarity index 100% rename from packages/app/src/components/form.fields/switch/style.ts rename to packages/app/src/components/fields/switch/style.ts diff --git a/packages/app/src/components/form.fields/text-button/index.tsx b/packages/app/src/components/fields/text-button/index.tsx similarity index 100% rename from packages/app/src/components/form.fields/text-button/index.tsx rename to packages/app/src/components/fields/text-button/index.tsx diff --git a/packages/app/src/components/form.fields/text-button/style.ts b/packages/app/src/components/fields/text-button/style.ts similarity index 100% rename from packages/app/src/components/form.fields/text-button/style.ts rename to packages/app/src/components/fields/text-button/style.ts diff --git a/packages/app/src/components/form.fields/time-picker/index.tsx b/packages/app/src/components/fields/time-picker/index.tsx similarity index 100% rename from packages/app/src/components/form.fields/time-picker/index.tsx rename to packages/app/src/components/fields/time-picker/index.tsx diff --git a/packages/app/src/components/form.fields/time-picker/style.ts b/packages/app/src/components/fields/time-picker/style.ts similarity index 100% rename from packages/app/src/components/form.fields/time-picker/style.ts rename to packages/app/src/components/fields/time-picker/style.ts diff --git a/packages/app/src/components/form.fields/transfer/index.tsx b/packages/app/src/components/fields/transfer/index.tsx similarity index 100% rename from packages/app/src/components/form.fields/transfer/index.tsx rename to packages/app/src/components/fields/transfer/index.tsx diff --git a/packages/app/src/components/form.fields/transfer/style.ts b/packages/app/src/components/fields/transfer/style.ts similarity index 100% rename from packages/app/src/components/form.fields/transfer/style.ts rename to packages/app/src/components/fields/transfer/style.ts diff --git a/packages/app/src/components/form.fields/types.ts b/packages/app/src/components/fields/types.ts similarity index 100% rename from packages/app/src/components/form.fields/types.ts rename to packages/app/src/components/fields/types.ts diff --git a/packages/app/src/components/form.fields/upload/index.tsx b/packages/app/src/components/fields/upload/index.tsx similarity index 100% rename from packages/app/src/components/form.fields/upload/index.tsx rename to packages/app/src/components/fields/upload/index.tsx diff --git a/packages/app/src/components/form.fields/upload/style.ts b/packages/app/src/components/fields/upload/style.ts similarity index 100% rename from packages/app/src/components/form.fields/upload/style.ts rename to packages/app/src/components/fields/upload/style.ts diff --git a/packages/app/src/components/form.fields/values/index.tsx b/packages/app/src/components/fields/values/index.tsx similarity index 100% rename from packages/app/src/components/form.fields/values/index.tsx rename to packages/app/src/components/fields/values/index.tsx diff --git a/packages/app/src/components/form.fields/values/style.less b/packages/app/src/components/fields/values/style.less similarity index 100% rename from packages/app/src/components/form.fields/values/style.less rename to packages/app/src/components/fields/values/style.less diff --git a/packages/app/src/components/form.fields/values/useDynamicList.ts b/packages/app/src/components/fields/values/useDynamicList.ts similarity index 100% rename from packages/app/src/components/form.fields/values/useDynamicList.ts rename to packages/app/src/components/fields/values/useDynamicList.ts diff --git a/packages/app/src/components/form.fields/wysiwyg/index.tsx b/packages/app/src/components/fields/wysiwyg/index.tsx similarity index 100% rename from packages/app/src/components/form.fields/wysiwyg/index.tsx rename to packages/app/src/components/fields/wysiwyg/index.tsx diff --git a/packages/app/src/components/form.fields/draggable-table/index.tsx b/packages/app/src/components/form.fields/draggable-table/index.tsx deleted file mode 100644 index 09a96e4e2..000000000 --- a/packages/app/src/components/form.fields/draggable-table/index.tsx +++ /dev/null @@ -1,109 +0,0 @@ -import React, { useState } from 'react'; -import { connect } from '@formily/react-schema-renderer'; -import moment from 'moment'; -import { Select, Table } from 'antd'; -import get from 'lodash/get'; -import { - mapStyledProps, - mapTextComponent, - compose, - isStr, - isArr, -} from '../shared'; -import { useRequest } from 'umi'; -import api from '@/api-client'; -import { Spin } from '@nocobase/client'; -import { fields2columns, components } from '@/components/views/SortableTable'; - -function DraggableTableComponent(props) { - const { - mode = 'showInDetail', - value, - onChange, - disabled, - rowKey = 'id', - fields = [], - resourceName, - associatedKey, - filter, - labelField, - valueField = 'id', - objectValue, - placeholder, - } = props; - const { data = [], loading = true, mutate } = useRequest( - () => { - return api.resource(resourceName).list({ - associatedKey, - filter, - perPage: -1, - }); - }, - { - refreshDeps: [resourceName, associatedKey], - }, - ); - const [selectedRowKeys, setSelectedRowKeys] = useState([]); - const onTableChange = (selectedRowKeys: React.ReactText[]) => { - onChange(selectedRowKeys); - }; - const tableProps: any = {}; - tableProps.rowSelection = { - selectedRowKeys: Array.isArray(value) - ? value - : data.map(item => item[rowKey]), - onChange: onTableChange, - }; - const dataSource = data.filter(item => { - return get(item, ['component', mode]); - }); - // const sortIds = get(value, 'sort')||[]; - // let values = []; - // sortIds.forEach(id => { - // const item = dataSource.find(item => item[rowKey] === id); - // if (item) { - // values.push(item); - // } - // }); - // if (values.length === 0) { - // values = dataSource; - // } - return ( - <> - { - // onChange({ - // sort: values.list.map(item => item[rowKey]), - // selectedRowKeys: get(value, 'selectedRowKeys')||data.map(item => item[rowKey]), - // }); - // mutate(values.list); - // // setDataSource(values.list); - // console.log('mutate', values); - // }, - // rowKey, - // onMoved: async ({resourceKey, target}) => { - // } - // })} - /> - - ); -} - -export const DraggableTable = connect({ - getProps: mapStyledProps, - getComponent: mapTextComponent, -})(DraggableTableComponent); - -export default DraggableTable; diff --git a/packages/app/src/components/form.fields/sub-table/Form.tsx b/packages/app/src/components/form.fields/sub-table/Form.tsx deleted file mode 100644 index 621637a52..000000000 --- a/packages/app/src/components/form.fields/sub-table/Form.tsx +++ /dev/null @@ -1,163 +0,0 @@ -import React, { - useState, - useEffect, - useImperativeHandle, - forwardRef, - useRef, -} from 'react'; -import { Button, Drawer } from 'antd'; -import { Tooltip, Input, Space, Modal } from 'antd'; -import isEqual from 'lodash/isEqual'; -import { - SchemaForm, - SchemaMarkupField as Field, - createFormActions, - FormSpy, - LifeCycleTypes, - createAsyncFormActions, - Submit, - Reset, - FormButtonGroup, - registerFormFields, - FormValidator, - setValidationLanguage, -} from '@formily/antd'; -import { QuestionCircleOutlined } from '@ant-design/icons'; -import { useRequest } from 'umi'; -import api from '@/api-client'; -import { Spin } from '@nocobase/client'; -import cleanDeep from 'clean-deep'; -import scopes from '@/components/views/Form/scopes'; - -const actions = createFormActions(); - -export default forwardRef((props: any, ref) => { - console.log(props); - const { target, onFinish } = props; - const { data: schema = {}, loading } = useRequest(() => - api.resource(target).getView({ - resourceKey: 'form', - }), - ); - const [state, setState] = useState({}); - const [form, setForm] = useState({}); - const [changed, setChanged] = useState(false); - const [visible, setVisible] = useState(false); - const [data, setData] = useState({}); - const [title, setTitle] = useState('创建子字段'); - const [index, setIndex] = useState(); - useImperativeHandle(ref, () => ({ - setVisible, - setData, - setTitle, - setIndex, - })); - console.log({ onFinish }); - const { fields = {} } = schema; - if (loading) { - return ; - } - return ( - { - if (changed) { - Modal.confirm({ - title: '表单内容发生变化,确定不保存吗?', - onOk() { - setChanged(false); - setVisible(false); - }, - }); - } else { - setChanged(false); - setVisible(false); - } - }} - title={title} - footer={ -
- - - - -
- } - > - { - setChanged(true); - }} - onSubmit={async values => { - setVisible(false); - setChanged(false); - onFinish && onFinish(values, index); - }} - // actions={actions} - schema={{ - type: 'object', - properties: fields, - }} - expressionScope={scopes} - > - { - switch (action.type) { - case LifeCycleTypes.ON_FORM_SUBMIT_START: - return { - ...state, - submitting: true, - }; - case LifeCycleTypes.ON_FORM_SUBMIT_END: - return { - ...state, - submitting: false, - }; - default: - return state; - } - }} - > - {({ state, form }) => { - setState(state); - setForm(form); - return
; - }} - - - - ); -}); diff --git a/packages/app/src/components/menu/index.tsx b/packages/app/src/components/menu/index.tsx index f70c84a25..318d612e4 100644 --- a/packages/app/src/components/menu/index.tsx +++ b/packages/app/src/components/menu/index.tsx @@ -1,60 +1,108 @@ -import React from 'react'; +import React, { useEffect, useState } from 'react'; import { Layout, Menu, Breadcrumb } from 'antd'; -import { Link, useLocation } from 'umi'; +import { Link as UmiLink, useLocation } from 'umi'; import Icon from '@/components/icons'; import './style.less'; function pathcamp(path1: string, path2: string) { + return true; if (path1 === path2) { return true; } return path1.indexOf(`${path2}/`) === 0; } +function Link(props: any) { + const { to, children } = props; + if (/^http/.test(to)) { + return ( + + {children} + + ); + } + return ; +} + export default (props: any) => { - const { items = [], hideChildren, ...restProps } = props; - const location = useLocation(); - let paths = items.map(item => item.path); + const { + menuId, + currentPageName, + items = [], + hideChildren, + ...restProps + } = props; if (items.length === 0) { return null; } + const toPaths = data => { + const paths = []; + data.forEach(item => { + if (item.path && item.path === currentPageName) { + paths.push(`${item.name}`); + } + if (item.paths && item.paths.includes(currentPageName)) { + paths.push(`${item.name}`); + } + paths.push(...toPaths(item.children || [])); + }); + return paths; + }; + const keys = toPaths(items); + console.log({ menuId, currentPageName, items, keys }); + const [loading, setLoading] = useState(true); + useEffect(() => { + setLoading(true); + setTimeout(() => { + setLoading(false); + }); + }, [menuId]); + if (loading) { + return null; + } + const renderChildren = items => { + return items.map(item => { + const { children = [] } = item; + // const subItems = children.filter(child => child.showInMenu); + if (!hideChildren && children.length) { + return ( + } + title={<>{item.title}} + > + {renderChildren(children)} + + ); + } + return ( + } + key={`${item.name}`} + > + {item.title} + + ); + }); + }; return ( pathcamp(location.pathname, path)) - .concat(location.pathname)} - defaultOpenKeys={paths - .filter(path => pathcamp(location.pathname, path)) - .concat(location.pathname)} + defaultSelectedKeys={keys} + defaultOpenKeys={keys} + // selectedKeys={keys} + // openKeys={keys} + onOpenChange={openKeys => { + console.log({ openKeys }); + }} + onSelect={info => { + console.log({ info }); + }} + onDeselect={info => { + console.log({ info }); + }} {...restProps} > - {items.map(item => { - if (!item.showInMenu) { - return null; - } - const { children = [] } = item; - const subItems = children.filter(child => child.showInMenu); - if (!hideChildren && subItems.length > 1) { - return ( - } - title={<>{item.title}} - > - {subItems.map((child: any) => ( - - {child.title} - - ))} - - ); - } - return ( - } key={item.path}> - {item.title} - - ); - })} + {renderChildren(items)} ); }; diff --git a/packages/app/src/components/pages/AdminLoader/Actions/index.tsx b/packages/app/src/components/pages/AdminLoader/Actions/index.tsx deleted file mode 100644 index 2b9bd2745..000000000 --- a/packages/app/src/components/pages/AdminLoader/Actions/index.tsx +++ /dev/null @@ -1,378 +0,0 @@ -import React, { useState } from 'react'; -import { Space, Button, Popconfirm, Popover } from 'antd'; -import { - FilterOutlined, - PlusOutlined, - SelectOutlined, - DeleteOutlined, - PrinterOutlined, - ExportOutlined, -} from '@ant-design/icons'; -import Drawer from '@/components/pages/AdminLoader/Drawer'; -import View from '@/components/pages/AdminLoader/View'; -import get from 'lodash/get'; -import set from 'lodash/set'; -import ReactToPrint from 'react-to-print'; -import api from '@/api-client'; - -const ACTIONS = new Map(); - -export function Create(props) { - const { size, onFinish, schema = {}, associatedKey, ...restProps } = props; - const { title, pageTitle, viewName, transform, componentProps = {} } = schema; - return ( - <> - - - ); -} - -export function Update(props) { - const { onFinish, data, schema = {}, associatedKey, ...restProps } = props; - const { title, viewName } = schema; - return ( - <> - - - ); -} - -export function Add(props) { - const { size, onFinish, schema = {}, associatedKey, ...restProps } = props; - console.log({ associatedKey }, 'add'); - const { filter, title, viewName, transform, componentProps = {} } = schema; - return ( - <> - - - - -
- ); - }, - }); - }} - icon={} - {...componentProps} - > - {title} - - - ); -} - -export function Destroy(props) { - const { size, schema = {}, onFinish } = props; - const { title, componentProps = {} } = schema; - return ( - { - onFinish && (await onFinish()); - }} - > - - - ); -} - -export function Filter(props) { - const { schema = {}, onFinish } = props; - const { title, fields = [] } = schema; - const [visible, setVisible] = useState(false); - const [data, setData] = useState({}); - const [filterCount, setFilterCount] = useState(0); - console.log('Filter', { visible, data }); - - return ( - <> - {visible && ( -
setVisible(false)} - >
- )} - { - setVisible(visible); - }} - className={'filters-popover'} - style={{}} - overlayStyle={{ - minWidth: 500, - }} - content={ - <> - { - if (values) { - const items = values.filter.and || values.filter.or; - setFilterCount(Array.isArray(items) ? items.length : 0); - setData(values); - onFinish && (await onFinish(values)); - } - setVisible(false); - }} - schema={{ - type: 'filterForm', - fields: [ - { - dataIndex: ['filter'], - name: 'filter', - interface: 'json', - type: 'json', - component: { - type: 'filter', - 'x-component-props': { - fields, - }, - }, - }, - ], - }} - /> - - } - > - - - - ); -} - -export function Print(props) { - const { schema = {}, contentRef } = props; - const { title, buttonProps = {} } = schema; - return ( - ( - - )} - content={() => contentRef.current} - pageStyle={` - @page { - margin: 1cm; - } - table { page-break-inside:auto } - tr { page-break-inside:avoid; page-break-after:auto } - `} - documentTitle={' '} - /> - ); -} - -export function Export(props) { - const { schema = {}, onFinish } = props; - const { title, buttonProps = {} } = schema; - return ( - - ); -} - -export function Actions(props) { - const { onTrigger = {}, actions = [], style, ...restProps } = props; - return ( - actions.length > 0 && ( -
- {actions.map( - action => - ACTIONS.has(action.type) && ( -
- -
- ), - )} -
- ) - ); -} - -export default Actions; - -export function registerAction(type: string, Action: any) { - ACTIONS.set(type, Action); -} - -export function getAction(type: string) { - return ACTIONS.get(type); -} - -export function Action(props) { - const { schema = {} } = props; - // cnsole.log(schema); - const { type } = schema; - const Component = getAction(type); - return Component && ; -} - -registerAction('add', Add); -registerAction('update', Update); -registerAction('create', Create); -registerAction('destroy', Destroy); -registerAction('filter', Filter); -registerAction('print', Print); -registerAction('export', Export); diff --git a/packages/app/src/components/pages/AdminLoader/SideMenuLayout/index.tsx b/packages/app/src/components/pages/AdminLoader/SideMenuLayout/index.tsx deleted file mode 100644 index 60a03f7c9..000000000 --- a/packages/app/src/components/pages/AdminLoader/SideMenuLayout/index.tsx +++ /dev/null @@ -1,100 +0,0 @@ -import React, { useState } from 'react'; -import { Layout, Breadcrumb, Drawer } from 'antd'; -import { Link } from 'umi'; -import './style.less'; -import Menu from '../menu'; -import { MenuUnfoldOutlined, MenuFoldOutlined } from '@ant-design/icons'; -import { useLocalStorageState } from 'ahooks'; -import { useResponsive } from 'ahooks'; - -export function SideMenuLayout(props: any) { - const { currentPageName, menu = [], menuId } = props; - const [visible, setVisible] = useState(false); - // console.log(menu); - const [collapsed, setCollapsed] = useLocalStorageState( - `nocobase-menu-collapsed-${menuId}`, - false, - ); - const responsive = useResponsive(); - const isMobile = responsive.small && !responsive.middle && !responsive.large; - document.body.className = collapsed ? 'collapsed' : ''; - return ( - - {!isMobile && ( - - -
{ - setCollapsed(!collapsed); - setVisible(true); - document.body.className = collapsed ? 'collapsed' : ''; - }} - className={'menu-toggle'} - > - {React.createElement( - collapsed ? MenuUnfoldOutlined : MenuFoldOutlined, - { - style: { fontSize: 16 }, - }, - )} -
- - )} - - {props.children} - {isMobile && ( - { - setCollapsed(!collapsed); - setVisible(false); - document.body.className = collapsed ? 'collapsed' : ''; - }} - placement={'left'} - closable={false} - bodyStyle={{ padding: 0 }} - > - { - setCollapsed(false); - setVisible(false); - document.body.className = collapsed ? 'collapsed' : ''; - }} - currentPageName={currentPageName} - menuId={menuId} - items={menu} - mode={'inline'} - /> - - )} - {isMobile && ( -
{ - setCollapsed(!collapsed); - setVisible(true); - document.body.className = collapsed ? 'collapsed' : ''; - }} - className={'menu-toggle'} - > - {React.createElement( - collapsed ? MenuUnfoldOutlined : MenuFoldOutlined, - { - style: { fontSize: 16 }, - }, - )} -
- )} - - - ); -} - -export default SideMenuLayout; diff --git a/packages/app/src/components/pages/AdminLoader/SideMenuLayout/style.less b/packages/app/src/components/pages/AdminLoader/SideMenuLayout/style.less deleted file mode 100644 index 391ba1df7..000000000 --- a/packages/app/src/components/pages/AdminLoader/SideMenuLayout/style.less +++ /dev/null @@ -1,21 +0,0 @@ -.nb-sider { - position: relative; - left: 0; - z-index: 100; - box-shadow: 2px 0 8px 0 rgba(29, 35, 41, 0.05); - &.collapsed { - margin-left: -200px; - } - .ant-menu-light { - border-right-color: transparent !important; - } -} - -.menu-toggle { - position: fixed; - bottom: 12px; - left: 12px; - line-height: 1; - cursor: pointer; - z-index: 1000; -} diff --git a/packages/app/src/components/pages/AdminLoader/TopMenuLayout/index.tsx b/packages/app/src/components/pages/AdminLoader/TopMenuLayout/index.tsx deleted file mode 100644 index 94c03c481..000000000 --- a/packages/app/src/components/pages/AdminLoader/TopMenuLayout/index.tsx +++ /dev/null @@ -1,97 +0,0 @@ -import React, { useState } from 'react'; -import { Layout, Dropdown, Avatar, Drawer } from 'antd'; -import './style.less'; -import { history, Link, request, useModel } from 'umi'; -import { UserOutlined, CodeOutlined, MenuOutlined } from '@ant-design/icons'; -import AvatarDropdown from '@/components/pages/AvatarDropdown'; -import Menu from '../menu'; -import { ReactComponent as Logo } from './logo-white.svg'; -import { useResponsive, useLocalStorageState } from 'ahooks'; -import get from 'lodash/get'; - -export function TopMenuLayout(props: any) { - const { currentPageName, menu = [] } = props; - console.log({ menu }); - // const [visible, setVisible] = useState(false); - const [visible, setVisible] = useLocalStorageState( - `nocobase-nav-visible`, - false, - ); - const responsive = useResponsive(); - const isMobile = responsive.small && !responsive.middle && !responsive.large; - const { - initialState = {}, - loading, - error, - refresh, - setInitialState, - } = useModel('@@initialState'); - const logoUrl = get(initialState, 'systemSettings.logo.url'); - console.log({ logoUrl }); - return ( - - -
- {!logoUrl ? : } -
- {!isMobile && ( - - )} - {!isMobile && } - {isMobile && ( - { - setVisible(true); - }} - style={{ - fontSize: 16, - color: '#fff', - position: 'absolute', - right: 16, - top: 16, - }} - /> - )} - {isMobile && ( - { - setVisible(false); - }} - placement={'right'} - closable={false} - bodyStyle={{ background: '#001529', padding: 0 }} - > - { - setVisible(false); - }} - mode={'inline'} - hideChildren={true} - items={menu} - className={'noco-top-menu'} - style={{ float: 'left' }} - theme="dark" - /> - - - )} - - {props.children} - - ); -} - -export default TopMenuLayout; diff --git a/packages/app/src/components/pages/AdminLoader/TopMenuLayout/logo-blue.svg b/packages/app/src/components/pages/AdminLoader/TopMenuLayout/logo-blue.svg deleted file mode 100644 index 80b9f1bbb..000000000 --- a/packages/app/src/components/pages/AdminLoader/TopMenuLayout/logo-blue.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/packages/app/src/components/pages/AdminLoader/TopMenuLayout/logo-white.svg b/packages/app/src/components/pages/AdminLoader/TopMenuLayout/logo-white.svg deleted file mode 100644 index 475f38e7d..000000000 --- a/packages/app/src/components/pages/AdminLoader/TopMenuLayout/logo-white.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/packages/app/src/components/pages/AdminLoader/TopMenuLayout/logo.svg b/packages/app/src/components/pages/AdminLoader/TopMenuLayout/logo.svg deleted file mode 100644 index 1aa836ce4..000000000 --- a/packages/app/src/components/pages/AdminLoader/TopMenuLayout/logo.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/packages/app/src/components/pages/AdminLoader/TopMenuLayout/style.less b/packages/app/src/components/pages/AdminLoader/TopMenuLayout/style.less deleted file mode 100644 index 58e2850db..000000000 --- a/packages/app/src/components/pages/AdminLoader/TopMenuLayout/style.less +++ /dev/null @@ -1,37 +0,0 @@ -.logo { - // font-family: 'Michroma', sans-serif; - color: rgba(255, 255, 255, 0.8); - font-size: 18px; - letter-spacing: 2px; - font-weight: 300; - padding: 0 15px; - img { - height: 100%; - } - svg { - margin-top: 12px; - } -} - -body { - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} -.noco-top-menu.ant-menu-dark.ant-menu-horizontal > .ant-menu-item:hover, -.noco-top-menu.ant-menu.ant-menu-dark .ant-menu-item-selected, -.noco-top-menu.ant-menu-submenu-popup.ant-menu-dark .ant-menu-item-selected { - background-color: rgba(255, 255, 255, 0.1); -} - -.ant-layout-content { - overflow: auto; -} - -.ant-layout-header { - display: flex; -} - -.ant-menu-dark.ant-menu-horizontal { - margin-right: 100px; -} diff --git a/packages/app/src/components/pages/AdminLoader/View/Calendar/index.tsx b/packages/app/src/components/pages/AdminLoader/View/Calendar/index.tsx deleted file mode 100644 index 6c05fbc9f..000000000 --- a/packages/app/src/components/pages/AdminLoader/View/Calendar/index.tsx +++ /dev/null @@ -1,272 +0,0 @@ -import React, { useEffect, useRef, useState } from 'react'; -import { Table as AntdTable, Card, Pagination } from 'antd'; -import { useRequest, useHistory } from 'umi'; -import api from '@/api-client'; -import { - LoadingOutlined, - LeftOutlined, - RightOutlined, -} from '@ant-design/icons'; -import './style.less'; -import { Calendar as BigCalendar, momentLocalizer } from 'react-big-calendar'; -import * as dates from 'react-big-calendar/lib/utils/dates'; -import moment from 'moment'; -const localizer = momentLocalizer(moment); // or globalizeLocalizer -import Drawer from '@/components/pages/AdminLoader/Drawer'; -import { Details, DetailsPage } from '../Table'; -import { Actions } from '../../Actions'; - -export const icon = ; - -export interface CalendarProps { - schema?: any; - activeTab?: any; - resourceName: string; - associatedName?: string; - associatedKey?: string; - [key: string]: any; -} - -// let weekRangeFormat = ({ start, end }, culture, local) => -// local.format(start, 'MMMM DD', culture) + -// ' – ' + -// local.format(end, dates.eq(start, end, 'month') ? 'DD' : 'MMMM DD', culture) - -function toEvents(data, options: any = {}) { - const { startDateField, endDateField, labelField, idField = 'id' } = options; - if (!Array.isArray(data)) { - return []; - } - return data.map(item => ({ - id: item[idField], - title: item[labelField], - allDay: true, - start: moment( - item[startDateField || 'createdAt'] || item.created_at, - ).toDate(), - end: moment( - item[endDateField || startDateField || 'createdAt'] || item.created_at, - ).toDate(), - })); -} - -export function Calendar(props: CalendarProps) { - const { schema = {}, associatedKey, defaultFilter } = props; - - const paginated = false; - - const { - rowKey = 'id', - filter: schemaFilter, - sort, - appends, - resourceName, - labelField, - startDateField, - endDateField, - detailsOpenMode, - details = [], - actions = [], - } = schema; - - console.log({ schema }); - - const [calendarView, setCalendarView] = useState('month'); - - const history = useHistory(); - - const { data, loading, mutate, refresh, run, params } = useRequest( - (params = {}, ...args) => { - const { current, pageSize, sorter, filter, ...restParams } = params as any; - console.log('paramsparamsparamsparamsparams', params, args); - return api - .resource(resourceName) - .list({ - associatedKey, - page: paginated ? current : 1, - perPage: paginated ? pageSize : -1, - sorter, - sort, - 'fields[appends]': appends, - // filter, - // ...actionDefaultParams, - filter: { - and: [ - defaultFilter, - schemaFilter, - filter, - // __parent ? { - // collection_name: __parent, - // } : null, - ].filter(obj => obj && Object.keys(obj).length), - }, - // ...args2, - }) - .then(({ data = [], meta = {} }) => { - return { - data: { - list: data, - total: meta.count || data.length, - }, - }; - }); - }, - { - paginated, - }, - ); - - const events = toEvents(data?.list, { - idField: rowKey, - labelField, - startDateField, - endDateField, - }); - - const messages = { - allDay: '', - previous: ( -
- -
- ), - next: ( -
- -
- ), - today: '今天', - month: '月', - week: '周', - day: '天', - agenda: '列表', - date: '日期', - time: '时间', - event: '事件', - noEventsInRange: '无', - showMore: count => `还有 ${count} 项`, - }; - - console.log('events', data); - return ( -
- - { - if (dates.eq(start, end, 'month')) { - return local.format(start, 'Y年M月', culture); - } - return `${local.format(start, 'Y年M月', culture)} - ${local.format( - end, - 'Y年M月', - culture, - )}`; - }, - }} - events={events} - onSelectSlot={slotInfo => { - // setFormMode('create'); - // drawerRef.current.setVisible(true); - // console.log('onSelectSlot', slotInfo) - }} - onView={view => { - setCalendarView(view); - console.log(view); - }} - onSelectEvent={data => { - console.log({ data }); - if (!detailsOpenMode || !details.length) { - return; - } - if (detailsOpenMode === 'window') { - const paths = history.location.pathname.split('/'); - history.push(`/admin/${paths[2]}/${data[rowKey]}/0`); - } else { - Drawer.open({ - headerStyle: - details.length > 1 - ? { - paddingBottom: 0, - borderBottom: 0, - // paddingTop: 16, - // marginBottom: -4, - } - : {}, - // title: details.length > 1 ? undefined : data[labelField], - title: data.title, - bodyStyle: { - // padding: 0, - }, - content: ({ resolve, closeWithConfirm }) => ( -
-
{ - await refresh(); - resolve(); - }} - onValueChange={() => { - closeWithConfirm && closeWithConfirm(true); - }} - onDraft={async () => { - await refresh(); - resolve(); - }} - onReset={resolve} - onDataChange={async () => { - await refresh(); - }} - data={data} - resolve={resolve} - items={details} - /> -
- ), - }); - } - }} - onRangeChange={range => { - console.log({ range }); - }} - views={['month', 'week', 'day']} - // step={120} - // showMultiDayTimes - // max={dates.add(dates.endOf(new Date(2015, 17, 1), 'day'), -1, 'hours')} - // defaultDate={new Date(2015, 3, 1)} - components={{ - timeGutterHeader: () =>
全天
, - }} - localizer={localizer} - /> -
- ); -} diff --git a/packages/app/src/components/pages/AdminLoader/View/Calendar/style.less b/packages/app/src/components/pages/AdminLoader/View/Calendar/style.less deleted file mode 100644 index 01fe7d9dc..000000000 --- a/packages/app/src/components/pages/AdminLoader/View/Calendar/style.less +++ /dev/null @@ -1,771 +0,0 @@ -@charset "UTF-8"; -.rbc-btn { - color: inherit; - font: inherit; - margin: 0; -} - -button.rbc-btn { - overflow: visible; - text-transform: none; - -webkit-appearance: button; - cursor: pointer; -} - -button[disabled].rbc-btn { - cursor: not-allowed; -} - -button.rbc-input::-moz-focus-inner { - border: 0; - padding: 0; -} - -.rbc-calendar { - box-sizing: border-box; - display: flex; - flex-direction: column; - align-items: stretch; - &.view-month { - height: 75vh; - } -} - -.rbc-calendar *, -.rbc-calendar *:before, -.rbc-calendar *:after { - box-sizing: inherit; -} - -.rbc-abs-full, -.rbc-row-bg { - overflow: hidden; - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; -} - -.rbc-ellipsis, -.rbc-event-label, -.rbc-row-segment .rbc-event-content, -.rbc-show-more { - display: block; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.rbc-rtl { - direction: rtl; -} - -.rbc-off-range { - color: rgba(0, 0, 0, 0.25); -} - -.rbc-off-range-bg { - // background: #e6e6e6; -} - -.rbc-header { - // font-size: 16px; - overflow: hidden; - flex: 1 0 0%; - text-overflow: ellipsis; - white-space: nowrap; - padding: 4px 12px; - text-align: right; - vertical-align: middle; - // font-weight: 500; - min-height: 32px; - color: rgba(0, 0, 0, 0.85); - margin: 0 4px; - border-bottom: 2px solid #f0f0f0; -} -.rbc-header + .rbc-header { - // border-left: 1px solid #f0f0f0; -} -.rbc-rtl .rbc-header + .rbc-header { - border-left-width: 0; - border-right: 1px solid #f0f0f0; -} -.rbc-header > a, -.rbc-header > a:active, -.rbc-header > a:visited { - color: inherit; - text-decoration: none; -} - -.rbc-row-content { - position: relative; - user-select: none; - -webkit-user-select: none; - z-index: 4; -} - -.rbc-row-content-scrollable { - display: flex; - flex-direction: column; - height: 100%; -} -.rbc-row-content-scrollable .rbc-row-content-scroll-container { - height: 100%; - overflow-y: scroll; - /* Hide scrollbar for Chrome, Safari and Opera */ - -ms-overflow-style: none; - /* IE and Edge */ - scrollbar-width: none; - /* Firefox */ -} -.rbc-row-content-scrollable - .rbc-row-content-scroll-container::-webkit-scrollbar { - display: none; -} - -.rbc-toolbar { - display: flex; - flex-wrap: wrap; - justify-content: center; - align-items: center; - margin-bottom: 10px; - font-size: 16px; -} -.rbc-toolbar .rbc-toolbar-label { - flex-grow: 1; - padding: 0 10px; - text-align: center; -} -.rbc-toolbar button { - outline: none; - font-size: 14px; - line-height: 1.5715; - height: 32px; - color: #373a3c; - display: inline-block; - margin: 0; - position: relative; - z-index: 1; - text-align: center; - vertical-align: middle; - background: none; - background-image: none; - border: 1px solid #d9d9d9; - padding: 4px 15px; - border-radius: 2px; - line-height: normal; - white-space: nowrap; -} -.rbc-toolbar button:active, -.rbc-toolbar button.rbc-active { - // background-image: none; - // box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125); - // background-color: #e6e6e6; - z-index: 2; - color: #1890ff; - border-color: #1890ff; -} -.rbc-toolbar button:active:hover, -.rbc-toolbar button:active:focus, -.rbc-toolbar button.rbc-active:hover, -.rbc-toolbar button.rbc-active:focus { - // color: #373a3c; - // background-color: #d4d4d4; - // border-color: #8c8c8c; - z-index: 2; - color: #40a9ff; - border-color: #40a9ff; -} -// .rbc-toolbar button:focus { -// color: #373a3c; -// background-color: #e6e6e6; -// border-color: #adadad; } -.rbc-toolbar button:hover { - // color: #373a3c; - // background-color: #e6e6e6; - z-index: 2; - color: #40a9ff; - border-color: #40a9ff; -} - -.rbc-btn-group { - display: inline-block; - white-space: nowrap; -} -.rbc-btn-group > button:first-child:not(:last-child) { - border-top-right-radius: 0; - border-bottom-right-radius: 0; -} -.rbc-btn-group > button:last-child:not(:first-child) { - border-top-left-radius: 0; - border-bottom-left-radius: 0; -} -.rbc-rtl .rbc-btn-group > button:first-child:not(:last-child) { - border-radius: 4px; - border-top-left-radius: 0; - border-bottom-left-radius: 0; -} -.rbc-rtl .rbc-btn-group > button:last-child:not(:first-child) { - border-radius: 4px; - border-top-right-radius: 0; - border-bottom-right-radius: 0; -} -.rbc-btn-group > button:not(:first-child):not(:last-child) { - border-radius: 0; -} -.rbc-btn-group button + button { - margin-left: -1px; -} -.rbc-rtl .rbc-btn-group button + button { - margin-left: 0; - margin-right: -1px; -} -.rbc-btn-group + .rbc-btn-group, -.rbc-btn-group + button { - margin-left: 10px; -} - -.rbc-event { - border: none; - box-sizing: border-box; - box-shadow: none; - margin: 0; - padding: 2px 5px; - background-color: #f0f0f0; - border-radius: 2px; - // color: #1890ff; - cursor: pointer; - font-size: 12px; - width: 100%; - text-align: left; - &:hover { - background-color: #e6f7ff; - color: #1890ff; - } -} -.rbc-slot-selecting .rbc-event { - cursor: inherit; - pointer-events: none; -} -.rbc-event.rbc-selected { - background-color: #e6f7ff; - color: #1890ff; -} -.rbc-event:focus { - // outline: 5px auto #3b99fc; -} - -.rbc-event-label { - font-size: 80%; -} - -.rbc-event-overlaps { - box-shadow: -1px 1px 5px 0px rgba(51, 51, 51, 0.5); -} - -.rbc-event-continues-prior { - border-top-left-radius: 0; - border-bottom-left-radius: 0; -} - -.rbc-event-continues-after { - border-top-right-radius: 0; - border-bottom-right-radius: 0; -} - -.rbc-event-continues-earlier { - border-top-left-radius: 0; - border-top-right-radius: 0; -} - -.rbc-event-continues-later { - border-bottom-left-radius: 0; - border-bottom-right-radius: 0; -} - -.rbc-row { - display: flex; - flex-direction: row; -} - -.rbc-row-segment { - padding: 0 4px 1px 4px; -} - -.rbc-selected-cell { - background-color: rgba(0, 0, 0, 0.1); -} - -.rbc-show-more { - z-index: 4; - font-weight: bold; - font-size: 85%; - height: auto; - line-height: normal; - color: inherit; - padding: 2px 5px; -} - -.rbc-month-view { - position: relative; - // border: 1px solid #f0f0f0; - display: flex; - flex-direction: column; - flex: 1 0 0; - width: 100%; - user-select: none; - -webkit-user-select: none; - height: 68vh; -} - -.rbc-month-header { - display: flex; - flex-direction: row; -} - -.rbc-month-row { - display: flex; - position: relative; - flex-direction: column; - flex: 1 0 0; - flex-basis: 0px; - overflow: hidden; - height: 100%; -} -.rbc-month-row + .rbc-month-row { - // border-top: 1px solid #f0f0f0; -} - -.rbc-date-cell { - // cursor: pointer; - flex: 1 1 0; - min-width: 0; - padding-right: 12px; - padding-top: 4px; - text-align: right; -} -.rbc-date-cell.rbc-now a { - // font-weight: bold; - color: #1890ff; -} -.rbc-date-cell > a, -.rbc-date-cell > a:active, -.rbc-date-cell > a:visited { - color: inherit; - text-decoration: none; -} -.rbc-date-cell > a:hover { - color: #1890ff; -} - -.rbc-row-bg { - display: flex; - flex-direction: row; - flex: 1 0 0; - overflow: hidden; -} - -.rbc-day-bg { - flex: 1 0 0%; - // border-top: 2px solid #f0f0f0; - margin: 0 4px; - &:hover { - background: #f5f5f5; - } - // cursor: pointer; -} - -.rbc-month-view { - .rbc-day-bg { - border-top: 2px solid #f0f0f0; - } - .rbc-today { - border-color: #1890ff !important; - background-color: #e6f7ff !important; - } - .rbc-header { - border-bottom: 0 !important; - } -} - -.rbc-day-bg + .rbc-day-bg { - // margin-left: 8px; - // border-left: 1px solid #f0f0f0; -} -.rbc-rtl .rbc-day-bg + .rbc-day-bg { - // border-left-width: 0; - // border-right: 1px solid #f0f0f0; -} - -.rbc-overlay { - position: absolute; - z-index: 5; - margin-top: 5px; - border-radius: 2px; - // border: 1px solid #e5e5e5; - background-color: #fff; - box-shadow: 0 3px 6px -4px rgba(0, 0, 0, 0.12), - 0 6px 16px 0 rgba(0, 0, 0, 0.08), 0 9px 28px 8px rgba(0, 0, 0, 0.05); - padding: 12px 16px; -} -.rbc-overlay > * + * { - margin-top: 1px; -} - -.rbc-overlay-header { - font-weight: 500; - min-height: 32px; - border-bottom: 1px solid #f0f0f0; - margin: -12px -16px 12px -16px; - padding: 5px 16px 4px; -} - -.rbc-agenda-view { - display: flex; - flex-direction: column; - flex: 1 0 0; - overflow: auto; -} -.rbc-agenda-view table.rbc-agenda-table { - width: 100%; - border: 1px solid #f0f0f0; - border-spacing: 0; - border-collapse: collapse; -} -.rbc-agenda-view table.rbc-agenda-table tbody > tr > td { - padding: 5px 10px; - vertical-align: top; -} -.rbc-agenda-view table.rbc-agenda-table .rbc-agenda-time-cell { - padding-left: 15px; - padding-right: 15px; - text-transform: lowercase; -} -.rbc-agenda-view table.rbc-agenda-table tbody > tr > td + td { - border-left: 1px solid #f0f0f0; -} -.rbc-rtl .rbc-agenda-view table.rbc-agenda-table tbody > tr > td + td { - border-left-width: 0; - border-right: 1px solid #f0f0f0; -} -.rbc-agenda-view table.rbc-agenda-table tbody > tr + tr { - border-top: 1px solid #f0f0f0; -} -.rbc-agenda-view table.rbc-agenda-table thead > tr > th { - padding: 3px 5px; - text-align: left; - border-bottom: 1px solid #f0f0f0; -} -.rbc-rtl .rbc-agenda-view table.rbc-agenda-table thead > tr > th { - text-align: right; -} - -.rbc-agenda-time-cell { - text-transform: lowercase; -} -.rbc-agenda-time-cell .rbc-continues-after:after { - content: ' »'; -} -.rbc-agenda-time-cell .rbc-continues-prior:before { - content: '« '; -} - -.rbc-agenda-date-cell, -.rbc-agenda-time-cell { - white-space: nowrap; -} - -.rbc-agenda-event-cell { - width: 100%; -} - -.rbc-time-column { - display: flex; - flex-direction: column; - min-height: 100%; -} -.rbc-time-column .rbc-timeslot-group { - flex: 1; -} - -.rbc-timeslot-group { - border-bottom: 1px solid #f0f0f0; - min-height: 40px; - line-height: 39px; - display: flex; - flex-flow: column nowrap; - // cursor: pointer; - &:hover { - background: #f0f0f0; - } -} - -.rbc-time-gutter, -.rbc-header-gutter { - flex: none; -} - -.rbc-label { - padding: 0 5px; -} - -.rbc-day-slot { - position: relative; -} -.rbc-day-slot .rbc-events-container { - bottom: 0; - left: 0; - position: absolute; - right: 0; - margin-right: 10px; - top: 0; -} -.rbc-day-slot .rbc-events-container.rbc-rtl { - left: 10px; - right: 0; -} -.rbc-day-slot .rbc-event { - border: 1px solid #265985; - display: flex; - max-height: 100%; - min-height: 20px; - flex-flow: column wrap; - align-items: flex-start; - overflow: hidden; - position: absolute; -} -.rbc-day-slot .rbc-event-label { - flex: none; - padding-right: 5px; - width: auto; -} -.rbc-day-slot .rbc-event-content { - width: 100%; - flex: 1 1 0; - word-wrap: break-word; - line-height: 1; - height: 100%; - min-height: 1em; -} -.rbc-day-slot .rbc-time-slot { - // border-top: 1px solid #f7f7f7; -} -.rbc-time-header-gutter { - line-height: 40px; -} -.rbc-time-header-cell { - min-height: 32px !important; -} -.rbc-calendar.view-week { - .rbc-time-header-cell { - margin-top: -32px; - margin-bottom: 4px; - } - .rbc-time-view { - padding-top: 32px; - border-top: 0; - } - .rbc-header { - padding: 4px 8px; - } - .rbc-time-header-content { - padding: 4px 0; - } - .rbc-time-header-gutter { - padding: 0; - padding-top: 2px; - > div { - border-top: 2px solid #f0f0f0; - padding: 0 5px; - } - } -} -.rbc-time-view-resources .rbc-time-gutter, -.rbc-time-view-resources .rbc-time-header-gutter { - position: sticky; - left: 0; - background-color: white; - border-right: 1px solid #f0f0f0; - z-index: 10; - margin-right: -1px; -} - -.rbc-time-view-resources .rbc-time-header { - overflow: hidden; -} - -.rbc-time-view-resources .rbc-time-header-content { - min-width: auto; - flex: 1 0 0; - flex-basis: 0px; -} - -.rbc-time-view-resources .rbc-time-header-cell-single-day { - display: none; -} - -.rbc-time-view-resources .rbc-day-slot { - min-width: 140px; -} - -.rbc-time-view-resources .rbc-header, -.rbc-time-view-resources .rbc-day-bg { - width: 140px; - flex: 1 1 0; - flex-basis: 0 px; -} - -.rbc-time-header-content + .rbc-time-header-content { - margin-left: -1px; -} - -.rbc-time-slot { - flex: 1 0 0; -} -.rbc-time-slot.rbc-now { - font-weight: bold; -} - -.rbc-day-header { - text-align: center; -} - -.rbc-slot-selection { - z-index: 10; - position: absolute; - background-color: rgba(0, 0, 0, 0.5); - color: white; - font-size: 75%; - width: 100%; - padding: 3px; -} - -.rbc-slot-selecting { - cursor: move; -} - -.rbc-time-view { - display: flex; - flex-direction: column; - flex: 1; - width: 100%; - border-top: 1px solid #f0f0f0; - min-height: 0; -} -.rbc-time-view .rbc-time-gutter { - white-space: nowrap; -} -.rbc-time-view .rbc-allday-cell { - box-sizing: content-box; - width: 100%; - height: 100%; - position: relative; -} -.rbc-time-view .rbc-allday-cell + .rbc-allday-cell { - border-left: 1px solid #f0f0f0; -} -.rbc-time-view .rbc-allday-events { - position: relative; - z-index: 4; -} -.rbc-time-view .rbc-row { - box-sizing: border-box; - min-height: 20px; -} - -.rbc-time-header { - display: flex; - flex: 0 0 auto; - flex-direction: row; -} -.rbc-time-header.rbc-overflowing { - border-right: 1px solid #f0f0f0; -} -.rbc-rtl .rbc-time-header.rbc-overflowing { - border-right-width: 0; - border-left: 1px solid #f0f0f0; -} -.rbc-time-header > .rbc-row:first-child { - border-bottom: 1px solid #f0f0f0; -} -.rbc-time-header > .rbc-row.rbc-row-resource { - border-bottom: 1px solid #f0f0f0; -} - -.rbc-time-header-cell-single-day { - display: none; -} - -.rbc-time-header-content { - flex: 1; - display: flex; - min-width: 0; - flex-direction: column; - // border-left: 1px solid #f0f0f0; -} -.rbc-rtl .rbc-time-header-content { - border-left-width: 0; - border-right: 1px solid #f0f0f0; -} -.rbc-time-header-content > .rbc-row.rbc-row-resource { - border-bottom: 1px solid #f0f0f0; - flex-shrink: 0; -} - -.rbc-time-content { - display: flex; - flex: 1 0 0%; - align-items: flex-start; - width: 100%; - border-top: 1px solid #f0f0f0; - overflow-y: auto; - position: relative; -} -.rbc-time-content > .rbc-time-gutter { - flex: none; -} -.rbc-time-content > * + * > * { - // border-left: 1px solid #f0f0f0; -} -.rbc-rtl .rbc-time-content > * + * > * { - border-left-width: 0; - border-right: 1px solid #f0f0f0; -} -.rbc-time-content > .rbc-day-slot { - width: 100%; - user-select: none; - -webkit-user-select: none; -} - -.rbc-current-time-indicator { - position: absolute; - z-index: 3; - left: 0; - right: 0; - height: 1px; - background-color: #74ad31; - pointer-events: none; -} - -@media only screen and (max-width: 800px) { - .view-type-calendar .action-buttons { - position: relative !important; - left: 0 !important; - .filter-action-button { - left: 0 !important; - } - } - .rbc-toolbar .rbc-toolbar-label { - position: absolute; - top: 28px; - left: 50%; - transform: translateX(-50%); - } - .rbc-toolbar { - justify-content: space-between !important; - } - .rbc-header { - padding: 4px !important; - } -} diff --git a/packages/app/src/components/pages/AdminLoader/View/Table.tsx b/packages/app/src/components/pages/AdminLoader/View/Table.tsx deleted file mode 100644 index 0717d7c97..000000000 --- a/packages/app/src/components/pages/AdminLoader/View/Table.tsx +++ /dev/null @@ -1,586 +0,0 @@ -import React, { useState, useEffect, useRef, createRef } from 'react'; -import './style.less'; -import { Helmet } from 'umi'; -import { Spin } from '@nocobase/client'; -import { useRequest, useHistory } from 'umi'; -import api from '@/api-client'; -import { Actions } from '../Actions'; -import { - Modal, - PageHeader, - Table as AntdTable, - Card, - Pagination, - Button, - Tabs, - Descriptions, - Tooltip, -} from 'antd'; -import { LoadingOutlined } from '@ant-design/icons'; -import { components, fields2columns } from '@/components/views/SortableTable'; -import ReactDragListView from 'react-drag-listview'; -import arrayMove from 'array-move'; -import get from 'lodash/get'; -import find from 'lodash/find'; -import Drawer from '@/components/pages/AdminLoader/Drawer'; -import Field from '@/components/views/Field'; -import { Form } from './Form'; -import { View } from './'; -import pathToRegexp from 'path-to-regexp'; - -export const icon = ; - -export function Details(props) { - const { - __parent, - associatedKey, - resourceName, - onFinish, - onDraft, - onReset, - onDataChange, - data, - items = [], - resolve, - onValueChange, - } = props; - if (!items || items.length === 0) { - return null; - } - const [currentTabIndex, setCurrentTabIndex] = useState('0'); - return ( -
- {items.length > 1 && ( -
- { - setCurrentTabIndex(activeKey); - }} - > - {items.map((page, index) => ( - - ))} - -
- )} - {(get(items, [currentTabIndex, 'views']) || []).map(view => { - let viewName: string; - if (typeof view === 'string') { - viewName = `${resourceName}.${view}`; - } - if (typeof view === 'object') { - viewName = `${resourceName}.${view.name}`; - } - return ( - - ); - })} -
- ); -} - -export function DetailsPage(props) { - const { - currentRowId, - title, - __parent, - associatedKey, - resourceName, - onFinish, - onReset, - onDataChange, - data, - items = [], - resolve, - } = props; - if (!items || items.length === 0) { - return null; - } - const history = useHistory(); - const paths = history.location.pathname.split('/'); - const index = parseInt(paths[4]); - const [currentTabIndex, setCurrentTabIndex] = useState( - items.length > index ? paths[4] : '0', - ); - return ( -
- { - history.push(`/admin/${paths[2]}`); - }} - footer={ - { - setCurrentTabIndex(activeKey); - history.push(`/admin/${paths[2]}/${currentRowId}/${activeKey}`); - }} - > - {items.map((page, index) => ( - - ))} - - } - /> -
- - {(get(items, [currentTabIndex, 'views']) || []).map(view => { - let viewName: string; - if (typeof view === 'string') { - viewName = `${resourceName}.${view}`; - } - if (typeof view === 'object') { - viewName = `${resourceName}.${view.name}`; - } - return ( - - ); - })} - -
-
- ); -} - -export function Table(props: any) { - const { - onSelected, - multiple = true, - isFieldComponent, - schema = {}, - data: record = {}, - defaultFilter, - defaultSelectedRowKeys, - noRequest = false, - __parent, - currentRowId, - } = props; - - const content = document.getElementById('content'); - - const { - fields = [], - actions = [], - details = [], - paginated = true, - defaultPerPage = 10, - rowKey = 'id', - labelField = 'id', - sort, - resourceName, - associationField = {}, - appends = [], - expandable, - detailsOpenMode = 'drawer', - filter: schemaFilter = {}, - } = schema; - - const history = useHistory(); - - const associatedKey = - props.associatedKey || record[associationField.sourceKey || 'id']; - console.log({ associatedKey, record, associationField, __parent }); - - async function reloadMenu() { - if (resourceName !== 'menus') { - return; - } - (window as any).reloadMenu && (await (window as any).reloadMenu()); - } - - const { - data, - loading, - pagination, - mutate, - refresh, - run, - params, - } = useRequest( - (params = {}, ...args) => { - const { current, pageSize, sorter, filter, ...restParams } = params as any; - console.log('paramsparamsparamsparamsparams', params, args); - return api - .resource(resourceName) - .list({ - associatedKey, - page: paginated ? current : 1, - perPage: paginated ? pageSize : -1, - sorter, - sort, - 'fields[appends]': appends, - // filter, - // ...actionDefaultParams, - filter: { - and: [ - defaultFilter, - schemaFilter, - filter, - // __parent ? { - // collection_name: __parent, - // } : null, - ].filter(obj => obj && Object.keys(obj).length), - }, - // ...args2, - }) - .then(({ data = [], meta = {} }) => { - return { - data: { - list: data, - total: meta.count || data.length, - }, - }; - }); - }, - { - paginated, - defaultPageSize: defaultPerPage, - }, - ); - - const currentRow = find( - data && data.list, - item => item[rowKey] == currentRowId, - ); - console.log({ currentRow }); - function getExpandedRowKeys(items: Array) { - if (!Array.isArray(items)) { - return []; - } - console.log({ items }); - let rowKeys = []; - items.forEach(item => { - if (item.children && item.children.length) { - rowKeys.push(item[rowKey]); - rowKeys = rowKeys.concat(getExpandedRowKeys(item.children)); - } - }); - return rowKeys; - } - - const [expandedRowKeys, setExpandedRowKeys] = useState(() => { - if (expandable) { - return getExpandedRowKeys(data?.list); - } - return []; - }); - - useEffect(() => { - setExpandedRowKeys(getExpandedRowKeys(data?.list)); - }, [data]); - - if (expandable) { - // expandable.expandIconColumnIndex = 4; - expandable.onExpand = (expanded, record) => { - if (!expanded) { - const index = expandedRowKeys.indexOf(record[rowKey]); - if (index >= 0) { - expandedRowKeys.splice(index, 1); - } - } else { - expandedRowKeys.push(record[rowKey]); - } - setExpandedRowKeys(expandedRowKeys); - }; - expandable.expandedRowKeys = expandedRowKeys; - console.log({ expandable, data }); - } - - // const { data, loading, pagination, mutate, refresh, run, params } = useRequest((params = {}, ...args) => { - // const { current, pageSize, sorter, filter, ...restParams } = params; - // return api.resource(resourceName).list({ - // associatedKey, - // sort, - // }).then(({data = [], meta = {}}) => { - // return { - // data: { - // list: data, - // total: meta.count||data.length, - // }, - // }; - // }); - // }, { - // paginated, - // defaultPageSize: defaultPerPage, - // }); - - const [selectedRowKeys, setSelectedRowKeys] = useState( - defaultSelectedRowKeys || [], - ); - const onChange = ( - selectedRowKeys: React.ReactText[], - selectedRows: React.ReactText[], - ) => { - setSelectedRowKeys(selectedRowKeys); - onSelected && onSelected(selectedRows); - }; - // useEffect(() => { - // setSelectedRowKeys(srk); - // }, [srk]); - // console.log(srk); - const tableProps: any = {}; - - if (actions.length || defaultSelectedRowKeys) { - tableProps.rowSelection = { - type: multiple ? 'checkbox' : 'radio', - selectedRowKeys, - onChange, - }; - } - - const ref = createRef(); - - const dragProps = { - async onDragEnd(fromIndex, toIndex) { - const list = data?.list || (data as any); - const nodes = ref.current.querySelectorAll('.ant-table-row'); - const resourceKey = nodes[fromIndex].getAttribute('data-row-key'); - const targetIndex = nodes[toIndex].getAttribute('data-row-key'); - - // const newList = arrayMove(list, fromIndex, toIndex); - // const item = list.splice(fromIndex, 1)[0]; - // list.splice(toIndex, 0, item); - // mutate({ - // ...data, - // list: newList, - // }); - await api.resource(resourceName).sort({ - associatedKey, - resourceKey, - values: { - field: 'sort', - target: { - [rowKey]: targetIndex, - }, - }, - }); - await refresh(); - await reloadMenu(); - - // console.log(nodes[fromIndex].getAttribute('data-row-key'), nodes[toIndex]) - console.log({ - // ref: ref.current.querySelectorAll('.ant-table-row'), - // fromIndex, toIndex, newList, - values: { - field: 'sort', - target: { - [rowKey]: targetIndex, - }, - }, - }); - }, - handleSelector: '.drag-handle', - ignoreSelector: 'tr.ant-table-expanded-row', - nodeSelector: 'tr.ant-table-row', - }; - - return ( -
-
- - - { - if (!detailsOpenMode || !details.length) { - return
; - } - return ( - - ); - }, - }, - }} - dataSource={data?.list || (data as any)} - size={'middle'} - columns={fields2columns(fields, { associatedKey, refresh })} - pagination={false} - onChange={(pagination, filters, sorter, extra) => { - console.log({sorter}); - run({ ...params[0], sorter }); - }} - expandable={expandable} - onRow={data => ({ - onClick: e => { - const className = (e.target as HTMLElement).className; - console.log({ className }); - if ( - typeof className === 'string' && - (className.includes('ant-table-selection-column') || - className.includes('ant-checkbox') || - className.includes('ant-radio')) - ) { - return; - } - if (!detailsOpenMode || !details.length) { - return; - } - if (!isFieldComponent && detailsOpenMode === 'window') { - const paths = history.location.pathname.split('/'); - history.push(`/admin/${paths[2]}/${data[rowKey]}/0`); - } else { - Drawer.open({ - headerStyle: - details.length > 1 - ? { - paddingBottom: 0, - borderBottom: 0, - // paddingTop: 16, - // marginBottom: -4, - } - : {}, - // title: details.length > 1 ? undefined : data[labelField], - title: data[labelField], - bodyStyle: { - // padding: 0, - }, - content: ({ resolve, closeWithConfirm }) => ( -
-
{ - await refresh(); - resolve(); - await reloadMenu(); - }} - onValueChange={() => { - closeWithConfirm && closeWithConfirm(true); - }} - onDraft={async () => { - await refresh(); - resolve(); - await reloadMenu(); - }} - onReset={resolve} - onDataChange={async () => { - await refresh(); - await reloadMenu(); - }} - data={data} - resolve={resolve} - items={details} - /> -
- ), - }); - } - }, - })} - {...tableProps} - /> - - {paginated && ( -
- `共 ${total} 条记录`} - showQuickJumper - showSizeChanger - size={'small'} - /> -
- )} - - {currentRow && ( -
- { - await refresh(); - await reloadMenu(); - }} - onReset={() => {}} - onDataChange={async () => { - await refresh(); - await reloadMenu(); - }} - currentRowId={currentRowId} - data={currentRow} - items={details} - /> -
- )} - - ); -} diff --git a/packages/app/src/components/pages/AdminLoader/View/Wysiwyg.tsx b/packages/app/src/components/pages/AdminLoader/View/Wysiwyg.tsx deleted file mode 100644 index 6b8ac4db9..000000000 --- a/packages/app/src/components/pages/AdminLoader/View/Wysiwyg.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import React, { useState, useEffect } from 'react'; -import './style.less'; -import { Helmet } from 'umi'; -import { Spin } from '@nocobase/client'; -import { useRequest, useLocation } from 'umi'; -import api from '@/api-client'; -import { Actions } from '../Actions'; -import { - Table as AntdTable, - Card, - Pagination, - Button, - Tabs, - Descriptions as AntdDescriptions, - Tooltip, -} from 'antd'; -import { LoadingOutlined } from '@ant-design/icons'; -import { components, fields2columns } from '@/components/views/SortableTable'; -import ReactDragListView from 'react-drag-listview'; -import arrayMove from 'array-move'; -import get from 'lodash/get'; -import Drawer from '@/components/pages/AdminLoader/Drawer'; -import Field, { markdown } from '@/components/views/Field'; -import { Form } from './Form'; - -export function Wysiwyg(props) { - const { data: record = {}, schema = {}, onDataChange } = props; - - const { html = '' } = schema; - - return
; -} diff --git a/packages/app/src/components/pages/AdminLoader/View/index.tsx b/packages/app/src/components/pages/AdminLoader/View/index.tsx deleted file mode 100644 index 2e2d80cd7..000000000 --- a/packages/app/src/components/pages/AdminLoader/View/index.tsx +++ /dev/null @@ -1,91 +0,0 @@ -import React, { useState, useEffect } from 'react'; -import './style.less'; -import { Helmet } from 'umi'; -import { Spin } from '@nocobase/client'; -import { useRequest, useLocation } from 'umi'; -import api from '@/api-client'; -import { Actions } from '../Actions'; -import { - Table as AntdTable, - Card, - Pagination, - Button, - Tabs, - Tooltip, -} from 'antd'; -import { LoadingOutlined } from '@ant-design/icons'; -import { components, fields2columns } from '@/components/views/SortableTable'; -import ReactDragListView from 'react-drag-listview'; -import arrayMove from 'array-move'; -import get from 'lodash/get'; -import Drawer from '@/components/pages/AdminLoader/Drawer'; -import Field from '@/components/views/Field'; -import { Form } from './Form'; -import { Table } from './Table'; -import { Association } from './Association'; -import { Descriptions } from './Descriptions'; -import { FilterForm } from './FilterForm'; -import { SubTable } from './SubTable'; -import { Wysiwyg } from './Wysiwyg'; -import { Calendar } from './Calendar'; -import { Kanban } from './Kanban'; - -const VIEWS = new Map(); - -export function registerView(type, view) { - VIEWS.set(type, view); -} - -export function getView(type) { - return VIEWS.get(type); -} - -export const icon = ; - -export function View(props: any) { - const { wrapper, schema, viewName, children, ...restProps } = props; - - const { data = {}, loading } = useRequest( - () => { - return schema - ? Promise.resolve({ data: schema }) - : api.resource('views_v2').getInfo({ - resourceKey: viewName, - }); - }, - { - refreshDeps: [viewName, schema], - }, - ); - - if (loading) { - return ; - } - - const type = props.type || data.type; - - const Component = getView(type); - - if (wrapper === 'card') { - return ( - - - - ) - } - - return ; -} - -registerView('table', Table); -registerView('subTable', SubTable); -registerView('form', Form); -registerView('filterForm', FilterForm); -registerView('descriptions', Descriptions); -registerView('association', Association); -registerView('wysiwyg', Wysiwyg); -registerView('markdown', Wysiwyg); -registerView('calendar', Calendar); -registerView('kanban', Kanban); - -export default View; diff --git a/packages/app/src/components/pages/AdminLoader/View/style.less b/packages/app/src/components/pages/AdminLoader/View/style.less deleted file mode 100644 index 6dab1a2c8..000000000 --- a/packages/app/src/components/pages/AdminLoader/View/style.less +++ /dev/null @@ -1,79 +0,0 @@ -.ant-drawer-body { - padding-bottom: 50px; - .form-button-group { - position: absolute; - bottom: 0; - left: 0; - width: 100%; - padding: 10px 16px; - border-top: 1px solid #f0f0f0; - background-color: #fff; - } -} -.ant-drawer-footer { - text-align: right; -} -.ant-descriptions-view - .ant-descriptions-item-container - .ant-descriptions-item-label { - align-items: center; -} -.page-tabs { - .ant-tabs { - margin: -24px -24px 8px; - position: relative; - // position: relative; - // // border-bottom: 1px solid #f0f0f0; - // padding: 0 24px; - // &::after { - // position: absolute; - // right: -24px; - // left: -24px; - // border-bottom: 1px solid #f0f0f0; - // content: ''; - // bottom: 16px; - // z-index: 11; - // } - .ant-tabs-nav { - &::before { - right: -24px; - left: -24px; - } - .ant-tabs-tab { - margin: 0 0 0 24px; - } - // margin-bottom: -1px; - } - } -} - -.markdown-content { - *:last-child { - margin-bottom: 0; - } -} - -.details-page { - background: #f0f2f5; - position: fixed; - top: 48px; - left: 200px; - width: calc(100% - 200px); - height: calc(100% - 48px); - overflow: auto; - transition: all 0.2s; -} - -body.collapsed { - .details-page { - left: 0; - width: 100%; - } -} - -@media only screen and (max-width: 800px) { - .details-page { - left: 0; - width: 100%; - } -} diff --git a/packages/app/src/components/pages/AdminLoader/index.tsx b/packages/app/src/components/pages/AdminLoader/index.tsx index 937064bbc..c81109f57 100644 --- a/packages/app/src/components/pages/AdminLoader/index.tsx +++ b/packages/app/src/components/pages/AdminLoader/index.tsx @@ -2,11 +2,11 @@ import React from 'react'; import api from '@/api-client'; import { useRequest, useLocation, useHistory, Redirect } from 'umi'; import get from 'lodash/get'; -import { TopMenuLayout } from './TopMenuLayout'; -import { SideMenuLayout } from './SideMenuLayout'; -import Page from './Page'; +import { TopMenuLayout } from '@/components/pages/TopMenuLayout'; +import { SideMenuLayout } from '@/components/pages/SideMenuLayout'; +import Page from '@/components/pages/Page'; import pathToRegexp from 'path-to-regexp'; -import { Spin } from '@nocobase/client'; +import { Spin } from '@/components/spin'; export function AdminLoader(props: any) { const { data = [], error, loading, run } = useRequest(() => diff --git a/packages/app/src/components/pages/AdminLoader/menu/index.tsx b/packages/app/src/components/pages/AdminLoader/menu/index.tsx deleted file mode 100644 index 318d612e4..000000000 --- a/packages/app/src/components/pages/AdminLoader/menu/index.tsx +++ /dev/null @@ -1,108 +0,0 @@ -import React, { useEffect, useState } from 'react'; -import { Layout, Menu, Breadcrumb } from 'antd'; -import { Link as UmiLink, useLocation } from 'umi'; -import Icon from '@/components/icons'; -import './style.less'; - -function pathcamp(path1: string, path2: string) { - return true; - if (path1 === path2) { - return true; - } - return path1.indexOf(`${path2}/`) === 0; -} - -function Link(props: any) { - const { to, children } = props; - if (/^http/.test(to)) { - return ( - - {children} - - ); - } - return ; -} - -export default (props: any) => { - const { - menuId, - currentPageName, - items = [], - hideChildren, - ...restProps - } = props; - if (items.length === 0) { - return null; - } - const toPaths = data => { - const paths = []; - data.forEach(item => { - if (item.path && item.path === currentPageName) { - paths.push(`${item.name}`); - } - if (item.paths && item.paths.includes(currentPageName)) { - paths.push(`${item.name}`); - } - paths.push(...toPaths(item.children || [])); - }); - return paths; - }; - const keys = toPaths(items); - console.log({ menuId, currentPageName, items, keys }); - const [loading, setLoading] = useState(true); - useEffect(() => { - setLoading(true); - setTimeout(() => { - setLoading(false); - }); - }, [menuId]); - if (loading) { - return null; - } - const renderChildren = items => { - return items.map(item => { - const { children = [] } = item; - // const subItems = children.filter(child => child.showInMenu); - if (!hideChildren && children.length) { - return ( - } - title={<>{item.title}} - > - {renderChildren(children)} - - ); - } - return ( - } - key={`${item.name}`} - > - {item.title} - - ); - }); - }; - return ( - { - console.log({ openKeys }); - }} - onSelect={info => { - console.log({ info }); - }} - onDeselect={info => { - console.log({ info }); - }} - {...restProps} - > - {renderChildren(items)} - - ); -}; diff --git a/packages/app/src/components/pages/AdminLoader/menu/style.less b/packages/app/src/components/pages/AdminLoader/menu/style.less deleted file mode 100644 index fc47ce22e..000000000 --- a/packages/app/src/components/pages/AdminLoader/menu/style.less +++ /dev/null @@ -1,7 +0,0 @@ -.ant-menu-sub.ant-menu-inline > .ant-menu-item, -.ant-menu-sub.ant-menu-inline > .ant-menu-submenu > .ant-menu-submenu-title { - height: 32px; - line-height: 32px; - margin: 4px 0; - font-size: 13px; -} diff --git a/packages/app/src/components/pages/AvatarDropdown/index.tsx b/packages/app/src/components/pages/AvatarDropdown/index.tsx index 7c37debc6..f69e7b976 100644 --- a/packages/app/src/components/pages/AvatarDropdown/index.tsx +++ b/packages/app/src/components/pages/AvatarDropdown/index.tsx @@ -41,6 +41,7 @@ export default (props: any) => { } = useModel('@@initialState'); const responsive = useResponsive(); const isMobile = responsive.small && !responsive.middle && !responsive.large; + const { currentUser = {} } = initialState as any; return (
{ icon={} style={{ marginRight: 5 }} />{' '} - { initialState.currentUser.nickname || initialState.currentUser.email } + { currentUser.nickname || currentUser.email }
diff --git a/packages/app/src/components/pages/CollectionLoader/Breadcrumb/index.tsx b/packages/app/src/components/pages/CollectionLoader/Breadcrumb/index.tsx deleted file mode 100644 index 65d5687ea..000000000 --- a/packages/app/src/components/pages/CollectionLoader/Breadcrumb/index.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import React from 'react'; -import { PageHeader, Tabs, Button, Statistic, Descriptions } from 'antd'; -import './style.less'; - -export function Breadcrumb(props) { - return
{props.children}
; -} - -Breadcrumb.Item = props => { - return
标题一
; -}; - -export default Breadcrumb; diff --git a/packages/app/src/components/pages/CollectionLoader/Breadcrumb/style.less b/packages/app/src/components/pages/CollectionLoader/Breadcrumb/style.less deleted file mode 100644 index d6318c0a8..000000000 --- a/packages/app/src/components/pages/CollectionLoader/Breadcrumb/style.less +++ /dev/null @@ -1,28 +0,0 @@ -.collection-item { - .breadcrumb { - display: flex; - position: absolute; - width: 100%; - padding: 12px 14px 0; - z-index: 4; - &-item { - vertical-align: middle; - color: rgba(0, 0, 0, 0.45); - &::after { - content: '/'; - color: rgba(0, 0, 0, 0.45); - display: inline-block; - margin: 0 8px; - } - &:last-child::after { - display: none; - } - a { - color: rgba(0, 0, 0, 0.45); - } - span { - color: rgba(0, 0, 0, 0.45); - } - } - } -} diff --git a/packages/app/src/components/pages/CollectionLoader/CollectionIndex.tsx b/packages/app/src/components/pages/CollectionLoader/CollectionIndex.tsx deleted file mode 100644 index 2519eef88..000000000 --- a/packages/app/src/components/pages/CollectionLoader/CollectionIndex.tsx +++ /dev/null @@ -1,49 +0,0 @@ -import React from 'react'; -import ViewFactory from '@/components/views'; -import { PageHeader, Tabs, Button, Statistic, Descriptions } from 'antd'; -import { useRequest, request, Spin } from '@nocobase/client'; -import { getPathName } from './utils'; -import { Helmet } from 'umi'; - -export function CollectionIndex(props) { - const { lastPage } = props; - const { viewName, collection } = props.match.params; - const { title, defaultViewName } = props.collection; - - return ( -
- - {title} - - Operation, - // , - // , - ] - } - // footer={ - // - // - // - // - // } - /> -
- -
-
- ); -} - -export default CollectionIndex; diff --git a/packages/app/src/components/pages/CollectionLoader/CollectionSingle.tsx b/packages/app/src/components/pages/CollectionLoader/CollectionSingle.tsx deleted file mode 100644 index 6cc89ea88..000000000 --- a/packages/app/src/components/pages/CollectionLoader/CollectionSingle.tsx +++ /dev/null @@ -1,102 +0,0 @@ -import React, { useState } from 'react'; -import { PageHeader, Tabs, Button, Statistic, Descriptions } from 'antd'; -import { CollectionTabPane } from './CollectionTabPane'; -import { getPathName, redirectTo } from './utils'; -import api from '@/api-client'; -import { useRequest } from 'umi'; -import { Spin } from '@nocobase/client'; -import { Helmet } from 'umi'; - -export function CollectionSingle(props) { - // console.log(props); - const { item = {} } = props; - const { data: collections = [], loading: collectionLoading } = useRequest( - () => - api.resource(props.match.params['collection']).getCollections({ - values: { - tabs: props.match.params['items'], - }, - }), - ); - - // const { data = {}, loading } = useRequest(() => currentTab && api.resource(currentTab.collection_name).getPageInfo({ - // resourceKey: item.itemId, - // })); - - const [activing, setActiving] = useState(false); - - if (collectionLoading) { - return ; - } - - const collection = collections[props.itemIndex] || {}; - - const { tabs = [], pageInfo = {} } = collection; - const activeTab = tabs.find(tab => tab.name == item.tabName) || {}; - console.log({ tabs, activeTab, item }); - - if (!activeTab) { - return null; - } - - return ( -
- - {pageInfo.pageTitle} - - { - redirectTo({ - ...props.match.params, - removeLastItem: true, - }); - }} - title={pageInfo.pageTitle} - // subTitle="This is a subtitle" - extra={ - [ - // , - // , - // , - ] - } - footer={ - { - setActiving(true); - redirectTo({ - ...props.match.params, - lastItem: { - tabName: activeKey, - }, - }); - setTimeout(() => { - setActiving(false); - }, 2); - }} - > - {tabs.map(tab => ( - - ))} - - } - /> -
- -
-
- ); -} - -export default CollectionSingle; diff --git a/packages/app/src/components/pages/CollectionLoader/CollectionTabPane.tsx b/packages/app/src/components/pages/CollectionLoader/CollectionTabPane.tsx deleted file mode 100644 index 9d2d16cb7..000000000 --- a/packages/app/src/components/pages/CollectionLoader/CollectionTabPane.tsx +++ /dev/null @@ -1,46 +0,0 @@ -import React, { useEffect, useState } from 'react'; -import ViewFactory from '@/components/views'; -import { PageHeader, Tabs, Button, Statistic, Descriptions } from 'antd'; -import { useRequest, request, Spin } from '@nocobase/client'; - -export function CollectionTabPane(props) { - const { loading, pageInfo = {}, activeTab = {}, item = {} } = props; - const { - viewName, - associationField = {}, - collection_name, - field = {}, - } = activeTab; - const { name, target, sourceKey = 'id' } = associationField || {}; - - const params = {}; - - if (target) { - params['resourceName'] = name; - params['resourceTarget'] = target; - params['associatedName'] = collection_name; - params['associatedKey'] = pageInfo[sourceKey] || item.itemId; - } else { - params['resourceName'] = collection_name; - params['resourceKey'] = item.itemId; - } - - console.log({ params }); - - if (loading) { - return ; - } - - return ( -
- -
- ); -} - -export default CollectionTabPane; diff --git a/packages/app/src/components/pages/CollectionLoader/index.tsx b/packages/app/src/components/pages/CollectionLoader/index.tsx deleted file mode 100644 index f6f59532f..000000000 --- a/packages/app/src/components/pages/CollectionLoader/index.tsx +++ /dev/null @@ -1,68 +0,0 @@ -import React from 'react'; -import Breadcrumb from './Breadcrumb'; -import CollectionIndex from './CollectionIndex'; -import CollectionSingle from './CollectionSingle'; -import './style.less'; -import { request, Spin } from '@nocobase/client'; -import api from '@/api-client'; -import { useRequest } from 'umi'; - -export function CollectionLoader(props: any) { - let { path, pagepath, collection } = props.match.params; - if (path.startsWith(pagepath)) { - path = path.substring(pagepath.length); - } - let matches: any; - matches = /\/views\/([^/]+)/.exec(path); - if (matches) { - props.match.params['viewName'] = matches[1]; - path = path.substring(`/views/${matches[1]}`.length); - } - const re = /\/items\/([^/]+)\/tabs\/([^/]+)/g; - matches = [...path.matchAll(re)]; - let items = matches.map((match, index) => ({ - itemId: match[1], - tabName: match[2], - })); - props.match.params['items'] = items; - console.log('props.match', props.match, path); - const { data = {}, error, loading, run } = useRequest(() => - api.resource(collection).getCollection(), - ); - - // const { data: collections = [], loading } = useRequest(() => api.resource(collection).getCollections({ - // values: { - // tabs: items, - // }, - // }), { - // // refreshDeps: [items], - // }); - - if (loading) { - return ; - } - - return ( -
-
- {items.length === 0 && } -
- {items.length > 0 && ( -
- {/* - {items.map(item => )} - */} - {items.map((item, index) => { - return ( -
- -
- ); - })} -
- )} -
- ); -} - -export default CollectionLoader; diff --git a/packages/app/src/components/pages/CollectionLoader/style.less b/packages/app/src/components/pages/CollectionLoader/style.less deleted file mode 100644 index e9fb95dd7..000000000 --- a/packages/app/src/components/pages/CollectionLoader/style.less +++ /dev/null @@ -1,49 +0,0 @@ -.collection { - position: relative; - height: calc(100vh - 48px); - overflow: hidden; -} - -.collection-index { - position: absolute; - top: 0; - width: 100%; - height: 100%; - overflow: auto; - z-index: 1; - background: #f0f2f5; -} - -.collection-item { - position: absolute; - top: 0; - width: 100%; - height: 100%; - overflow: hidden; - z-index: 4; - background: #f0f2f5; -} - -.collection-single { - position: absolute; - top: 0; - width: 100%; - height: 100%; - overflow: auto; - background: #f0f2f5; -} - -.collection-content { - margin: 16px; -} - -@media only screen and (max-width: 800px) { - .collection-content { - margin: 0; - margin-top: 1px; - } -} - -// .ant-page-header.has-footer { -// padding-top: 50px; -// } diff --git a/packages/app/src/components/pages/CollectionLoader/utils.ts b/packages/app/src/components/pages/CollectionLoader/utils.ts deleted file mode 100644 index ca828369d..000000000 --- a/packages/app/src/components/pages/CollectionLoader/utils.ts +++ /dev/null @@ -1,43 +0,0 @@ -import cloneDeep from 'lodash/cloneDeep'; -import { history } from 'umi'; - -export function getPathName(params) { - const { - pagepath, - viewName, - removeLastItem, - items = [], - lastItem = {}, - newItem = {}, - } = cloneDeep(params); - let path = `/${pagepath}`; - if (viewName) { - path += `/views/${viewName}`; - } - let last = items.pop(); - path += items - .map(item => `/items/${item.itemId}/tabs/${item.tabName}`) - .join('/'); - if (removeLastItem) { - return path; - } - last = { ...last, ...lastItem }; - if (typeof last.itemId !== 'undefined') { - path += `/items/${last.itemId}/tabs/${last.tabName}`; - } - if (typeof newItem.itemId !== 'undefined') { - path += `/items/${newItem.itemId}/tabs/${newItem.tabName}`; - } - return path; -} - -/** - * 跳转 - * - * @param params - * @param item - */ -export function redirectTo(params = {}) { - const pathname = getPathName(params); - history.push(pathname); -} diff --git a/packages/app/src/components/pages/Page.tsx b/packages/app/src/components/pages/Page.tsx deleted file mode 100644 index 9e3a08bc1..000000000 --- a/packages/app/src/components/pages/Page.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import React from 'react'; -import { PageHeader } from 'antd'; -import './style.less'; -import { Helmet } from 'umi'; - -export function Page(props: any) { - const { title, children, ...restProps } = props; - return ( -
- - {title} - - -
{children}
-
- ); -} - -export default Page; diff --git a/packages/app/src/components/pages/AdminLoader/Page/index.tsx b/packages/app/src/components/pages/Page/index.tsx similarity index 97% rename from packages/app/src/components/pages/AdminLoader/Page/index.tsx rename to packages/app/src/components/pages/Page/index.tsx index f90c634e1..5d7378ed9 100644 --- a/packages/app/src/components/pages/AdminLoader/Page/index.tsx +++ b/packages/app/src/components/pages/Page/index.tsx @@ -2,10 +2,10 @@ import React from 'react'; import { PageHeader, Card, Row, Col, Modal, message } from 'antd'; import './style.less'; import { Helmet, useHistory } from 'umi'; -import { Spin } from '@nocobase/client'; +import { Spin } from '@/components/spin'; import { useRequest, useModel } from 'umi'; import api from '@/api-client'; -import View from '../View'; +import View from '@/components/views'; import get from 'lodash/get'; import { markdown } from '@/components/views/Field'; diff --git a/packages/app/src/components/pages/AdminLoader/Page/style.less b/packages/app/src/components/pages/Page/style.less similarity index 100% rename from packages/app/src/components/pages/AdminLoader/Page/style.less rename to packages/app/src/components/pages/Page/style.less diff --git a/packages/app/src/components/pages/PageLoader.tsx b/packages/app/src/components/pages/PageLoader.tsx index 541d155d1..7d2bb03c0 100644 --- a/packages/app/src/components/pages/PageLoader.tsx +++ b/packages/app/src/components/pages/PageLoader.tsx @@ -1,7 +1,6 @@ import React, { useState } from 'react'; -// import { request } from 'umi'; import { TemplateLoader } from './TemplateLoader'; -import { useRequest, request } from '@nocobase/client'; +import { useRequest } from 'umi'; import { templates } from '@/pages'; import api from '@/api-client'; @@ -21,7 +20,7 @@ export function PageLoader(props: any) { {...props} templates={templates} loading={loading && first} - pages={data.data || {}} + pages={data || {}} pathname={`/${path}`} /> ); diff --git a/packages/app/src/components/pages/SideMenuLayout/index.tsx b/packages/app/src/components/pages/SideMenuLayout/index.tsx index 3bad9bbb1..a4d385de9 100644 --- a/packages/app/src/components/pages/SideMenuLayout/index.tsx +++ b/packages/app/src/components/pages/SideMenuLayout/index.tsx @@ -1,22 +1,23 @@ import React, { useState } from 'react'; import { Layout, Breadcrumb, Drawer } from 'antd'; import { Link } from 'umi'; -import './style.less'; import Menu from '@/components/menu'; import { MenuUnfoldOutlined, MenuFoldOutlined } from '@ant-design/icons'; import { useLocalStorageState } from 'ahooks'; import { useResponsive } from 'ahooks'; +import './style.less'; export function SideMenuLayout(props: any) { - const { menu = [], id } = props.page; + const { currentPageName, menu = [], menuId } = props; const [visible, setVisible] = useState(false); // console.log(menu); const [collapsed, setCollapsed] = useLocalStorageState( - `nocobase-menu-collapsed-${id}`, + `nocobase-menu-collapsed-${menuId}`, false, ); const responsive = useResponsive(); const isMobile = responsive.small && !responsive.middle && !responsive.large; + document.body.className = collapsed ? 'collapsed' : ''; return ( {!isMobile && ( @@ -24,11 +25,17 @@ export function SideMenuLayout(props: any) { className={`nb-sider${collapsed ? ' collapsed' : ''}`} theme={'light'} > - +
{ setCollapsed(!collapsed); setVisible(true); + document.body.className = collapsed ? 'collapsed' : ''; }} className={'menu-toggle'} > @@ -41,7 +48,7 @@ export function SideMenuLayout(props: any) {
)} - + {props.children} {isMobile && ( { setCollapsed(!collapsed); setVisible(false); + document.body.className = collapsed ? 'collapsed' : ''; }} placement={'left'} closable={false} @@ -58,7 +66,10 @@ export function SideMenuLayout(props: any) { onSelect={() => { setCollapsed(false); setVisible(false); + document.body.className = collapsed ? 'collapsed' : ''; }} + currentPageName={currentPageName} + menuId={menuId} items={menu} mode={'inline'} /> @@ -69,6 +80,7 @@ export function SideMenuLayout(props: any) { onClick={() => { setCollapsed(!collapsed); setVisible(true); + document.body.className = collapsed ? 'collapsed' : ''; }} className={'menu-toggle'} > diff --git a/packages/app/src/components/pages/TemplateLoader.tsx b/packages/app/src/components/pages/TemplateLoader.tsx index c6a614433..4ab965f52 100644 --- a/packages/app/src/components/pages/TemplateLoader.tsx +++ b/packages/app/src/components/pages/TemplateLoader.tsx @@ -1,8 +1,8 @@ import React from 'react'; import { Redirect } from 'umi'; import get from 'lodash/get'; -import { Spin } from '@nocobase/client'; -import { CollectionLoader } from './CollectionLoader'; +import { Spin } from '@/components/spin'; +// import { CollectionLoader } from './CollectionLoader'; function getRoutes(path: string, pages: any) { const keys = path.split('/'); @@ -43,7 +43,9 @@ export function TemplateLoader(props: any) { // ? CollectionLoader // : require(`@/pages/${tmp}`).default; if (route.type === 'collection') { - Component = CollectionLoader; + Component = (props) => { + return
+ }; componentProps.match.params['collection'] = route.collection; } else { Component = templates[route.template]; diff --git a/packages/app/src/components/pages/TopMenuLayout/index.tsx b/packages/app/src/components/pages/TopMenuLayout/index.tsx index dd5cffd8a..25f8c0352 100644 --- a/packages/app/src/components/pages/TopMenuLayout/index.tsx +++ b/packages/app/src/components/pages/TopMenuLayout/index.tsx @@ -1,15 +1,17 @@ import React, { useState } from 'react'; import { Layout, Dropdown, Avatar, Drawer } from 'antd'; import './style.less'; -import { history, Link, request, useModel, Redirect } from 'umi'; +import { history, Link, request, useModel } from 'umi'; import { UserOutlined, CodeOutlined, MenuOutlined } from '@ant-design/icons'; -import AvatarDropdown from '../AvatarDropdown'; +import AvatarDropdown from '@/components/pages/AvatarDropdown'; import Menu from '@/components/menu'; import { ReactComponent as Logo } from './logo-white.svg'; import { useResponsive, useLocalStorageState } from 'ahooks'; +import get from 'lodash/get'; export function TopMenuLayout(props: any) { - const { menu = [] } = props.page; + const { currentPageName, menu = [] } = props; + console.log({ menu }); // const [visible, setVisible] = useState(false); const [visible, setVisible] = useLocalStorageState( `nocobase-nav-visible`, @@ -17,18 +19,27 @@ export function TopMenuLayout(props: any) { ); const responsive = useResponsive(); const isMobile = responsive.small && !responsive.middle && !responsive.large; - return ; + const { + initialState = {}, + loading, + error, + refresh, + setInitialState, + } = useModel('@@initialState'); + const logoUrl = get(initialState, 'systemSettings.logo.url'); + console.log({ logoUrl }); return ( -
- +
+ {!logoUrl ? : }
{!isMobile && ( { setVisible(false); }} diff --git a/packages/app/src/components/pages/TopMenuLayout/style.less b/packages/app/src/components/pages/TopMenuLayout/style.less index d8d8179a8..58e2850db 100644 --- a/packages/app/src/components/pages/TopMenuLayout/style.less +++ b/packages/app/src/components/pages/TopMenuLayout/style.less @@ -4,7 +4,13 @@ font-size: 18px; letter-spacing: 2px; font-weight: 300; - padding: 6px 25px 0 25px; + padding: 0 15px; + img { + height: 100%; + } + svg { + margin-top: 12px; + } } body { @@ -17,3 +23,15 @@ body { .noco-top-menu.ant-menu-submenu-popup.ant-menu-dark .ant-menu-item-selected { background-color: rgba(255, 255, 255, 0.1); } + +.ant-layout-content { + overflow: auto; +} + +.ant-layout-header { + display: flex; +} + +.ant-menu-dark.ant-menu-horizontal { + margin-right: 100px; +} diff --git a/packages/app/src/components/pages/index.tsx b/packages/app/src/components/pages/index.tsx index 2e28d625b..413de02d9 100644 --- a/packages/app/src/components/pages/index.tsx +++ b/packages/app/src/components/pages/index.tsx @@ -1,7 +1,3 @@ export { PageLoader } from './PageLoader'; export { TemplateLoader } from './TemplateLoader'; -export { CollectionLoader } from './CollectionLoader'; export { PageLoader as default } from './PageLoader'; -export { SideMenuLayout } from './SideMenuLayout/index'; -export { TopMenuLayout } from './TopMenuLayout/index'; -export { Page } from './Page'; diff --git a/packages/client/src/spin/index.tsx b/packages/app/src/components/spin/index.tsx similarity index 100% rename from packages/client/src/spin/index.tsx rename to packages/app/src/components/spin/index.tsx diff --git a/packages/app/src/components/pages/AdminLoader/View/Association.tsx b/packages/app/src/components/views/Association.tsx similarity index 76% rename from packages/app/src/components/pages/AdminLoader/View/Association.tsx rename to packages/app/src/components/views/Association.tsx index 6b29d56f6..77d5f058d 100644 --- a/packages/app/src/components/pages/AdminLoader/View/Association.tsx +++ b/packages/app/src/components/views/Association.tsx @@ -1,10 +1,10 @@ import React, { useState, useEffect } from 'react'; import './style.less'; import { Helmet } from 'umi'; -import { Spin } from '@nocobase/client'; +import { Spin } from '@/components/spin'; import { useRequest, useLocation } from 'umi'; import api from '@/api-client'; -import { Actions } from '../Actions'; +import { Actions } from '@/components/actions'; import { Table as AntdTable, Card, @@ -15,14 +15,13 @@ import { Tooltip, } from 'antd'; import { LoadingOutlined } from '@ant-design/icons'; -import { components, fields2columns } from '@/components/views/SortableTable'; import ReactDragListView from 'react-drag-listview'; import arrayMove from 'array-move'; import get from 'lodash/get'; -import Drawer from '@/components/pages/AdminLoader/Drawer'; +import Drawer from '@/components/drawer'; import Field from '@/components/views/Field'; import { Form } from './Form'; -import { View } from './'; +import { View } from '.'; export function Association(props) { const { schema = {}, ...restProps } = props; diff --git a/packages/app/src/components/views/Calendar/index.tsx b/packages/app/src/components/views/Calendar/index.tsx index 32a847127..45b1b846d 100644 --- a/packages/app/src/components/views/Calendar/index.tsx +++ b/packages/app/src/components/views/Calendar/index.tsx @@ -1,11 +1,7 @@ import React, { useEffect, useRef, useState } from 'react'; import { Table as AntdTable, Card, Pagination } from 'antd'; -import { Actions } from '@/components/actions'; -import { redirectTo } from '@/components/pages/CollectionLoader/utils'; -import ViewFactory from '@/components/views'; -import { useRequest } from 'umi'; +import { useRequest, useHistory } from 'umi'; import api from '@/api-client'; -import { components, fields2columns } from '../SortableTable'; import { LoadingOutlined, LeftOutlined, @@ -16,6 +12,9 @@ import { Calendar as BigCalendar, momentLocalizer } from 'react-big-calendar'; import * as dates from 'react-big-calendar/lib/utils/dates'; import moment from 'moment'; const localizer = momentLocalizer(moment); // or globalizeLocalizer +import Drawer from '@/components/drawer'; +import { Details, DetailsPage } from '../Table'; +import { Actions } from '@/components/actions'; export const icon = ; @@ -52,67 +51,56 @@ function toEvents(data, options: any = {}) { } export function Calendar(props: CalendarProps) { - console.log(props); - const { - activeTab = {}, - pageInfo = {}, - schema, - resourceName, - associatedName, - associatedKey, - isFieldComponent, - onSelected, - multiple = true, - selectedRowKeys: srk, - } = props; + const { schema = {}, associatedKey, defaultFilter } = props; + + const paginated = false; + const { rowKey = 'id', - mode, - defaultTabName, + filter: schemaFilter, + sort, + appends, + resourceName, labelField, startDateField, endDateField, - name: viewName, - actionDefaultParams = {}, - fields = [], - rowViewName, + detailsOpenMode, + details = [], actions = [], - paginated = true, - defaultPerPage = 10, } = schema; - const { filter: defaultFilter = {} } = actionDefaultParams; - const { sourceKey = 'id' } = activeTab.field || {}; - const drawerRef = useRef(); - const [filterCount, setFilterCount] = useState(0); - const name = associatedName - ? `${associatedName}.${resourceName}` - : resourceName; - const { - data, - loading, - pagination, - mutate, - refresh, - params, - run, - } = useRequest( - (params = {}) => { - const { current, pageSize, sorter, filter, ...restParams } = params; + + console.log({ schema }); + + const [calendarView, setCalendarView] = useState('month'); + + const history = useHistory(); + + const { data, loading, mutate, refresh, run, params } = useRequest( + (params = {}, ...args) => { + const { current, pageSize, sorter, filter, ...restParams } = params as any; + console.log('paramsparamsparamsparamsparams', params, args); return api - .resource(name) + .resource(resourceName) .list({ associatedKey, - // page: paginated ? current : 1, - perPage: -1, + page: paginated ? current : 1, + perPage: paginated ? pageSize : -1, sorter, + sort, + 'fields[appends]': appends, // filter, - viewName, - ...actionDefaultParams, + // ...actionDefaultParams, filter: { - and: [defaultFilter, filter].filter( - obj => obj && Object.keys(obj).length, - ), + and: [ + defaultFilter, + schemaFilter, + filter, + // __parent ? { + // collection_name: __parent, + // } : null, + ].filter(obj => obj && Object.keys(obj).length), }, + // ...args2, }) .then(({ data = [], meta = {} }) => { return { @@ -125,31 +113,8 @@ export function Calendar(props: CalendarProps) { }, { paginated, - defaultPageSize: defaultPerPage, }, ); - console.log(schema, data); - const [selectedRowKeys, setSelectedRowKeys] = useState(srk || []); - const onChange = ( - selectedRowKeys: React.ReactText[], - selectedRows: React.ReactText[], - ) => { - setSelectedRowKeys(selectedRowKeys); - onSelected && onSelected(selectedRows); - }; - const [formMode, setFormMode] = useState('update'); - const [calendarView, setCalendarView] = useState('month'); - useEffect(() => { - setSelectedRowKeys(srk); - }, [srk]); - const tableProps: any = {}; - if (actions.length) { - tableProps.rowSelection = { - type: multiple ? 'checkbox' : 'radio', - selectedRowKeys, - onChange, - }; - } const events = toEvents(data?.list, { idField: rowKey, @@ -184,44 +149,26 @@ export function Calendar(props: CalendarProps) { console.log('events', data); return ( - - {/* { - refresh(); - }} +
+ */} - { - refresh(); + actions={actions} + style={{ + position: 'absolute', + left: '157px', + right: '168px', + marginBottom: 14, }} /> { - console.log(event); - if (isFieldComponent) { + onSelectEvent={data => { + console.log({ data }); + if (!detailsOpenMode || !details.length) { return; } - setFormMode('update'); - drawerRef.current.setVisible(true); - drawerRef.current.getData(event[rowKey]); - - if (mode === 'simple') { - drawerRef.current.setVisible(true); - drawerRef.current.getData(event[rowKey]); + if (detailsOpenMode === 'window') { + const paths = history.location.pathname.split('/'); + history.push(`/admin/${paths[2]}/${data[rowKey]}/0`); } else { - redirectTo({ - ...props.match.params, - [activeTab ? 'newItem' : 'lastItem']: { - itemId: event[rowKey] || event.id, - tabName: defaultTabName, + Drawer.open({ + headerStyle: + details.length > 1 + ? { + paddingBottom: 0, + borderBottom: 0, + // paddingTop: 16, + // marginBottom: -4, + } + : {}, + // title: details.length > 1 ? undefined : data[labelField], + title: data.title, + bodyStyle: { + // padding: 0, }, + content: ({ resolve, closeWithConfirm }) => ( +
+
{ + await refresh(); + resolve(); + }} + onValueChange={() => { + closeWithConfirm && closeWithConfirm(true); + }} + onDraft={async () => { + await refresh(); + resolve(); + }} + onReset={resolve} + onDataChange={async () => { + await refresh(); + }} + data={data} + resolve={resolve} + items={details} + /> +
+ ), }); } - // drawerRef.current. }} onRangeChange={range => { console.log({ range }); @@ -290,6 +267,6 @@ export function Calendar(props: CalendarProps) { }} localizer={localizer} /> - +
); } diff --git a/packages/app/src/components/views/Calendar/style.less b/packages/app/src/components/views/Calendar/style.less index 46b1050c1..01fe7d9dc 100644 --- a/packages/app/src/components/views/Calendar/style.less +++ b/packages/app/src/components/views/Calendar/style.less @@ -23,10 +23,12 @@ button.rbc-input::-moz-focus-inner { .rbc-calendar { box-sizing: border-box; - // height: 75vh; display: flex; flex-direction: column; align-items: stretch; + &.view-month { + height: 75vh; + } } .rbc-calendar *, @@ -745,3 +747,25 @@ button.rbc-input::-moz-focus-inner { background-color: #74ad31; pointer-events: none; } + +@media only screen and (max-width: 800px) { + .view-type-calendar .action-buttons { + position: relative !important; + left: 0 !important; + .filter-action-button { + left: 0 !important; + } + } + .rbc-toolbar .rbc-toolbar-label { + position: absolute; + top: 28px; + left: 50%; + transform: translateX(-50%); + } + .rbc-toolbar { + justify-content: space-between !important; + } + .rbc-header { + padding: 4px !important; + } +} diff --git a/packages/app/src/components/pages/AdminLoader/View/Descriptions.tsx b/packages/app/src/components/views/Descriptions.tsx similarity index 93% rename from packages/app/src/components/pages/AdminLoader/View/Descriptions.tsx rename to packages/app/src/components/views/Descriptions.tsx index 454030fa6..60ddf4875 100644 --- a/packages/app/src/components/pages/AdminLoader/View/Descriptions.tsx +++ b/packages/app/src/components/views/Descriptions.tsx @@ -1,10 +1,10 @@ import React, { useRef } from 'react'; import './style.less'; import { Helmet } from 'umi'; -import { Spin } from '@nocobase/client'; +import { Spin } from '@/components/spin'; import { useRequest, useLocation } from 'umi'; import api from '@/api-client'; -import { Actions } from '../Actions'; +import { Actions } from '@/components/actions'; import { Table as AntdTable, Card, @@ -15,11 +15,9 @@ import { Tooltip, } from 'antd'; import { LoadingOutlined } from '@ant-design/icons'; -import { components, fields2columns } from '@/components/views/SortableTable'; -import ReactDragListView from 'react-drag-listview'; import arrayMove from 'array-move'; import get from 'lodash/get'; -import Drawer from '@/components/pages/AdminLoader/Drawer'; +import Drawer from '@/components/drawer'; import Field from '@/components/views/Field'; import { Form } from './Form'; import { configResponsive, useResponsive } from 'ahooks'; diff --git a/packages/app/src/components/views/Details.tsx b/packages/app/src/components/views/Details.tsx deleted file mode 100644 index c923dae57..000000000 --- a/packages/app/src/components/views/Details.tsx +++ /dev/null @@ -1,145 +0,0 @@ -import React from 'react'; -import { Card, Descriptions, Button, Tooltip } from 'antd'; -import { Actions } from '@/components/actions'; -import api from '@/api-client'; -import { useRequest } from 'umi'; -import { Spin } from '@nocobase/client'; -import Field from './Field'; -import get from 'lodash/get'; -import { useSize } from 'ahooks'; -import { configResponsive, useResponsive } from 'ahooks'; -import { InfoCircleOutlined } from '@ant-design/icons'; - -configResponsive({ - small: 0, - middle: 800, - large: 1200, -}); -function toGroups(fields: any[], { displayFields = [] }) { - const groups = []; - let group = { - title: undefined, - tooltip: undefined, - children: [], - }; - fields.forEach(field => { - if ( - Array.isArray(displayFields) && - displayFields.length && - displayFields.indexOf(field.id) === -1 - ) { - return null; - } - if (field.interface === 'description') { - if (group.children.length) { - groups.push(group); - } - group = { - title: field.title, - tooltip: get(field, 'component.tooltip'), - children: [], - }; - } else { - group.children.push(field); - } - }); - if (group.children.length) { - groups.push(group); - } - return groups; -} -export function Details(props: any) { - const dom = document.querySelector('body'); - const responsive = useResponsive(); - console.log('Details.props', props); - - const { - activeTab = {}, - pageInfo = {}, - schema, - resourceName, - associatedName, - associatedKey, - resourceKey, - } = props; - const { actions = [], actionDefaultParams = {}, fields = [] } = props.schema; - const { data = {}, loading, refresh } = useRequest(() => { - const name = associatedName - ? `${associatedName}.${resourceName}` - : resourceName; - return api.resource(name).get({ - resourceKey, - associatedKey, - ...actionDefaultParams, - }); - }); - let descriptionsProps: any = { - size: 'middle', - bordered: true, - }; - if (responsive.small && !responsive.middle && !responsive.large) { - descriptionsProps = { - layout: 'vertical', - }; - } - const { displayFields = [] } = activeTab; - const groups = toGroups(fields, { displayFields }); - console.log({ groups }); - return ( - - { - refresh(); - }} - style={{ marginBottom: 14 }} - actions={actions} - /> - {loading ? ( - - ) : ( - groups.map(group => ( - - {group.title}{' '} - {group.tooltip && ( - - - - )} - - ) - } - column={1} - > - {group.children.map((field: any) => { - if ( - Array.isArray(displayFields) && - displayFields.length && - displayFields.indexOf(field.id) === -1 - ) { - return null; - } - return ( - - - - ); - })} - - )) - )} - - ); -} diff --git a/packages/app/src/components/views/Field/index.tsx b/packages/app/src/components/views/Field/index.tsx index 100304680..8e151df52 100644 --- a/packages/app/src/components/views/Field/index.tsx +++ b/packages/app/src/components/views/Field/index.tsx @@ -5,19 +5,17 @@ import Icon from '@/components/icons'; import get from 'lodash/get'; import isEmpty from 'lodash/isEmpty'; import findIndex from 'lodash/findIndex'; -import { fields2columns } from '../SortableTable'; -import ViewFactory from '..'; -import './style.less'; -import { getImageByUrl, testUrl } from '@/components/form.fields'; +import { getImageByUrl, testUrl } from '@/components/fields'; import { CheckOutlined, CloseOutlined } from '@ant-design/icons'; import marked from 'marked'; import set from 'lodash/set'; import Lightbox from 'react-image-lightbox'; -import 'react-image-lightbox/style.css'; import api from '@/api-client'; import { useRequest } from 'umi'; -import Drawer from '@/components/pages/AdminLoader/Drawer'; -import View from '@/components/pages/AdminLoader/View'; +import Drawer from '@/components/drawer'; +import View from '@/components/views'; +import './style.less'; +import 'react-image-lightbox/style.css'; marked.setOptions({ gfm: true, @@ -293,7 +291,6 @@ export function SubTableField(props: any) { viewName={viewName} type={'subTable'} /> - {/*
*/} ); } @@ -382,24 +379,6 @@ export function LinkToFieldLink(props) { > {data[labelField]} - {/* { - e.stopPropagation(); - }} - className={'noco-drawer'} - bodyStyle={{padding: 0}} - width={'40%'} - title={`查看${title}详情`} - visible={visible} - onClose={() => setVisible(false)} - > - - */} ); } diff --git a/packages/app/src/components/pages/AdminLoader/View/FilterForm.tsx b/packages/app/src/components/views/FilterForm.tsx similarity index 96% rename from packages/app/src/components/pages/AdminLoader/View/FilterForm.tsx rename to packages/app/src/components/views/FilterForm.tsx index 2acd78220..0ac860595 100644 --- a/packages/app/src/components/pages/AdminLoader/View/FilterForm.tsx +++ b/packages/app/src/components/views/FilterForm.tsx @@ -13,7 +13,7 @@ import { setValidationLanguage, } from '@formily/antd'; import { QuestionCircleOutlined } from '@ant-design/icons'; -import scopes from '@/components/views/Form/scopes'; +import scopes from '@/components/views/scopes'; import { fields2properties } from './Form'; export function FilterForm(props: any) { diff --git a/packages/app/src/components/pages/AdminLoader/View/Form.tsx b/packages/app/src/components/views/Form.tsx similarity index 98% rename from packages/app/src/components/pages/AdminLoader/View/Form.tsx rename to packages/app/src/components/views/Form.tsx index 20ab7cad9..32888a252 100644 --- a/packages/app/src/components/pages/AdminLoader/View/Form.tsx +++ b/packages/app/src/components/views/Form.tsx @@ -17,12 +17,12 @@ import { import { QuestionCircleOutlined } from '@ant-design/icons'; import api from '@/api-client'; import { useRequest, useLocation } from 'umi'; -import Drawer from '@/components/pages/AdminLoader/Drawer'; +import Drawer from '@/components/drawer'; import set from 'lodash/set'; import cloneDeep from 'lodash/cloneDeep'; -import { Spin } from '@nocobase/client'; +import { Spin } from '@/components/spin'; import { markdown } from '@/components/views/Field'; -import scopes from '@/components/views/Form/scopes'; +import scopes from '@/components/views/scopes'; export function fields2properties(fields = [], options: any = {}) { const { mode } = options; diff --git a/packages/app/src/components/views/Form/DrawerForm.tsx b/packages/app/src/components/views/Form/DrawerForm.tsx deleted file mode 100644 index 4dae3bd76..000000000 --- a/packages/app/src/components/views/Form/DrawerForm.tsx +++ /dev/null @@ -1,218 +0,0 @@ -import React, { - useState, - useEffect, - useImperativeHandle, - forwardRef, - useRef, - createRef, -} from 'react'; -import { Button, Drawer, Modal } from 'antd'; -import { Tooltip, Input } from 'antd'; -import { - SchemaForm, - SchemaMarkupField as Field, - createFormActions, - createAsyncFormActions, - Submit, - Reset, - FormButtonGroup, - registerFormFields, - FormValidator, - setValidationLanguage, - FormEffectHooks, - FormSpy, - LifeCycleTypes, -} from '@formily/antd'; -import { merge } from '@formily/shared'; -import { QuestionCircleOutlined } from '@ant-design/icons'; -import { useRequest } from 'umi'; -import api from '@/api-client'; -import { Spin } from '@nocobase/client'; -import isEqual from 'lodash/isEqual'; -import isEmpty from 'lodash/isEmpty'; -import get from 'lodash/get'; -import cleanDeep from 'clean-deep'; -import scopes from './scopes'; - -export const DrawerForm = forwardRef((props: any, ref) => { - console.log('DrawerForm', props); - const { - activeTab = {}, - pageInfo = {}, - schema, - resourceName, - associatedName, - associatedKey, - onFinish, - } = props; - const [state, setState] = useState({}); - const [form, setForm] = useState({}); - const [changed, setChanged] = useState(false); - console.log(associatedKey); - const { title, initialValues = {}, actionDefaultParams = {}, fields = {} } = - props.schema || {}; - const [resourceKey, setResourceKey] = useState(props.resourceKey); - const [visible, setVisible] = useState(false); - const name = associatedName - ? `${associatedName}.${resourceName}` - : resourceName; - const { data = {}, run, loading } = useRequest( - resourceKey => { - setResourceKey(resourceKey); - return api.resource(name).get({ - resourceKey, - associatedKey, - ...actionDefaultParams, - }); - }, - { - manual: true, - }, - ); - useImperativeHandle(ref, () => ({ - setVisible, - getData: run, - })); - const { displayFormFields = [] } = activeTab; - const properties: any = {}; - for (const key in fields) { - if (Object.prototype.hasOwnProperty.call(fields, key)) { - const field = fields[key]; - if ( - Array.isArray(displayFormFields) && - displayFormFields.length && - displayFormFields.indexOf(field.id) === -1 - ) { - continue; - } - properties[key] = field; - } - } - return ( - { - if (changed) { - Modal.confirm({ - title: '表单内容发生变化,确定不保存吗?', - onOk() { - setChanged(false); - setVisible(false); - }, - }); - } else { - setChanged(false); - setVisible(false); - } - }} - title={title} - footer={ -
- - - -
- } - > - {loading ? ( - - ) : ( - { - setChanged(true); - }} - onSubmit={async values => { - console.log(values); - console.log('submitsubmitsubmit', values); - if (resourceKey) { - await api.resource(name).update({ - resourceKey, - associatedKey, - values, - }); - } else { - await api.resource(name).create({ - associatedKey, - values, - }); - } - setVisible(false); - setChanged(false); - // @ts-ignore - window.routesReload && window.routesReload(); - onFinish && onFinish(values); - }} - > - { - switch (action.type) { - case LifeCycleTypes.ON_FORM_SUBMIT_START: - return { - ...state, - submitting: true, - }; - case LifeCycleTypes.ON_FORM_SUBMIT_END: - return { - ...state, - submitting: false, - }; - default: - return state; - } - }} - > - {({ state, form }) => { - setState(state); - setForm(form); - return
; - }} - - - )} - - ); -}); diff --git a/packages/app/src/components/views/Form/FilterForm.tsx b/packages/app/src/components/views/Form/FilterForm.tsx deleted file mode 100644 index 1ce63c0e9..000000000 --- a/packages/app/src/components/views/Form/FilterForm.tsx +++ /dev/null @@ -1,49 +0,0 @@ -import React from 'react'; -import { Tooltip, Button } from 'antd'; -import { - SchemaForm, - SchemaMarkupField as Field, - createFormActions, - createAsyncFormActions, - Submit, - Reset, - FormButtonGroup, - registerFormFields, - FormValidator, - setValidationLanguage, -} from '@formily/antd'; -import { QuestionCircleOutlined } from '@ant-design/icons'; -import scopes from './scopes'; - -export function FilterForm(props: any) { - // const actions = createAsyncFormActions(); - const { setVisible, onTrigger } = props; - const { title, fields: properties = {} } = props.schema || {}; - return ( - { - setVisible && setVisible(false); - }} - onSubmit={async values => { - if (onTrigger) { - await onTrigger(values); - } - setVisible && setVisible(false); - }} - schema={{ - type: 'object', - properties, - }} - expressionScope={scopes} - > - - 取消 - 确定 - - - ); -} diff --git a/packages/app/src/components/views/Form/Form.tsx b/packages/app/src/components/views/Form/Form.tsx deleted file mode 100644 index c5ff1e4ce..000000000 --- a/packages/app/src/components/views/Form/Form.tsx +++ /dev/null @@ -1,62 +0,0 @@ -import React from 'react'; -import { Tooltip, Card } from 'antd'; -import { - SchemaForm, - SchemaMarkupField as Field, - createFormActions, - createAsyncFormActions, - Submit, - Reset, - FormButtonGroup, - registerFormFields, - FormValidator, - setValidationLanguage, -} from '@formily/antd'; -import { QuestionCircleOutlined } from '@ant-design/icons'; - -export function Form(props: any) { - const actions = createFormActions(); - - return ( - - - - - ); - }, - }} - > - - - - - - ); -} diff --git a/packages/app/src/components/views/Form/index.tsx b/packages/app/src/components/views/Form/index.tsx deleted file mode 100644 index 603c56678..000000000 --- a/packages/app/src/components/views/Form/index.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import { setup } from '@/components/form.fields'; -import { QuestionCircleOutlined } from '@ant-design/icons'; -import { - SchemaForm, - SchemaMarkupField as Field, - createFormActions, - createAsyncFormActions, - Submit, - Reset, - FormButtonGroup, - registerFormFields, - FormValidator, - setValidationLanguage, -} from '@formily/antd'; -import './style.less'; - -setup(); -setValidationLanguage('zh-CN'); - -export { Form } from './Form'; -export { DrawerForm } from './DrawerForm'; -export { FilterForm } from './FilterForm'; diff --git a/packages/app/src/components/views/Form/style.less b/packages/app/src/components/views/Form/style.less deleted file mode 100644 index efc0b1f2c..000000000 --- a/packages/app/src/components/views/Form/style.less +++ /dev/null @@ -1,22 +0,0 @@ -.users-form { - max-width: 368px; - margin: 0 auto; - padding-top: 100px; - padding: 100px 12px 12px; -} - -.ant-form-item-with-help { - margin-bottom: 24px; -} - -.users-form { - .button-group { - justify-content: flex-start; - } -} - -.ant-radio-wrapper { - p { - display: inline; - } -} diff --git a/packages/app/src/components/pages/AdminLoader/View/Kanban/index.tsx b/packages/app/src/components/views/Kanban/index.tsx similarity index 97% rename from packages/app/src/components/pages/AdminLoader/View/Kanban/index.tsx rename to packages/app/src/components/views/Kanban/index.tsx index 8ffd2f45d..ea53395e6 100644 --- a/packages/app/src/components/pages/AdminLoader/View/Kanban/index.tsx +++ b/packages/app/src/components/views/Kanban/index.tsx @@ -4,15 +4,14 @@ import api from '@/api-client'; import { Descriptions, Popconfirm, Card, Button } from 'antd'; import Board, { moveCard } from '@lourenci/react-kanban'; import '@lourenci/react-kanban/dist/styles.css'; -import { PlusOutlined, CloseOutlined, RightOutlined } from '@ant-design/icons'; -import Drawer from '@/components/pages/AdminLoader/Drawer'; -import { Actions, Create, Destroy } from '../../Actions'; +import Drawer from '@/components/drawer'; +import { Actions, Create, Destroy } from '@/components/actions'; import get from 'lodash/get'; import filter from 'lodash/filter'; import Field from '@/components/views/Field'; -import { Details, DetailsPage } from '../Table'; +import { Details, DetailsPage } from '@/components/views/Table'; import merge from 'lodash/merge'; -import { Spin } from '@nocobase/client'; +import { Spin } from '@/components/spin'; import './style.less'; export function Kanban(props: any) { diff --git a/packages/app/src/components/pages/AdminLoader/View/Kanban/style.less b/packages/app/src/components/views/Kanban/style.less similarity index 100% rename from packages/app/src/components/pages/AdminLoader/View/Kanban/style.less rename to packages/app/src/components/views/Kanban/style.less diff --git a/packages/app/src/components/views/Form/Login.tsx b/packages/app/src/components/views/Login.tsx similarity index 99% rename from packages/app/src/components/views/Form/Login.tsx rename to packages/app/src/components/views/Login.tsx index 1b797224a..5248fb264 100644 --- a/packages/app/src/components/views/Form/Login.tsx +++ b/packages/app/src/components/views/Login.tsx @@ -40,6 +40,7 @@ export function Login(props: any) {

{title || 'NocoBase'}

登录

+ { console.log(values); diff --git a/packages/app/src/components/views/Form/LostPassword.tsx b/packages/app/src/components/views/LostPassword.tsx similarity index 100% rename from packages/app/src/components/views/Form/LostPassword.tsx rename to packages/app/src/components/views/LostPassword.tsx diff --git a/packages/app/src/components/views/Form/Register.tsx b/packages/app/src/components/views/Register.tsx similarity index 100% rename from packages/app/src/components/views/Form/Register.tsx rename to packages/app/src/components/views/Register.tsx diff --git a/packages/app/src/components/views/Form/ResetPassword.tsx b/packages/app/src/components/views/ResetPassword.tsx similarity index 100% rename from packages/app/src/components/views/Form/ResetPassword.tsx rename to packages/app/src/components/views/ResetPassword.tsx diff --git a/packages/app/src/components/views/SimpleTable.tsx b/packages/app/src/components/views/SimpleTable.tsx deleted file mode 100644 index 46449bd1c..000000000 --- a/packages/app/src/components/views/SimpleTable.tsx +++ /dev/null @@ -1,212 +0,0 @@ -import React, { useEffect, useRef, useState } from 'react'; -import { Table as AntdTable, Card, Pagination } from 'antd'; -import { Actions } from '@/components/actions'; -import ViewFactory from '@/components/views'; -import { useRequest } from 'umi'; -import api from '@/api-client'; -import { components, fields2columns } from './SortableTable'; -import { LoadingOutlined } from '@ant-design/icons'; - -export const icon = ; - -export interface SimpleTableProps { - schema?: any; - activeTab?: any; - resourceName: string; - associatedName?: string; - associatedKey?: string; - [key: string]: any; -} - -export function SimpleTable(props: SimpleTableProps) { - console.log(props); - const { - activeTab = {}, - pageInfo = {}, - schema, - resourceName, - associatedName, - associatedKey, - isFieldComponent, - onSelected, - multiple = true, - selectedRowKeys: srk, - } = props; - const { - rowKey = 'id', - name: viewName, - actionDefaultParams = {}, - fields = [], - rowViewName, - actions = [], - paginated = true, - defaultPerPage = 10, - } = schema; - const { filter: defaultFilter = {} } = actionDefaultParams; - const { sourceKey = 'id' } = activeTab.field || {}; - const drawerRef = useRef(); - const [filterCount, setFilterCount] = useState(0); - const name = associatedName - ? `${associatedName}.${resourceName}` - : resourceName; - const { - data, - loading, - pagination, - mutate, - refresh, - params, - run, - } = useRequest( - (params = {}) => { - const { current, pageSize, sorter, filter, ...restParams } = params; - return api - .resource(name) - .list({ - associatedKey, - page: paginated ? current : 1, - perPage: paginated ? pageSize : -1, - sorter, - // filter, - viewName, - ...actionDefaultParams, - filter: { - and: [defaultFilter, filter].filter( - obj => obj && Object.keys(obj).length, - ), - }, - }) - .then(({ data = [], meta = {} }) => { - return { - data: { - list: data, - total: meta.count || data.length, - }, - }; - }); - }, - { - paginated, - defaultPageSize: defaultPerPage, - }, - ); - console.log(schema, data); - const [selectedRowKeys, setSelectedRowKeys] = useState(srk || []); - const onChange = ( - selectedRowKeys: React.ReactText[], - selectedRows: React.ReactText[], - ) => { - setSelectedRowKeys(selectedRowKeys); - onSelected && onSelected(selectedRows); - }; - useEffect(() => { - setSelectedRowKeys(srk); - }, [srk]); - const tableProps: any = {}; - if (actions.length) { - tableProps.rowSelection = { - type: multiple ? 'checkbox' : 'radio', - selectedRowKeys, - onChange, - }; - } - console.log('rowViewName', { rowViewName }); - return ( - - { - refresh(); - }} - onTrigger={{ - async filter(values) { - console.log('filter', values); - const items = values.filter.and || values.filter.or; - setFilterCount(Object.keys(items).length); - // @ts-ignore - run({ ...params[0], filter: values.filter }); - }, - async destroy() { - await api.resource(name).destroy({ - associatedKey, - filter: { - [`${rowKey}.in`]: selectedRowKeys, - }, - }); - await refresh(); - // @ts-ignore - window.routesReload && window.routesReload(); - console.log('destroy.onTrigger', selectedRowKeys); - }, - }} - /> - { - refresh(); - }} - /> - { - run({ ...params[0], sorter }); - }} - components={components({ - data, - mutate, - rowKey, - isFieldComponent, - onMoved: async ({ resourceKey, target }) => { - await api.resource(name).sort({ - associatedKey, - resourceKey, - values: { - field: 'sort', - target, - }, - }); - await refresh(); - console.log({ resourceKey, target }); - }, - })} - onRow={record => ({ - onClick: () => { - if (isFieldComponent) { - return; - } - drawerRef.current.setVisible(true); - drawerRef.current.getData(record[rowKey]); - }, - })} - pagination={false} - {...tableProps} - /> - {paginated && ( -
- `共 ${total} 条记录`} - showQuickJumper - showSizeChanger - size={'small'} - /> -
- )} -
- ); -} diff --git a/packages/app/src/components/views/SortableTable/index.tsx b/packages/app/src/components/views/SortableTable/index.tsx deleted file mode 100644 index 31b4d1f99..000000000 --- a/packages/app/src/components/views/SortableTable/index.tsx +++ /dev/null @@ -1,149 +0,0 @@ -import React from 'react'; -// @ts-ignore -import { - sortableContainer, - sortableElement, - sortableHandle, -} from 'react-sortable-hoc'; -import { MenuOutlined } from '@ant-design/icons'; -import arrayMove from 'array-move'; -import findIndex from 'lodash/findIndex'; -import get from 'lodash/get'; -import './style.less'; -import Field from '../Field'; -import cloneDeep from 'lodash/cloneDeep'; -import { Checkbox, message } from 'antd'; -import api from '@/api-client'; - -export const SortableItem = sortableElement(props =>
); -export const SortableContainer = sortableContainer(props => ( - -)); - -export const DragHandle = sortableHandle(() => ( - -)); - -interface Props { - data: any; - mutate: any; - rowKey: any; - onMoved: any; - isFieldComponent?: boolean; -} - -export const components = ({ - data = {}, - rowKey, - mutate, - onMoved, - isFieldComponent, -}: Props) => { - return { - body: { - wrapper: props => ( - { - if (oldIndex !== newIndex) { - const targetIndex = get(data.list, [newIndex, rowKey]); - const list = arrayMove( - [].concat(data.list), - oldIndex, - newIndex, - ).filter(el => !!el); - console.log({ oldIndex, newIndex, list }); - mutate({ - ...data, - list, - }); - const resourceKey = get(list, [newIndex, rowKey]); - await onMoved({ resourceKey, target: { [rowKey]: targetIndex } }); - // @ts-ignore - window.routesReload && window.routesReload(); - } - }} - {...props} - /> - ), - row: ({ className, style, ...restProps }) => { - // function findIndex base on Table rowKey props and should always be a right array index - const index = findIndex( - data.list, - (x: any) => x[rowKey] === restProps['data-row-key'], - ); - return ( - - ); - }, - }, - }; -}; - -export function fields2columns(fields = [], ctx: any = {}) { - const columns: any[] = fields.map(item => { - const field = cloneDeep(item); - if (!field.dataIndex) { - field.dataIndex = field.name.split('.'); - } - if (['datetime', 'number'].includes(field.interface)) { - field.sorter = true; - } - field.render = (value, record, index) => - field.interface === 'sort' ? ( - - ) : ( - - ); - field.className = `${field.className || ''} noco-field-${field.interface}`; - if (field.editable && field.interface === 'boolean') { - field.title = ( - - { - try { - await api.resource(field.resource).update({ - associatedKey: ctx.associatedKey, - // resourceKey: data.id, - // tableName: data.tableName||'pages', - values: { - accessible: e.target.checked, - }, - }); - message.success('保存成功'); - if (ctx.refresh) { - ctx.refresh(); - } - } catch (error) { - message.error('保存失败'); - } - }} - />{' '} - {field.title} - - ); - } - return { - ...field, - ...(field.component || {}), - }; - }); - return columns; -} diff --git a/packages/app/src/components/views/SortableTable/style.less b/packages/app/src/components/views/SortableTable/style.less deleted file mode 100644 index f3a63c0f9..000000000 --- a/packages/app/src/components/views/SortableTable/style.less +++ /dev/null @@ -1,14 +0,0 @@ -.row-dragging { - background: #fafafa; - border: 1px solid #ccc; - z-index: 99999; -} - -.row-dragging td { - padding: 16px; - visibility: hidden; -} - -.row-dragging .drag-visible { - visibility: visible; -} diff --git a/packages/app/src/components/pages/AdminLoader/View/SubTable.tsx b/packages/app/src/components/views/SubTable.tsx similarity index 96% rename from packages/app/src/components/pages/AdminLoader/View/SubTable.tsx rename to packages/app/src/components/views/SubTable.tsx index 0975f3d5b..70d08fe18 100644 --- a/packages/app/src/components/pages/AdminLoader/View/SubTable.tsx +++ b/packages/app/src/components/views/SubTable.tsx @@ -1,10 +1,10 @@ import React, { useState, useEffect, useRef, createRef } from 'react'; import './style.less'; import { Helmet } from 'umi'; -import { Spin } from '@nocobase/client'; +import { Spin } from '@/components/spin'; import { useRequest, useLocation } from 'umi'; import api from '@/api-client'; -import { Actions } from '../Actions'; +import { Actions } from '@/components/actions'; import { Modal, Table as AntdTable, @@ -16,16 +16,13 @@ import { Tooltip, } from 'antd'; import { LoadingOutlined } from '@ant-design/icons'; -import { components, fields2columns } from '@/components/views/SortableTable'; +import { fields2columns } from '@/components/views/fields2columns'; import ReactDragListView from 'react-drag-listview'; import arrayMove from 'array-move'; import get from 'lodash/get'; import cloneDeep from 'lodash/cloneDeep'; -import some from 'lodash/some'; -import Drawer from '@/components/pages/AdminLoader/Drawer'; -import Field from '@/components/views/Field'; -import { Form } from './Form'; -import { View } from './'; +import Drawer from '@/components/drawer'; +import { View } from '.'; export const icon = ; diff --git a/packages/app/src/components/views/Table.tsx b/packages/app/src/components/views/Table.tsx index b295eeb79..92e82c17c 100644 --- a/packages/app/src/components/views/Table.tsx +++ b/packages/app/src/components/views/Table.tsx @@ -1,59 +1,213 @@ -import React, { useEffect, useState, useRef } from 'react'; -import { Table as AntdTable, Card, Pagination } from 'antd'; -import { redirectTo } from '@/components/pages/CollectionLoader/utils'; -import { Actions } from '@/components/actions'; -import { request, useRequest } from 'umi'; +import React, { useState, useEffect, useRef, createRef } from 'react'; +import './style.less'; +import { Helmet } from 'umi'; +import { Spin } from '@/components/spin'; +import { useRequest, useHistory } from 'umi'; import api from '@/api-client'; -import { components, fields2columns } from './SortableTable'; +import { Actions } from '@/components/actions'; +import { + Modal, + PageHeader, + Table as AntdTable, + Card, + Pagination, + Button, + Tabs, + Descriptions, + Tooltip, +} from 'antd'; import { LoadingOutlined } from '@ant-design/icons'; -import ViewFactory from '@/components/views'; +import { fields2columns } from '@/components/views/fields2columns'; +import ReactDragListView from 'react-drag-listview'; +import get from 'lodash/get'; +import find from 'lodash/find'; +import Drawer from '@/components/drawer'; +import { Form } from './Form'; +import { View } from '.'; export const icon = ; -export interface TableProps { - schema?: any; - activeTab?: any; - resourceName: string; - associatedName?: string; - associatedKey?: string; - [key: string]: any; +export function Details(props) { + const { + __parent, + associatedKey, + resourceName, + onFinish, + onDraft, + onReset, + onDataChange, + data, + items = [], + resolve, + onValueChange, + } = props; + if (!items || items.length === 0) { + return null; + } + const [currentTabIndex, setCurrentTabIndex] = useState('0'); + return ( +
+ {items.length > 1 && ( +
+ { + setCurrentTabIndex(activeKey); + }} + > + {items.map((page, index) => ( + + ))} + +
+ )} + {(get(items, [currentTabIndex, 'views']) || []).map(view => { + let viewName: string; + if (typeof view === 'string') { + viewName = `${resourceName}.${view}`; + } + if (typeof view === 'object') { + viewName = `${resourceName}.${view.name}`; + } + return ( + + ); + })} +
+ ); } -export function Table(props: TableProps) { +export function DetailsPage(props) { const { - activeTab = {}, - schema, - resourceName, - associatedName, + currentRowId, + title, + __parent, associatedKey, - isFieldComponent, + resourceName, + onFinish, + onReset, + onDataChange, + data, + items = [], + resolve, + } = props; + if (!items || items.length === 0) { + return null; + } + const history = useHistory(); + const paths = history.location.pathname.split('/'); + const index = parseInt(paths[4]); + const [currentTabIndex, setCurrentTabIndex] = useState( + items.length > index ? paths[4] : '0', + ); + return ( +
+ { + history.push(`/admin/${paths[2]}`); + }} + footer={ + { + setCurrentTabIndex(activeKey); + history.push(`/admin/${paths[2]}/${currentRowId}/${activeKey}`); + }} + > + {items.map((page, index) => ( + + ))} + + } + /> +
+ + {(get(items, [currentTabIndex, 'views']) || []).map(view => { + let viewName: string; + if (typeof view === 'string') { + viewName = `${resourceName}.${view}`; + } + if (typeof view === 'object') { + viewName = `${resourceName}.${view.name}`; + } + return ( + + ); + })} + +
+
+ ); +} + +export function Table(props: any) { + const { onSelected, multiple = true, - selectedRowKeys: srk, - defaultFilter = {}, + isFieldComponent, + schema = {}, + data: record = {}, + defaultFilter, + defaultSelectedRowKeys, + noRequest = false, + __parent, + currentRowId, } = props; + + const content = document.getElementById('content'); + const { - name: viewName, - mode = 'default', - rowViewName = 'form', - fields, - actionDefaultParams = {}, - defaultTabName, - rowKey = 'id', + fields = [], actions = [], + details = [], paginated = true, defaultPerPage = 10, - disableRowClick, + rowKey = 'id', + labelField = 'id', + sort, + resourceName, + associationField = {}, + appends = [], + expandable, + detailsOpenMode = 'drawer', + filter: schemaFilter = {}, } = schema; - // const { data, mutate } = useRequest(() => api.resource(name).list({ - // associatedKey, - // })); - const { filter: defaultActionFilter = {} } = actionDefaultParams; - const [filterCount, setFilterCount] = useState(0); - const name = associatedName - ? `${associatedName}.${resourceName}` - : resourceName; + const history = useHistory(); + + const associatedKey = + props.associatedKey || record[associationField.sourceKey || 'id']; + console.log({ associatedKey, record, associationField, __parent }); + + async function reloadMenu() { + if (resourceName !== 'menus') { + return; + } + (window as any).reloadMenu && (await (window as any).reloadMenu()); + } + const { data, loading, @@ -64,22 +218,28 @@ export function Table(props: TableProps) { params, } = useRequest( (params = {}, ...args) => { - const { current, pageSize, sorter, filter, ...restParams } = params; + const { current, pageSize, sorter, filter, ...restParams } = params as any; console.log('paramsparamsparamsparamsparams', params, args); return api - .resource(name) + .resource(resourceName) .list({ associatedKey, page: paginated ? current : 1, perPage: paginated ? pageSize : -1, sorter, + sort, + 'fields[appends]': appends, // filter, - viewName, - ...actionDefaultParams, + // ...actionDefaultParams, filter: { - and: [defaultFilter, defaultActionFilter, filter].filter( - obj => obj && Object.keys(obj).length, - ), + and: [ + defaultFilter, + schemaFilter, + filter, + // __parent ? { + // collection_name: __parent, + // } : null, + ].filter(obj => obj && Object.keys(obj).length), }, // ...args2, }) @@ -97,10 +257,76 @@ export function Table(props: TableProps) { defaultPageSize: defaultPerPage, }, ); - const { sourceKey = 'id' } = activeTab.field || {}; - const drawerRef = useRef(); - console.log(props); - const [selectedRowKeys, setSelectedRowKeys] = useState(srk || []); + + const currentRow = find( + data && data.list, + item => item[rowKey] == currentRowId, + ); + console.log({ currentRow }); + function getExpandedRowKeys(items: Array) { + if (!Array.isArray(items)) { + return []; + } + console.log({ items }); + let rowKeys = []; + items.forEach(item => { + if (item.children && item.children.length) { + rowKeys.push(item[rowKey]); + rowKeys = rowKeys.concat(getExpandedRowKeys(item.children)); + } + }); + return rowKeys; + } + + const [expandedRowKeys, setExpandedRowKeys] = useState(() => { + if (expandable) { + return getExpandedRowKeys(data?.list); + } + return []; + }); + + useEffect(() => { + setExpandedRowKeys(getExpandedRowKeys(data?.list)); + }, [data]); + + if (expandable) { + // expandable.expandIconColumnIndex = 4; + expandable.onExpand = (expanded, record) => { + if (!expanded) { + const index = expandedRowKeys.indexOf(record[rowKey]); + if (index >= 0) { + expandedRowKeys.splice(index, 1); + } + } else { + expandedRowKeys.push(record[rowKey]); + } + setExpandedRowKeys(expandedRowKeys); + }; + expandable.expandedRowKeys = expandedRowKeys; + console.log({ expandable, data }); + } + + // const { data, loading, pagination, mutate, refresh, run, params } = useRequest((params = {}, ...args) => { + // const { current, pageSize, sorter, filter, ...restParams } = params; + // return api.resource(resourceName).list({ + // associatedKey, + // sort, + // }).then(({data = [], meta = {}}) => { + // return { + // data: { + // list: data, + // total: meta.count||data.length, + // }, + // }; + // }); + // }, { + // paginated, + // defaultPageSize: defaultPerPage, + // }); + + const [selectedRowKeys, setSelectedRowKeys] = useState( + defaultSelectedRowKeys || [], + ); const onChange = ( selectedRowKeys: React.ReactText[], selectedRows: React.ReactText[], @@ -108,126 +334,250 @@ export function Table(props: TableProps) { setSelectedRowKeys(selectedRowKeys); onSelected && onSelected(selectedRows); }; - useEffect(() => { - setSelectedRowKeys(srk); - }, [srk]); - console.log(srk); + // useEffect(() => { + // setSelectedRowKeys(srk); + // }, [srk]); + // console.log(srk); const tableProps: any = {}; - if (actions.length) { + + if (actions.length || defaultSelectedRowKeys) { tableProps.rowSelection = { type: multiple ? 'checkbox' : 'radio', selectedRowKeys, onChange, }; } + + const ref = createRef(); + + const dragProps = { + async onDragEnd(fromIndex, toIndex) { + const list = data?.list || (data as any); + const nodes = ref.current.querySelectorAll('.ant-table-row'); + const resourceKey = nodes[fromIndex].getAttribute('data-row-key'); + const targetIndex = nodes[toIndex].getAttribute('data-row-key'); + + // const newList = arrayMove(list, fromIndex, toIndex); + // const item = list.splice(fromIndex, 1)[0]; + // list.splice(toIndex, 0, item); + // mutate({ + // ...data, + // list: newList, + // }); + await api.resource(resourceName).sort({ + associatedKey, + resourceKey, + values: { + field: 'sort', + target: { + [rowKey]: targetIndex, + }, + }, + }); + await refresh(); + await reloadMenu(); + + // console.log(nodes[fromIndex].getAttribute('data-row-key'), nodes[toIndex]) + console.log({ + // ref: ref.current.querySelectorAll('.ant-table-row'), + // fromIndex, toIndex, newList, + values: { + field: 'sort', + target: { + [rowKey]: targetIndex, + }, + }, + }); + }, + handleSelector: '.drag-handle', + ignoreSelector: 'tr.ant-table-expanded-row', + nodeSelector: 'tr.ant-table-row', + }; + return ( - - { - refresh(); - }} - onTrigger={{ - async filter(values) { - const items = values.filter.and || values.filter.or; - setFilterCount(Object.keys(items).length); - // @ts-ignore - run({ ...params[0], filter: values.filter }); - console.log('filter', values); - }, - async destroy() { - await api.resource(name).destroy({ - associatedKey, - filter: { - [`${rowKey}.in`]: selectedRowKeys, - }, - }); - await refresh(); - // @ts-ignore - window.routesReload && window.routesReload(); - console.log('destroy.onTrigger', selectedRowKeys); - }, - }} - /> - {mode === 'simple' && ( - { - refresh(); - }} - /> - )} - { - run({ ...params[0], sorter }); - }} - components={components({ - data, - mutate, - rowKey, - isFieldComponent: disableRowClick || isFieldComponent, - onMoved: async ({ resourceKey, target }) => { - await api.resource(name).sort({ - associatedKey, - resourceKey, - values: { - field: 'sort', - target, - }, - }); - await refresh(); - console.log({ resourceKey, target }); - }, - })} - onRow={data => ({ - onClick: () => { - if (disableRowClick || isFieldComponent) { - return; - } - if (mode === 'simple') { - drawerRef.current.setVisible(true); - drawerRef.current.getData(data[rowKey]); - } else { - redirectTo({ - ...props.match.params, - [activeTab ? 'newItem' : 'lastItem']: { - itemId: data[rowKey] || data.id, - tabName: defaultTabName, - }, +
+
+ - {paginated && ( -
- `共 ${total} 条记录`} - showQuickJumper - showSizeChanger - size={'small'} + }, + async update(values) { + await refresh(); + await reloadMenu(); + }, + async filter(values) { + const items = values.filter.and || values.filter.or; + // @ts-ignore + run({ ...params[0], filter: values.filter }); + // refresh(); + }, + async destroy() { + if (selectedRowKeys.length) { + await api.resource(resourceName).destroy({ + associatedKey, + filter: { + [`${rowKey}.in`]: selectedRowKeys, + }, + }); + } + refresh(); + await reloadMenu(); + }, + }} + actions={actions} + style={{ marginBottom: 14 }} + /> + + { + if (!detailsOpenMode || !details.length) { + return
; + } + return ( + + ); + }, + }, + }} + dataSource={data?.list || (data as any)} + size={'middle'} + columns={fields2columns(fields, { associatedKey, refresh })} + pagination={false} + onChange={(pagination, filters, sorter, extra) => { + console.log({sorter}); + run({ ...params[0], sorter }); + }} + expandable={expandable} + onRow={data => ({ + onClick: e => { + const className = (e.target as HTMLElement).className; + console.log({ className }); + if ( + typeof className === 'string' && + (className.includes('ant-table-selection-column') || + className.includes('ant-checkbox') || + className.includes('ant-radio')) + ) { + return; + } + if (!detailsOpenMode || !details.length) { + return; + } + if (!isFieldComponent && detailsOpenMode === 'window') { + const paths = history.location.pathname.split('/'); + history.push(`/admin/${paths[2]}/${data[rowKey]}/0`); + } else { + Drawer.open({ + headerStyle: + details.length > 1 + ? { + paddingBottom: 0, + borderBottom: 0, + // paddingTop: 16, + // marginBottom: -4, + } + : {}, + // title: details.length > 1 ? undefined : data[labelField], + title: data[labelField], + bodyStyle: { + // padding: 0, + }, + content: ({ resolve, closeWithConfirm }) => ( +
+
{ + await refresh(); + resolve(); + await reloadMenu(); + }} + onValueChange={() => { + closeWithConfirm && closeWithConfirm(true); + }} + onDraft={async () => { + await refresh(); + resolve(); + await reloadMenu(); + }} + onReset={resolve} + onDataChange={async () => { + await refresh(); + await reloadMenu(); + }} + data={data} + resolve={resolve} + items={details} + /> +
+ ), + }); + } + }, + })} + {...tableProps} + /> + + {paginated && ( +
+ `共 ${total} 条记录`} + showQuickJumper + showSizeChanger + size={'small'} + /> +
+ )} + + {currentRow && ( +
+ { + await refresh(); + await reloadMenu(); + }} + onReset={() => {}} + onDataChange={async () => { + await refresh(); + await reloadMenu(); + }} + currentRowId={currentRowId} + data={currentRow} + items={details} />
)} - + ); } diff --git a/packages/app/src/components/views/Wysiwyg.tsx b/packages/app/src/components/views/Wysiwyg.tsx new file mode 100644 index 000000000..8c3e2c387 --- /dev/null +++ b/packages/app/src/components/views/Wysiwyg.tsx @@ -0,0 +1,11 @@ +import React, { useState, useEffect } from 'react'; +import './style.less'; +import { markdown } from '@/components/views/Field'; + +export function Wysiwyg(props) { + const { data: record = {}, schema = {}, onDataChange } = props; + + const { html = '' } = schema; + + return
; +} diff --git a/packages/app/src/components/views/fields2columns.tsx b/packages/app/src/components/views/fields2columns.tsx new file mode 100644 index 000000000..775943d07 --- /dev/null +++ b/packages/app/src/components/views/fields2columns.tsx @@ -0,0 +1,71 @@ +import React from 'react'; + +import { MenuOutlined } from '@ant-design/icons'; +import Field from '@/components/views/Field'; +import cloneDeep from 'lodash/cloneDeep'; +import { Checkbox, message } from 'antd'; +import api from '@/api-client'; + +export const DragHandle = () => ( + +); + +export function fields2columns(fields = [], ctx: any = {}) { + const columns: any[] = fields.map(item => { + const field = cloneDeep(item); + if (!field.dataIndex) { + field.dataIndex = field.name.split('.'); + } + if (['datetime', 'number'].includes(field.interface)) { + field.sorter = true; + } + field.render = (value, record, index) => + field.interface === 'sort' ? ( + + ) : ( + + ); + field.className = `${field.className || ''} noco-field-${field.interface}`; + if (field.editable && field.interface === 'boolean') { + field.title = ( + + { + try { + await api.resource(field.resource).update({ + associatedKey: ctx.associatedKey, + // resourceKey: data.id, + // tableName: data.tableName||'pages', + values: { + accessible: e.target.checked, + }, + }); + message.success('保存成功'); + if (ctx.refresh) { + ctx.refresh(); + } + } catch (error) { + message.error('保存失败'); + } + }} + />{' '} + {field.title} + + ); + } + return { + ...field, + ...(field.component || {}), + }; + }); + return columns; +} diff --git a/packages/app/src/components/views/index.tsx b/packages/app/src/components/views/index.tsx index ae5c754e0..56d7594b2 100644 --- a/packages/app/src/components/views/index.tsx +++ b/packages/app/src/components/views/index.tsx @@ -1,85 +1,90 @@ -import React, { useEffect, useState } from 'react'; -import api from '@/api-client'; -import { useRequest } from 'umi'; -import { Spin } from '@nocobase/client'; -import { SimpleTable } from './SimpleTable'; -import { Table } from './Table'; -import { Form, DrawerForm, FilterForm } from './Form/index'; -import { Details } from './Details'; +import React, { useState, useEffect } from 'react'; import './style.less'; -import { Login } from './Form/Login'; -import { Register } from './Form/Register'; -import { Calendar } from './Calendar/index'; +import { Helmet } from 'umi'; +import { Spin } from '@/components/spin'; +import { useRequest, useLocation } from 'umi'; +import api from '@/api-client'; +import { Actions } from '@/components/actions'; +import { + Table as AntdTable, + Card, + Pagination, + Button, + Tabs, + Tooltip, +} from 'antd'; +import { LoadingOutlined } from '@ant-design/icons'; +import { Form } from './Form'; +import { Table } from './Table'; +import { Association } from './Association'; +import { Descriptions } from './Descriptions'; +import { FilterForm } from './FilterForm'; +import { SubTable } from './SubTable'; +import { Wysiwyg } from './Wysiwyg'; +import { Calendar } from './Calendar'; +import { Kanban } from './Kanban'; +import { setValidationLanguage } from '@formily/antd'; +import { setup } from '@/components/fields'; -const TEMPLATES = new Map(); +setup(); +setValidationLanguage('zh-CN'); -export function registerView(template: string, Template: any) { - TEMPLATES.set(template, Template); +const VIEWS = new Map(); + +export function registerView(type, view) { + VIEWS.set(type, view); } -export function getViewTemplate(template: string) { - return TEMPLATES.get(template); +export function getView(type) { + return VIEWS.get(type); } -registerView('Calendar', Calendar); -registerView('FilterForm', FilterForm); -registerView('DrawerForm', DrawerForm); -registerView('PermissionForm', DrawerForm); -registerView('Form', Form); -registerView('Table', Table); -registerView('SimpleTable', Table); -registerView('Details', Details); -registerView('Login', Login); -registerView('Register', Register); +export const icon = ; -export interface ViewProps { - resourceName: string; - resourceKey?: string | number; - associatedName?: string; - associatedKey?: string | number; - viewName?: string; - [key: string]: any; -} +export function View(props: any) { + const { wrapper, schema, viewName, children, ...restProps } = props; -export default function ViewFactory(props: ViewProps) { - const { - associatedName, - associatedKey, - resourceName, - resourceTarget, - resourceKey, - resourceFieldName, - viewName, - mode, - reference, - isAssociationView = false, - } = props; - console.log('propspropspropspropspropspropsprops', props); const { data = {}, loading } = useRequest( () => { - const params = { - resourceKey: viewName, - values: { - resourceKey, - associatedKey: associatedKey, - associatedName: associatedName, - resourceFieldName: resourceName, - mode, - }, - }; - return api.resource(resourceTarget || resourceName).getView(params); + return schema + ? Promise.resolve({ data: schema }) + : api.resource('views_v2').getInfo({ + resourceKey: viewName, + }); }, { - refreshDeps: [associatedName, resourceTarget, resourceName, viewName], + refreshDeps: [viewName, schema], }, ); + if (loading) { return ; } - let { template } = data; - if (isAssociationView && template === 'Table') { - template = 'SimpleTable'; + + const type = props.type || data.type; + + const Component = getView(type); + + if (wrapper === 'card') { + return ( + + + + ) } - const Template = getViewTemplate(template); - return Template &&