@nocobase/plugin-mobile-client 0.10.0-alpha.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/client.d.ts +4 -0
- package/client.js +30 -0
- package/docs/en-US/index.md +7 -0
- package/docs/en-US/installation.md +13 -0
- package/docs/en-US/tabs.json +14 -0
- package/docs/en-US/usage.md +1 -0
- package/docs/zh-CN/index.md +7 -0
- package/docs/zh-CN/installation.md +13 -0
- package/docs/zh-CN/tabs.json +14 -0
- package/docs/zh-CN/usage.md +2 -0
- package/lib/client/configuration/App.d.ts +2 -0
- package/lib/client/configuration/App.js +40 -0
- package/lib/client/configuration/Interface.d.ts +2 -0
- package/lib/client/configuration/Interface.js +20 -0
- package/lib/client/configuration/index.d.ts +2 -0
- package/lib/client/configuration/index.js +27 -0
- package/lib/client/core/bridge/index.d.ts +2 -0
- package/lib/client/core/bridge/index.js +17 -0
- package/lib/client/core/bridge/injects.d.ts +13 -0
- package/lib/client/core/bridge/injects.js +13 -0
- package/lib/client/core/bridge/native-call.d.ts +1 -0
- package/lib/client/core/bridge/native-call.js +24 -0
- package/lib/client/core/index.d.ts +3 -0
- package/lib/client/core/index.js +46 -0
- package/lib/client/core/schema/common/index.d.ts +1 -0
- package/lib/client/core/schema/common/index.js +16 -0
- package/lib/client/core/schema/common/page.d.ts +16 -0
- package/lib/client/core/schema/common/page.js +23 -0
- package/lib/client/core/schema/components/container/Container.Designer.d.ts +2 -0
- package/lib/client/core/schema/components/container/Container.Designer.js +138 -0
- package/lib/client/core/schema/components/container/Container.d.ts +5 -0
- package/lib/client/core/schema/components/container/Container.js +150 -0
- package/lib/client/core/schema/components/container/index.d.ts +1 -0
- package/lib/client/core/schema/components/container/index.js +16 -0
- package/lib/client/core/schema/components/header/Header.Designer.d.ts +2 -0
- package/lib/client/core/schema/components/header/Header.Designer.js +72 -0
- package/lib/client/core/schema/components/header/Header.d.ts +10 -0
- package/lib/client/core/schema/components/header/Header.js +85 -0
- package/lib/client/core/schema/components/header/index.d.ts +1 -0
- package/lib/client/core/schema/components/header/index.js +16 -0
- package/lib/client/core/schema/components/index.d.ts +6 -0
- package/lib/client/core/schema/components/index.js +71 -0
- package/lib/client/core/schema/components/menu/Menu.Designer.d.ts +2 -0
- package/lib/client/core/schema/components/menu/Menu.Designer.js +81 -0
- package/lib/client/core/schema/components/menu/Menu.Item.d.ts +6 -0
- package/lib/client/core/schema/components/menu/Menu.Item.js +129 -0
- package/lib/client/core/schema/components/menu/Menu.d.ts +7 -0
- package/lib/client/core/schema/components/menu/Menu.js +88 -0
- package/lib/client/core/schema/components/menu/MenuBlockInitializer.d.ts +2 -0
- package/lib/client/core/schema/components/menu/MenuBlockInitializer.js +51 -0
- package/lib/client/core/schema/components/menu/index.d.ts +2 -0
- package/lib/client/core/schema/components/menu/index.js +27 -0
- package/lib/client/core/schema/components/menu/schema.d.ts +17 -0
- package/lib/client/core/schema/components/menu/schema.js +24 -0
- package/lib/client/core/schema/components/page/Page.Designer.d.ts +2 -0
- package/lib/client/core/schema/components/page/Page.Designer.js +160 -0
- package/lib/client/core/schema/components/page/Page.d.ts +5 -0
- package/lib/client/core/schema/components/page/Page.js +157 -0
- package/lib/client/core/schema/components/page/index.d.ts +1 -0
- package/lib/client/core/schema/components/page/index.js +16 -0
- package/lib/client/core/schema/components/settings/Settings.Designer.d.ts +2 -0
- package/lib/client/core/schema/components/settings/Settings.Designer.js +37 -0
- package/lib/client/core/schema/components/settings/Settings.d.ts +6 -0
- package/lib/client/core/schema/components/settings/Settings.js +43 -0
- package/lib/client/core/schema/components/settings/SettingsBlockInitializer.d.ts +2 -0
- package/lib/client/core/schema/components/settings/SettingsBlockInitializer.js +51 -0
- package/lib/client/core/schema/components/settings/index.d.ts +2 -0
- package/lib/client/core/schema/components/settings/index.js +27 -0
- package/lib/client/core/schema/components/tab-bar/TabBar.Item.d.ts +6 -0
- package/lib/client/core/schema/components/tab-bar/TabBar.Item.js +80 -0
- package/lib/client/core/schema/components/tab-bar/TabBar.d.ts +6 -0
- package/lib/client/core/schema/components/tab-bar/TabBar.js +138 -0
- package/lib/client/core/schema/components/tab-bar/index.d.ts +1 -0
- package/lib/client/core/schema/components/tab-bar/index.js +16 -0
- package/lib/client/core/schema/components/tab-bar/schema.d.ts +18 -0
- package/lib/client/core/schema/components/tab-bar/schema.js +25 -0
- package/lib/client/core/schema/helpers/index.d.ts +67 -0
- package/lib/client/core/schema/helpers/index.js +49 -0
- package/lib/client/core/schema/hooks/index.d.ts +1 -0
- package/lib/client/core/schema/hooks/index.js +16 -0
- package/lib/client/core/schema/hooks/useSchemaPatch.d.ts +3 -0
- package/lib/client/core/schema/hooks/useSchemaPatch.js +61 -0
- package/lib/client/core/schema/index.d.ts +3 -0
- package/lib/client/core/schema/index.js +38 -0
- package/lib/client/core/schema/initializers/BlockInitializers.d.ts +147 -0
- package/lib/client/core/schema/initializers/BlockInitializers.js +79 -0
- package/lib/client/core/schema/initializers/index.d.ts +1 -0
- package/lib/client/core/schema/initializers/index.js +16 -0
- package/lib/client/core/schema/scopes/grid-card.d.ts +15 -0
- package/lib/client/core/schema/scopes/grid-card.js +45 -0
- package/lib/client/core/schema/scopes/index.d.ts +1 -0
- package/lib/client/core/schema/scopes/index.js +16 -0
- package/lib/client/devices/iOS6.d.ts +5 -0
- package/lib/client/devices/iOS6.js +32 -0
- package/lib/client/devices/index.d.ts +2 -0
- package/lib/client/devices/index.js +43 -0
- package/lib/client/index.d.ts +3 -0
- package/lib/client/index.js +47 -0
- package/lib/client/locale/en-US.d.ts +2 -0
- package/lib/client/locale/en-US.js +9 -0
- package/lib/client/locale/index.d.ts +4 -0
- package/lib/client/locale/index.js +43 -0
- package/lib/client/locale/zh-CN.d.ts +32 -0
- package/lib/client/locale/zh-CN.js +39 -0
- package/lib/client/router/Application.d.ts +3 -0
- package/lib/client/router/Application.js +129 -0
- package/lib/client/router/InterfaceProvider.d.ts +4 -0
- package/lib/client/router/InterfaceProvider.js +29 -0
- package/lib/client/router/InterfaceRouter.d.ts +6 -0
- package/lib/client/router/InterfaceRouter.js +58 -0
- package/lib/client/router/RouteSwitchProvider.d.ts +2 -0
- package/lib/client/router/RouteSwitchProvider.js +59 -0
- package/lib/client/router/index.d.ts +2 -0
- package/lib/client/router/index.js +27 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.js +13 -0
- package/lib/server/index.d.ts +1 -0
- package/lib/server/index.js +13 -0
- package/lib/server/plugin.d.ts +10 -0
- package/lib/server/plugin.js +57 -0
- package/lib/server/routes.d.ts +34 -0
- package/lib/server/routes.js +41 -0
- package/package.json +28 -0
- package/server.d.ts +4 -0
- package/server.js +30 -0
- package/src/client/configuration/App.tsx +23 -0
- package/src/client/configuration/Interface.tsx +11 -0
- package/src/client/configuration/index.ts +2 -0
- package/src/client/core/bridge/index.ts +2 -0
- package/src/client/core/bridge/injects.ts +14 -0
- package/src/client/core/bridge/native-call.ts +23 -0
- package/src/client/core/index.tsx +45 -0
- package/src/client/core/schema/common/index.ts +1 -0
- package/src/client/core/schema/common/page.ts +16 -0
- package/src/client/core/schema/components/container/Container.Designer.tsx +88 -0
- package/src/client/core/schema/components/container/Container.tsx +135 -0
- package/src/client/core/schema/components/container/index.ts +1 -0
- package/src/client/core/schema/components/header/Header.Designer.tsx +39 -0
- package/src/client/core/schema/components/header/Header.tsx +49 -0
- package/src/client/core/schema/components/header/index.ts +1 -0
- package/src/client/core/schema/components/index.ts +6 -0
- package/src/client/core/schema/components/menu/Menu.Designer.tsx +46 -0
- package/src/client/core/schema/components/menu/Menu.Item.tsx +97 -0
- package/src/client/core/schema/components/menu/Menu.tsx +82 -0
- package/src/client/core/schema/components/menu/MenuBlockInitializer.tsx +20 -0
- package/src/client/core/schema/components/menu/index.ts +2 -0
- package/src/client/core/schema/components/menu/schema.ts +17 -0
- package/src/client/core/schema/components/page/Page.Designer.tsx +106 -0
- package/src/client/core/schema/components/page/Page.tsx +132 -0
- package/src/client/core/schema/components/page/index.ts +1 -0
- package/src/client/core/schema/components/settings/Settings.Designer.tsx +22 -0
- package/src/client/core/schema/components/settings/Settings.tsx +25 -0
- package/src/client/core/schema/components/settings/SettingsBlockInitializer.tsx +20 -0
- package/src/client/core/schema/components/settings/index.ts +2 -0
- package/src/client/core/schema/components/tab-bar/TabBar.Item.tsx +67 -0
- package/src/client/core/schema/components/tab-bar/TabBar.tsx +108 -0
- package/src/client/core/schema/components/tab-bar/index.ts +1 -0
- package/src/client/core/schema/components/tab-bar/schema.ts +18 -0
- package/src/client/core/schema/helpers/index.ts +38 -0
- package/src/client/core/schema/hooks/index.ts +1 -0
- package/src/client/core/schema/hooks/useSchemaPatch.ts +24 -0
- package/src/client/core/schema/index.ts +3 -0
- package/src/client/core/schema/initializers/BlockInitializers.ts +81 -0
- package/src/client/core/schema/initializers/index.ts +1 -0
- package/src/client/core/schema/scopes/grid-card.ts +35 -0
- package/src/client/core/schema/scopes/index.ts +1 -0
- package/src/client/devices/iOS6.tsx +24 -0
- package/src/client/devices/index.tsx +27 -0
- package/src/client/index.tsx +33 -0
- package/src/client/locale/en-US.ts +5 -0
- package/src/client/locale/index.ts +23 -0
- package/src/client/locale/zh-CN.ts +33 -0
- package/src/client/router/Application.tsx +114 -0
- package/src/client/router/InterfaceProvider.tsx +11 -0
- package/src/client/router/InterfaceRouter.tsx +48 -0
- package/src/client/router/RouteSwitchProvider.tsx +31 -0
- package/src/client/router/index.ts +2 -0
- package/src/index.ts +1 -0
- package/src/server/collections/.gitkeep +0 -0
- package/src/server/index.ts +1 -0
- package/src/server/plugin.ts +25 -0
- package/src/server/routes.ts +38 -0
- package/types.d.ts +0 -0
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { GeneralSchemaDesigner, SchemaSettings, useDesignable } from '@nocobase/client';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { generateNTemplate, useTranslation } from '../../../../locale';
|
|
4
|
+
import { useField, useFieldSchema } from '@formily/react';
|
|
5
|
+
import { findGridSchema } from '../../helpers';
|
|
6
|
+
import { uid } from '@formily/shared';
|
|
7
|
+
import { Button } from 'antd';
|
|
8
|
+
import { MenuOutlined } from '@ant-design/icons';
|
|
9
|
+
|
|
10
|
+
export const PageDesigner = (props) => {
|
|
11
|
+
const { showBack } = props;
|
|
12
|
+
const { t } = useTranslation();
|
|
13
|
+
const fieldSchema = useFieldSchema();
|
|
14
|
+
const { dn } = useDesignable();
|
|
15
|
+
const headerSchema = fieldSchema?.properties?.['header'];
|
|
16
|
+
const tabsSchema = fieldSchema?.properties?.['tabs'];
|
|
17
|
+
const field = useField();
|
|
18
|
+
const schemaSettingsProps = {
|
|
19
|
+
dn,
|
|
20
|
+
field,
|
|
21
|
+
fieldSchema,
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<SchemaSettings
|
|
26
|
+
title={
|
|
27
|
+
<Button
|
|
28
|
+
style={{
|
|
29
|
+
borderColor: 'rgb(241, 139, 98)',
|
|
30
|
+
color: 'rgb(241, 139, 98)',
|
|
31
|
+
}}
|
|
32
|
+
icon={<MenuOutlined />}
|
|
33
|
+
type="dashed"
|
|
34
|
+
>
|
|
35
|
+
{t('Page configuration')}
|
|
36
|
+
</Button>
|
|
37
|
+
}
|
|
38
|
+
{...schemaSettingsProps}
|
|
39
|
+
>
|
|
40
|
+
<SchemaSettings.SwitchItem
|
|
41
|
+
checked={!!headerSchema}
|
|
42
|
+
title={t('Enable Header')}
|
|
43
|
+
onChange={async (v) => {
|
|
44
|
+
if (v) {
|
|
45
|
+
await dn.insertAfterBegin({
|
|
46
|
+
type: 'void',
|
|
47
|
+
name: 'header',
|
|
48
|
+
'x-component': 'MHeader',
|
|
49
|
+
'x-designer': 'MHeader.Designer',
|
|
50
|
+
'x-component-props': {
|
|
51
|
+
title: fieldSchema.parent['x-component-props']?.name,
|
|
52
|
+
showBack,
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
} else {
|
|
56
|
+
await dn.remove(headerSchema);
|
|
57
|
+
}
|
|
58
|
+
dn.refresh();
|
|
59
|
+
}}
|
|
60
|
+
/>
|
|
61
|
+
<SchemaSettings.SwitchItem
|
|
62
|
+
checked={!!tabsSchema}
|
|
63
|
+
title={t('Enable Tabs')}
|
|
64
|
+
onChange={async (v) => {
|
|
65
|
+
if (v) {
|
|
66
|
+
const gridSchema = findGridSchema(fieldSchema);
|
|
67
|
+
if (gridSchema) {
|
|
68
|
+
return dn.remove(gridSchema).then(() => {
|
|
69
|
+
return dn.insertBeforeEnd({
|
|
70
|
+
type: 'void',
|
|
71
|
+
name: 'tabs',
|
|
72
|
+
'x-component': 'Tabs',
|
|
73
|
+
'x-component-props': {},
|
|
74
|
+
'x-initializer': 'TabPaneInitializers',
|
|
75
|
+
'x-initializer-props': {
|
|
76
|
+
gridInitializer: 'MBlockInitializers',
|
|
77
|
+
},
|
|
78
|
+
properties: {
|
|
79
|
+
tab1: {
|
|
80
|
+
type: 'void',
|
|
81
|
+
title: generateNTemplate('Untitled'),
|
|
82
|
+
'x-component': 'Tabs.TabPane',
|
|
83
|
+
'x-designer': 'Tabs.Designer',
|
|
84
|
+
'x-component-props': {},
|
|
85
|
+
properties: {
|
|
86
|
+
grid: {
|
|
87
|
+
...gridSchema,
|
|
88
|
+
'x-uid': uid(),
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
},
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
} else {
|
|
97
|
+
const gridSchema = findGridSchema(tabsSchema.properties[Object.keys(tabsSchema.properties)[0]]);
|
|
98
|
+
if (gridSchema) {
|
|
99
|
+
return dn.remove(tabsSchema).then(() => dn.insertBeforeEnd(gridSchema, {}));
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}}
|
|
103
|
+
/>
|
|
104
|
+
</SchemaSettings>
|
|
105
|
+
);
|
|
106
|
+
};
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { css, cx } from '@emotion/css';
|
|
2
|
+
import { RecursionField, useFieldSchema } from '@formily/react';
|
|
3
|
+
import { ActionBarProvider, SortableItem, TabsContextProvider, useDesigner } from '@nocobase/client';
|
|
4
|
+
import { TabsProps } from 'antd';
|
|
5
|
+
import React, { useCallback, useMemo } from 'react';
|
|
6
|
+
import { useSearchParams } from 'react-router-dom';
|
|
7
|
+
import { countGridCol } from '../../helpers';
|
|
8
|
+
import { PageDesigner } from './Page.Designer';
|
|
9
|
+
|
|
10
|
+
const globalActionCSS = css`
|
|
11
|
+
#nb-position-container > & {
|
|
12
|
+
height: 49px;
|
|
13
|
+
border-top: 1px solid #f0f2f5;
|
|
14
|
+
margin-bottom: 0px !important;
|
|
15
|
+
padding: 0 var(--nb-spacing);
|
|
16
|
+
align-items: center;
|
|
17
|
+
overflow-x: auto;
|
|
18
|
+
background: #ffffff;
|
|
19
|
+
z-index: 100;
|
|
20
|
+
}
|
|
21
|
+
`;
|
|
22
|
+
|
|
23
|
+
const InternalPage: React.FC = (props) => {
|
|
24
|
+
const Designer = useDesigner();
|
|
25
|
+
const fieldSchema = useFieldSchema();
|
|
26
|
+
const [searchParams, setSearchParams] = useSearchParams();
|
|
27
|
+
const tabsSchema = fieldSchema.properties?.['tabs'];
|
|
28
|
+
// Only support globalActions in page
|
|
29
|
+
const onlyInPage = fieldSchema.root === fieldSchema.parent;
|
|
30
|
+
let hasGlobalActions = false;
|
|
31
|
+
if (!tabsSchema) {
|
|
32
|
+
hasGlobalActions = countGridCol(fieldSchema.properties['grid'], 2) === 1;
|
|
33
|
+
} else if (searchParams.has('tab') && tabsSchema.properties?.[searchParams.get('tab')]) {
|
|
34
|
+
hasGlobalActions = countGridCol(tabsSchema.properties[searchParams.get('tab')]?.properties?.['grid'], 2) === 1;
|
|
35
|
+
} else if (tabsSchema.properties) {
|
|
36
|
+
const schema = Object.values(tabsSchema.properties).sort((t1, t2) => t1['x-index'] - t2['x-index'])[0];
|
|
37
|
+
if (schema) {
|
|
38
|
+
setTimeout(() => {
|
|
39
|
+
setSearchParams([['tab', schema.name.toString()]]);
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const onTabsChange = useCallback<TabsProps['onChange']>(
|
|
45
|
+
(key) => {
|
|
46
|
+
setSearchParams([['tab', key]]);
|
|
47
|
+
},
|
|
48
|
+
[setSearchParams],
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
const GlobalActionProvider = useMemo(() => {
|
|
52
|
+
if (hasGlobalActions) {
|
|
53
|
+
return ActionBarProvider;
|
|
54
|
+
}
|
|
55
|
+
return (props) => <>{props.children}</>;
|
|
56
|
+
}, [hasGlobalActions]);
|
|
57
|
+
|
|
58
|
+
return (
|
|
59
|
+
<GlobalActionProvider
|
|
60
|
+
container={hasGlobalActions && onlyInPage ? document.getElementById('nb-position-container') : null}
|
|
61
|
+
forceProps={{
|
|
62
|
+
layout: 'one-column',
|
|
63
|
+
className: globalActionCSS,
|
|
64
|
+
}}
|
|
65
|
+
>
|
|
66
|
+
<SortableItem
|
|
67
|
+
eid="nb-mobile-scroll-wrapper"
|
|
68
|
+
className={cx(
|
|
69
|
+
'nb-mobile-page',
|
|
70
|
+
css`
|
|
71
|
+
background: #f0f2f5;
|
|
72
|
+
display: flex;
|
|
73
|
+
flex-direction: column;
|
|
74
|
+
width: 100%;
|
|
75
|
+
height: 100%;
|
|
76
|
+
overflow-x: hidden;
|
|
77
|
+
overflow-y: auto;
|
|
78
|
+
padding-bottom: var(--nb-spacing);
|
|
79
|
+
`,
|
|
80
|
+
)}
|
|
81
|
+
>
|
|
82
|
+
<Designer {...fieldSchema?.['x-designer-props']}></Designer>
|
|
83
|
+
<div
|
|
84
|
+
style={{
|
|
85
|
+
paddingBottom: tabsSchema ? null : 'var(--nb-spacing)',
|
|
86
|
+
}}
|
|
87
|
+
className={cx(
|
|
88
|
+
'nb-mobile-page-header',
|
|
89
|
+
css`
|
|
90
|
+
& > .ant-tabs > .ant-tabs-nav {
|
|
91
|
+
background: #fff;
|
|
92
|
+
padding: 0 var(--nb-spacing);
|
|
93
|
+
}
|
|
94
|
+
display: flex;
|
|
95
|
+
flex-direction: column;
|
|
96
|
+
`,
|
|
97
|
+
)}
|
|
98
|
+
>
|
|
99
|
+
<RecursionField
|
|
100
|
+
schema={fieldSchema}
|
|
101
|
+
filterProperties={(s) => {
|
|
102
|
+
return 'MHeader' === s['x-component'];
|
|
103
|
+
}}
|
|
104
|
+
></RecursionField>
|
|
105
|
+
<TabsContextProvider deep={false} activeKey={searchParams.get('tab')} onChange={onTabsChange}>
|
|
106
|
+
<RecursionField
|
|
107
|
+
schema={fieldSchema}
|
|
108
|
+
filterProperties={(s) => {
|
|
109
|
+
return 'Tabs' === s['x-component'];
|
|
110
|
+
}}
|
|
111
|
+
></RecursionField>
|
|
112
|
+
</TabsContextProvider>
|
|
113
|
+
</div>
|
|
114
|
+
|
|
115
|
+
{!tabsSchema && (
|
|
116
|
+
<RecursionField
|
|
117
|
+
schema={fieldSchema}
|
|
118
|
+
filterProperties={(s) => {
|
|
119
|
+
return s['x-component'] !== 'MHeader';
|
|
120
|
+
}}
|
|
121
|
+
></RecursionField>
|
|
122
|
+
)}
|
|
123
|
+
</SortableItem>
|
|
124
|
+
</GlobalActionProvider>
|
|
125
|
+
);
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
export const MPage = InternalPage as unknown as typeof InternalPage & {
|
|
129
|
+
Designer: typeof PageDesigner;
|
|
130
|
+
};
|
|
131
|
+
MPage.Designer = PageDesigner;
|
|
132
|
+
MPage.displayName = 'MPage';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './Page';
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { GeneralSchemaDesigner, SchemaSettings } from '@nocobase/client';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { useTranslation } from '../../../../locale';
|
|
4
|
+
|
|
5
|
+
export const SettingsDesigner = () => {
|
|
6
|
+
const { t } = useTranslation();
|
|
7
|
+
|
|
8
|
+
return (
|
|
9
|
+
<GeneralSchemaDesigner>
|
|
10
|
+
<SchemaSettings.Remove
|
|
11
|
+
key="remove"
|
|
12
|
+
removeParentsIfNoChildren
|
|
13
|
+
confirm={{
|
|
14
|
+
title: t('Delete settings block'),
|
|
15
|
+
}}
|
|
16
|
+
breakRemoveOn={{
|
|
17
|
+
'x-component': 'Grid',
|
|
18
|
+
}}
|
|
19
|
+
/>
|
|
20
|
+
</GeneralSchemaDesigner>
|
|
21
|
+
);
|
|
22
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { SettingsMenu, SortableItem, useDesigner } from '@nocobase/client';
|
|
3
|
+
import { SettingsDesigner } from './Settings.Designer';
|
|
4
|
+
import { css, cx } from '@emotion/css';
|
|
5
|
+
export const InternalSettings = () => {
|
|
6
|
+
const Designer = useDesigner();
|
|
7
|
+
return (
|
|
8
|
+
<SortableItem
|
|
9
|
+
className={cx(
|
|
10
|
+
'nb-mobile-setting',
|
|
11
|
+
css`
|
|
12
|
+
margin-bottom: var(--nb-spacing);
|
|
13
|
+
`,
|
|
14
|
+
)}
|
|
15
|
+
>
|
|
16
|
+
<Designer />
|
|
17
|
+
<SettingsMenu redirectUrl="/mobile" />
|
|
18
|
+
</SortableItem>
|
|
19
|
+
);
|
|
20
|
+
};
|
|
21
|
+
export const MSettings = InternalSettings as unknown as typeof InternalSettings & {
|
|
22
|
+
Designer: typeof SettingsDesigner;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
MSettings.Designer = SettingsDesigner;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { SettingOutlined } from '@ant-design/icons';
|
|
3
|
+
import { SchemaInitializer } from '@nocobase/client';
|
|
4
|
+
|
|
5
|
+
export const MSettingsBlockInitializer = (props) => {
|
|
6
|
+
const { insert } = props;
|
|
7
|
+
return (
|
|
8
|
+
<SchemaInitializer.Item
|
|
9
|
+
icon={<SettingOutlined />}
|
|
10
|
+
onClick={async () => {
|
|
11
|
+
insert({
|
|
12
|
+
type: 'void',
|
|
13
|
+
'x-component': 'MSettings',
|
|
14
|
+
'x-designer': 'MSettings.Designer',
|
|
15
|
+
'x-component-props': {},
|
|
16
|
+
});
|
|
17
|
+
}}
|
|
18
|
+
/>
|
|
19
|
+
);
|
|
20
|
+
};
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import React, { useEffect, useMemo } from 'react';
|
|
2
|
+
import { TabBar, TabBarItemProps } from 'antd-mobile';
|
|
3
|
+
import { GeneralSchemaDesigner, SchemaSettings, SortableItem, useDesigner } from '@nocobase/client';
|
|
4
|
+
import { useTranslation } from '../../../../locale';
|
|
5
|
+
import { Schema, useField, useFieldSchema } from '@formily/react';
|
|
6
|
+
import { useSchemaPatch } from '../../hooks';
|
|
7
|
+
import { css, cx } from '@emotion/css';
|
|
8
|
+
import { tabItemSchema } from './schema';
|
|
9
|
+
|
|
10
|
+
const InternalItem: React.FC<TabBarItemProps> = () => {
|
|
11
|
+
// NOTE: nothing to do
|
|
12
|
+
// return <TabBar.Item {...props}></TabBar.Item>;
|
|
13
|
+
const Designer = useDesigner();
|
|
14
|
+
return (
|
|
15
|
+
<SortableItem
|
|
16
|
+
className={cx(
|
|
17
|
+
'nb-mobile-tab-bar-item',
|
|
18
|
+
css`
|
|
19
|
+
position: absolute !important;
|
|
20
|
+
width: 100%;
|
|
21
|
+
height: 100%;
|
|
22
|
+
top: 0;
|
|
23
|
+
left: 0;
|
|
24
|
+
`,
|
|
25
|
+
)}
|
|
26
|
+
>
|
|
27
|
+
<Designer />
|
|
28
|
+
</SortableItem>
|
|
29
|
+
);
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export const Designer = () => {
|
|
33
|
+
const { t } = useTranslation();
|
|
34
|
+
const fieldSchema = useFieldSchema();
|
|
35
|
+
const { onUpdateComponentProps } = useSchemaPatch();
|
|
36
|
+
const field = useField();
|
|
37
|
+
const tabItems = Object.keys(fieldSchema.parent.properties).length;
|
|
38
|
+
|
|
39
|
+
return (
|
|
40
|
+
<GeneralSchemaDesigner>
|
|
41
|
+
<SchemaSettings.ModalItem
|
|
42
|
+
title={t('Edit info')}
|
|
43
|
+
initialValues={field.componentProps}
|
|
44
|
+
schema={tabItemSchema}
|
|
45
|
+
onSubmit={onUpdateComponentProps}
|
|
46
|
+
></SchemaSettings.ModalItem>
|
|
47
|
+
{tabItems > 1 ? (
|
|
48
|
+
<SchemaSettings.Remove
|
|
49
|
+
key="remove"
|
|
50
|
+
removeParentsIfNoChildren
|
|
51
|
+
confirm={{
|
|
52
|
+
title: t('Delete tab item?'),
|
|
53
|
+
}}
|
|
54
|
+
breakRemoveOn={{
|
|
55
|
+
'x-component': 'MTabBar',
|
|
56
|
+
}}
|
|
57
|
+
></SchemaSettings.Remove>
|
|
58
|
+
) : null}
|
|
59
|
+
</GeneralSchemaDesigner>
|
|
60
|
+
);
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
export const TabBarItem = InternalItem as unknown as typeof InternalItem & {
|
|
64
|
+
Designer: typeof Designer;
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
TabBarItem.Designer = Designer;
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { TabBar } from 'antd-mobile';
|
|
2
|
+
import { TabBarItem } from './TabBar.Item';
|
|
3
|
+
import React, { useCallback } from 'react';
|
|
4
|
+
import { useFieldSchema } from '@formily/react';
|
|
5
|
+
import {
|
|
6
|
+
DndContext,
|
|
7
|
+
Icon,
|
|
8
|
+
SchemaComponent,
|
|
9
|
+
SchemaInitializer,
|
|
10
|
+
SortableItem,
|
|
11
|
+
useCompile,
|
|
12
|
+
useDesignable,
|
|
13
|
+
} from '@nocobase/client';
|
|
14
|
+
import { useTranslation } from '../../../../locale';
|
|
15
|
+
import { css, cx } from '@emotion/css';
|
|
16
|
+
import { uid } from '@formily/shared';
|
|
17
|
+
import { useNavigate, useParams } from 'react-router-dom';
|
|
18
|
+
import { tabItemSchema } from './schema';
|
|
19
|
+
import { PageSchema } from '../../common';
|
|
20
|
+
|
|
21
|
+
export const InternalTabBar: React.FC = (props) => {
|
|
22
|
+
const fieldSchema = useFieldSchema();
|
|
23
|
+
const { designable } = useDesignable();
|
|
24
|
+
const { t } = useTranslation();
|
|
25
|
+
const { insertBeforeEnd } = useDesignable();
|
|
26
|
+
const navigate = useNavigate();
|
|
27
|
+
const params = useParams<{ name: string }>();
|
|
28
|
+
const compile = useCompile();
|
|
29
|
+
|
|
30
|
+
const onAddTab = useCallback((values: any) => {
|
|
31
|
+
return insertBeforeEnd({
|
|
32
|
+
type: 'void',
|
|
33
|
+
'x-component': 'MTabBar.Item',
|
|
34
|
+
'x-component-props': values,
|
|
35
|
+
'x-designer': 'MTabBar.Item.Designer',
|
|
36
|
+
properties: {
|
|
37
|
+
[uid()]: PageSchema,
|
|
38
|
+
},
|
|
39
|
+
});
|
|
40
|
+
}, []);
|
|
41
|
+
|
|
42
|
+
return (
|
|
43
|
+
<SortableItem
|
|
44
|
+
className={cx(
|
|
45
|
+
'nb-mobile-tab-bar',
|
|
46
|
+
css`
|
|
47
|
+
position: relative;
|
|
48
|
+
width: 100%;
|
|
49
|
+
display: flex;
|
|
50
|
+
align-items: center;
|
|
51
|
+
`,
|
|
52
|
+
)}
|
|
53
|
+
>
|
|
54
|
+
<DndContext>
|
|
55
|
+
<TabBar
|
|
56
|
+
activeKey={params.name}
|
|
57
|
+
onChange={(key) => {
|
|
58
|
+
if (key === 'add-tab') {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
navigate(`/mobile/${key}`);
|
|
62
|
+
}}
|
|
63
|
+
safeArea
|
|
64
|
+
className={cx(
|
|
65
|
+
css`
|
|
66
|
+
width: 100%;
|
|
67
|
+
`,
|
|
68
|
+
)}
|
|
69
|
+
>
|
|
70
|
+
{fieldSchema.mapProperties((schema, name) => {
|
|
71
|
+
const cp = schema['x-component-props'];
|
|
72
|
+
return (
|
|
73
|
+
<TabBar.Item
|
|
74
|
+
{...cp}
|
|
75
|
+
key={`tab_${schema['x-uid']}`}
|
|
76
|
+
title={
|
|
77
|
+
<>
|
|
78
|
+
{compile(cp.title)}
|
|
79
|
+
<SchemaComponent schema={schema} name={name} />
|
|
80
|
+
</>
|
|
81
|
+
}
|
|
82
|
+
icon={cp.icon ? <Icon type={cp.icon} /> : undefined}
|
|
83
|
+
></TabBar.Item>
|
|
84
|
+
);
|
|
85
|
+
})}
|
|
86
|
+
{designable && (!fieldSchema.properties || Object.keys(fieldSchema.properties).length < 5) ? (
|
|
87
|
+
<TabBar.Item
|
|
88
|
+
className={css`
|
|
89
|
+
.adm-tab-bar-item-icon {
|
|
90
|
+
height: auto;
|
|
91
|
+
}
|
|
92
|
+
`}
|
|
93
|
+
icon={<SchemaInitializer.ActionModal title={t('Add tab')} onSubmit={onAddTab} schema={tabItemSchema} />}
|
|
94
|
+
key="add-tab"
|
|
95
|
+
></TabBar.Item>
|
|
96
|
+
) : null}
|
|
97
|
+
</TabBar>
|
|
98
|
+
</DndContext>
|
|
99
|
+
</SortableItem>
|
|
100
|
+
);
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
export const MTabBar = InternalTabBar as unknown as typeof InternalTabBar & {
|
|
104
|
+
Item: typeof TabBarItem;
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
MTabBar.Item = TabBarItem;
|
|
108
|
+
MTabBar.displayName = 'MTabBar';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './TabBar';
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export const tabItemSchema = {
|
|
2
|
+
properties: {
|
|
3
|
+
title: {
|
|
4
|
+
type: 'string',
|
|
5
|
+
title: `{{ t('Title') }}`,
|
|
6
|
+
required: true,
|
|
7
|
+
'x-component': 'Input',
|
|
8
|
+
'x-decorator': 'FormItem',
|
|
9
|
+
},
|
|
10
|
+
icon: {
|
|
11
|
+
required: true,
|
|
12
|
+
'x-decorator': 'FormItem',
|
|
13
|
+
'x-component': 'IconPicker',
|
|
14
|
+
title: `{{ t('Icon') }}`,
|
|
15
|
+
'x-component-props': {},
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { ISchema, Schema } from '@formily/react';
|
|
2
|
+
import { uid } from '@formily/shared';
|
|
3
|
+
export const gridItemWrap = (schema: ISchema) => {
|
|
4
|
+
return {
|
|
5
|
+
type: 'void',
|
|
6
|
+
'x-component': 'MGrid.Item',
|
|
7
|
+
properties: {
|
|
8
|
+
[schema.name || uid()]: schema,
|
|
9
|
+
},
|
|
10
|
+
};
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export const findSchema = (schema: Schema, component: string) => {
|
|
14
|
+
const gridSchema = schema.reduceProperties(
|
|
15
|
+
(schema, next) => schema || (next['x-component'] === component && next),
|
|
16
|
+
) as Schema;
|
|
17
|
+
return gridSchema;
|
|
18
|
+
};
|
|
19
|
+
export const findGridSchema = (schema: Schema) => {
|
|
20
|
+
return findSchema(schema, 'Grid');
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const allowComponents = ['Grid', 'Grid.Row'];
|
|
24
|
+
const plusComponent = ['Grid.Col'];
|
|
25
|
+
export const countGridCol = (schema: Schema, countToStop?: number) => {
|
|
26
|
+
if (!schema) return 0;
|
|
27
|
+
let count = 0;
|
|
28
|
+
if (plusComponent.includes(schema['x-component'])) {
|
|
29
|
+
count += 1;
|
|
30
|
+
}
|
|
31
|
+
if (typeof countToStop === 'number' && count >= countToStop) return count;
|
|
32
|
+
if (allowComponents.includes(schema['x-component'])) {
|
|
33
|
+
schema.mapProperties((schema) => {
|
|
34
|
+
count += countGridCol(schema, countToStop);
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
return count;
|
|
38
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './useSchemaPatch';
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { useField, useFieldSchema } from '@formily/react';
|
|
2
|
+
import { useDesignable } from '@nocobase/client';
|
|
3
|
+
import _ from 'lodash';
|
|
4
|
+
import { useCallback } from 'react';
|
|
5
|
+
|
|
6
|
+
export const useSchemaPatch = () => {
|
|
7
|
+
const { dn } = useDesignable();
|
|
8
|
+
const fieldSchema = useFieldSchema();
|
|
9
|
+
const field = useField();
|
|
10
|
+
|
|
11
|
+
const onUpdateComponentProps = useCallback((data) => {
|
|
12
|
+
_.set(fieldSchema, 'x-component-props', data);
|
|
13
|
+
field.componentProps = { ...field.componentProps, ...data };
|
|
14
|
+
dn.emit('patch', {
|
|
15
|
+
schema: {
|
|
16
|
+
['x-uid']: fieldSchema['x-uid'],
|
|
17
|
+
'x-component-props': fieldSchema['x-component-props'],
|
|
18
|
+
},
|
|
19
|
+
});
|
|
20
|
+
dn.refresh();
|
|
21
|
+
}, []);
|
|
22
|
+
|
|
23
|
+
return { onUpdateComponentProps };
|
|
24
|
+
};
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { gridRowColWrap } from '@nocobase/client';
|
|
2
|
+
import { generateNTemplate } from '../../../locale';
|
|
3
|
+
|
|
4
|
+
// 页面里添加区块
|
|
5
|
+
export const MBlockInitializers = {
|
|
6
|
+
title: '{{t("Add block")}}',
|
|
7
|
+
icon: 'PlusOutlined',
|
|
8
|
+
wrap: gridRowColWrap,
|
|
9
|
+
items: [
|
|
10
|
+
{
|
|
11
|
+
key: 'dataBlocks',
|
|
12
|
+
type: 'itemGroup',
|
|
13
|
+
title: '{{t("Data blocks")}}',
|
|
14
|
+
children: [
|
|
15
|
+
{
|
|
16
|
+
key: 'GridCard',
|
|
17
|
+
type: 'item',
|
|
18
|
+
title: '{{t("Grid Card")}}',
|
|
19
|
+
component: 'GridCardBlockInitializer',
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
key: 'table',
|
|
23
|
+
type: 'item',
|
|
24
|
+
title: '{{t("Table")}}',
|
|
25
|
+
component: 'TableBlockInitializer',
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
key: 'form',
|
|
29
|
+
type: 'item',
|
|
30
|
+
title: '{{t("Form")}}',
|
|
31
|
+
component: 'FormBlockInitializer',
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
key: 'details',
|
|
35
|
+
type: 'item',
|
|
36
|
+
title: '{{t("Details")}}',
|
|
37
|
+
component: 'DetailsBlockInitializer',
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
key: 'calendar',
|
|
41
|
+
type: 'item',
|
|
42
|
+
title: '{{t("Calendar")}}',
|
|
43
|
+
component: 'CalendarBlockInitializer',
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
key: 'mapBlock',
|
|
47
|
+
type: 'item',
|
|
48
|
+
title: generateNTemplate('Map'),
|
|
49
|
+
component: 'MapBlockInitializer',
|
|
50
|
+
},
|
|
51
|
+
],
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
key: 'otherBlocks',
|
|
55
|
+
type: 'itemGroup',
|
|
56
|
+
title: '{{t("Other blocks")}}',
|
|
57
|
+
children: [
|
|
58
|
+
{
|
|
59
|
+
key: 'menu',
|
|
60
|
+
type: 'item',
|
|
61
|
+
title: generateNTemplate('Menu'),
|
|
62
|
+
component: 'MMenuBlockInitializer',
|
|
63
|
+
sort: 100,
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
key: 'markdown',
|
|
67
|
+
type: 'item',
|
|
68
|
+
title: '{{t("Markdown")}}',
|
|
69
|
+
component: 'MarkdownBlockInitializer',
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
key: 'settings',
|
|
73
|
+
type: 'item',
|
|
74
|
+
title: generateNTemplate('Settings'),
|
|
75
|
+
component: 'MSettingsBlockInitializer',
|
|
76
|
+
sort: 100,
|
|
77
|
+
},
|
|
78
|
+
],
|
|
79
|
+
},
|
|
80
|
+
],
|
|
81
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './BlockInitializers';
|