@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,23 @@
|
|
|
1
|
+
import { invoke } from './injects';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* App 右滑返回
|
|
5
|
+
* @param cb 回调函数,返回 true 表示 web 自己消费,false表示 app 消费
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const JSBridgeFunction = {
|
|
9
|
+
/**
|
|
10
|
+
* @description JSBridge injects
|
|
11
|
+
*/
|
|
12
|
+
onBackPressed: () => {
|
|
13
|
+
if (history.length === 1) {
|
|
14
|
+
invoke({ action: 'moveTaskToBack' });
|
|
15
|
+
} else {
|
|
16
|
+
history.back();
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
Object.keys(JSBridgeFunction).forEach((key) => {
|
|
22
|
+
window[key] = JSBridgeFunction[key];
|
|
23
|
+
});
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { SchemaComponentOptions, SchemaInitializerProvider } from '@nocobase/client';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import {
|
|
4
|
+
MBlockInitializers,
|
|
5
|
+
MMenuBlockInitializer,
|
|
6
|
+
MMenu,
|
|
7
|
+
MContainer,
|
|
8
|
+
MTabBar,
|
|
9
|
+
MPage,
|
|
10
|
+
MHeader,
|
|
11
|
+
MSettingsBlockInitializer,
|
|
12
|
+
MSettings,
|
|
13
|
+
useGridCardBlockItemProps,
|
|
14
|
+
useGridCardBlockProps,
|
|
15
|
+
} from './schema';
|
|
16
|
+
import './bridge';
|
|
17
|
+
|
|
18
|
+
export const MobileCore: React.FC = (props) => {
|
|
19
|
+
return (
|
|
20
|
+
<SchemaInitializerProvider
|
|
21
|
+
initializers={{
|
|
22
|
+
MBlockInitializers,
|
|
23
|
+
}}
|
|
24
|
+
>
|
|
25
|
+
<SchemaComponentOptions
|
|
26
|
+
components={{
|
|
27
|
+
MMenuBlockInitializer,
|
|
28
|
+
MSettingsBlockInitializer,
|
|
29
|
+
MContainer,
|
|
30
|
+
MMenu,
|
|
31
|
+
MTabBar,
|
|
32
|
+
MPage,
|
|
33
|
+
MHeader,
|
|
34
|
+
MSettings,
|
|
35
|
+
}}
|
|
36
|
+
scope={{
|
|
37
|
+
useGridCardBlockItemProps,
|
|
38
|
+
useGridCardBlockProps,
|
|
39
|
+
}}
|
|
40
|
+
>
|
|
41
|
+
{props.children}
|
|
42
|
+
</SchemaComponentOptions>
|
|
43
|
+
</SchemaInitializerProvider>
|
|
44
|
+
);
|
|
45
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './page';
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export const PageSchema = {
|
|
2
|
+
type: 'void',
|
|
3
|
+
'x-component': 'MPage',
|
|
4
|
+
'x-designer': 'MPage.Designer',
|
|
5
|
+
'x-component-props': {},
|
|
6
|
+
properties: {
|
|
7
|
+
grid: {
|
|
8
|
+
type: 'void',
|
|
9
|
+
'x-component': 'Grid',
|
|
10
|
+
'x-initializer': 'MBlockInitializers',
|
|
11
|
+
'x-component-props': {
|
|
12
|
+
showDivider: false,
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
};
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { SchemaSettings, useDesignable } from '@nocobase/client';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { generateNTemplate, useTranslation } from '../../../../locale';
|
|
4
|
+
import { Schema, useField, useFieldSchema } from '@formily/react';
|
|
5
|
+
import { uid } from '@formily/shared';
|
|
6
|
+
import { useNavigate } from 'react-router-dom';
|
|
7
|
+
import { findSchema } from '../../helpers';
|
|
8
|
+
import { Button } from 'antd';
|
|
9
|
+
import { MenuOutlined } from '@ant-design/icons';
|
|
10
|
+
import { PageSchema } from '../../common';
|
|
11
|
+
|
|
12
|
+
export const ContainerDesigner = () => {
|
|
13
|
+
const { t } = useTranslation();
|
|
14
|
+
const fieldSchema = useFieldSchema();
|
|
15
|
+
const { dn } = useDesignable();
|
|
16
|
+
const tabBarSchema = fieldSchema.reduceProperties(
|
|
17
|
+
(schema, next) => schema || (next['x-component'] === 'MTabBar' && next),
|
|
18
|
+
) as Schema;
|
|
19
|
+
|
|
20
|
+
const navigate = useNavigate();
|
|
21
|
+
|
|
22
|
+
const field = useField();
|
|
23
|
+
const schemaSettingsProps = {
|
|
24
|
+
dn,
|
|
25
|
+
field,
|
|
26
|
+
fieldSchema,
|
|
27
|
+
};
|
|
28
|
+
return (
|
|
29
|
+
<SchemaSettings
|
|
30
|
+
title={
|
|
31
|
+
<Button
|
|
32
|
+
style={{
|
|
33
|
+
borderColor: 'rgb(241, 139, 98)',
|
|
34
|
+
color: 'rgb(241, 139, 98)',
|
|
35
|
+
}}
|
|
36
|
+
icon={<MenuOutlined />}
|
|
37
|
+
type="dashed"
|
|
38
|
+
>
|
|
39
|
+
{t('App level Configuration')}
|
|
40
|
+
</Button>
|
|
41
|
+
}
|
|
42
|
+
{...schemaSettingsProps}
|
|
43
|
+
>
|
|
44
|
+
<SchemaSettings.SwitchItem
|
|
45
|
+
checked={!!tabBarSchema}
|
|
46
|
+
title={t('Enable TabBar')}
|
|
47
|
+
onChange={async (v) => {
|
|
48
|
+
if (v) {
|
|
49
|
+
const pageSchema = findSchema(fieldSchema, 'MPage');
|
|
50
|
+
if (!pageSchema) return;
|
|
51
|
+
await dn.remove(pageSchema);
|
|
52
|
+
await dn.insertBeforeEnd({
|
|
53
|
+
type: 'void',
|
|
54
|
+
'x-component': 'MTabBar',
|
|
55
|
+
'x-component-props': {},
|
|
56
|
+
name: 'tabBar',
|
|
57
|
+
properties: {
|
|
58
|
+
[uid()]: {
|
|
59
|
+
type: 'void',
|
|
60
|
+
'x-component': 'MTabBar.Item',
|
|
61
|
+
'x-designer': 'MTabBar.Item.Designer',
|
|
62
|
+
'x-component-props': {
|
|
63
|
+
icon: 'HomeOutlined',
|
|
64
|
+
title: generateNTemplate('Untitled'),
|
|
65
|
+
},
|
|
66
|
+
properties: {
|
|
67
|
+
page: pageSchema.toJSON(),
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
});
|
|
72
|
+
} else {
|
|
73
|
+
const tabBarSchemaFirstKey = Object.keys(tabBarSchema.properties || {})?.[0];
|
|
74
|
+
const pageSchema = tabBarSchemaFirstKey
|
|
75
|
+
? findSchema(tabBarSchema.properties[tabBarSchemaFirstKey], 'MPage')
|
|
76
|
+
: null;
|
|
77
|
+
await dn.remove(tabBarSchema);
|
|
78
|
+
await dn.insertBeforeEnd(pageSchema || PageSchema, {
|
|
79
|
+
onSuccess() {
|
|
80
|
+
navigate('../');
|
|
81
|
+
},
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
}}
|
|
85
|
+
/>
|
|
86
|
+
</SchemaSettings>
|
|
87
|
+
);
|
|
88
|
+
};
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { css, cx } from '@emotion/css';
|
|
2
|
+
import { useFieldSchema } from '@formily/react';
|
|
3
|
+
import { RouteSwitch, SchemaComponent, SortableItem, useDesigner } from '@nocobase/client';
|
|
4
|
+
import React, { useMemo } from 'react';
|
|
5
|
+
import { Navigate, RouteProps, useLocation, useParams } from 'react-router-dom';
|
|
6
|
+
import { ContainerDesigner } from './Container.Designer';
|
|
7
|
+
|
|
8
|
+
const findGrid = (schema, uid) => {
|
|
9
|
+
return schema.reduceProperties((final, next) => {
|
|
10
|
+
if (final) return final;
|
|
11
|
+
if (next['x-component'] === 'MTabBar') {
|
|
12
|
+
return findGrid(next, uid);
|
|
13
|
+
}
|
|
14
|
+
if (next['x-component'] === 'MTabBar.Item' && uid === next['x-uid']) {
|
|
15
|
+
return next;
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const TabContentComponent = () => {
|
|
21
|
+
const { name } = useParams<{ name: string }>();
|
|
22
|
+
const fieldSchema = useFieldSchema();
|
|
23
|
+
if (!name) return <></>;
|
|
24
|
+
const gridSchema = findGrid(fieldSchema.properties['tabBar'], name.replace('tab_', ''));
|
|
25
|
+
if (!gridSchema) {
|
|
26
|
+
return <Navigate replace to="../" />;
|
|
27
|
+
}
|
|
28
|
+
return <SchemaComponent schema={gridSchema} />;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const InternalContainer: React.FC = (props) => {
|
|
32
|
+
const Designer = useDesigner();
|
|
33
|
+
const fieldSchema = useFieldSchema();
|
|
34
|
+
const params = useParams<{ name: string }>();
|
|
35
|
+
const location = useLocation();
|
|
36
|
+
const tabBarSchema = fieldSchema?.properties?.['tabBar'];
|
|
37
|
+
const tabBarCurrentFirstKey = tabBarSchema?.properties ? Object.keys(tabBarSchema.properties)[0] : null;
|
|
38
|
+
let redirectToUid = null;
|
|
39
|
+
if (tabBarCurrentFirstKey) {
|
|
40
|
+
redirectToUid = tabBarSchema?.properties[tabBarCurrentFirstKey]?.['x-uid'];
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const tabRoutes = useMemo<RouteProps[]>(() => {
|
|
44
|
+
if (!redirectToUid) {
|
|
45
|
+
return [];
|
|
46
|
+
}
|
|
47
|
+
const locationPath = location.pathname.endsWith('/') ? location.pathname.slice(0, -1) : location.pathname;
|
|
48
|
+
|
|
49
|
+
return [
|
|
50
|
+
!params.name
|
|
51
|
+
? {
|
|
52
|
+
type: 'redirect',
|
|
53
|
+
to: `${locationPath}/tab_${redirectToUid}`,
|
|
54
|
+
from: location.pathname,
|
|
55
|
+
}
|
|
56
|
+
: null,
|
|
57
|
+
{
|
|
58
|
+
type: 'route',
|
|
59
|
+
path: location.pathname,
|
|
60
|
+
component: TabContentComponent,
|
|
61
|
+
},
|
|
62
|
+
].filter(Boolean) as any[];
|
|
63
|
+
}, [redirectToUid, params.name, location.pathname]);
|
|
64
|
+
|
|
65
|
+
return (
|
|
66
|
+
<SortableItem
|
|
67
|
+
eid="nb-mobile-scroll-wrapper"
|
|
68
|
+
className={cx(
|
|
69
|
+
'nb-mobile-container',
|
|
70
|
+
css`
|
|
71
|
+
& > .general-schema-designer > .general-schema-designer-icons {
|
|
72
|
+
right: unset;
|
|
73
|
+
left: 2px;
|
|
74
|
+
}
|
|
75
|
+
background: #f0f2f5;
|
|
76
|
+
display: flex;
|
|
77
|
+
flex-direction: column;
|
|
78
|
+
width: 100%;
|
|
79
|
+
height: 100%;
|
|
80
|
+
overflow-y: scroll;
|
|
81
|
+
position: initial !important;
|
|
82
|
+
`,
|
|
83
|
+
)}
|
|
84
|
+
>
|
|
85
|
+
<Designer></Designer>
|
|
86
|
+
<div
|
|
87
|
+
style={{
|
|
88
|
+
paddingBottom: tabRoutes.length ? '50px' : '0px',
|
|
89
|
+
}}
|
|
90
|
+
className={cx('nb-mobile-container-content')}
|
|
91
|
+
>
|
|
92
|
+
{tabRoutes.length ? (
|
|
93
|
+
<RouteSwitch routes={tabRoutes as any} />
|
|
94
|
+
) : (
|
|
95
|
+
<SchemaComponent
|
|
96
|
+
filterProperties={(schema) => {
|
|
97
|
+
return schema['x-component'] !== 'MTabBar';
|
|
98
|
+
}}
|
|
99
|
+
schema={fieldSchema}
|
|
100
|
+
/>
|
|
101
|
+
)}
|
|
102
|
+
</div>
|
|
103
|
+
<div
|
|
104
|
+
className={cx(
|
|
105
|
+
'nb-mobile-container-tab-bar',
|
|
106
|
+
css`
|
|
107
|
+
& > .general-schema-designer {
|
|
108
|
+
--nb-designer-top: 20px;
|
|
109
|
+
}
|
|
110
|
+
position: absolute;
|
|
111
|
+
background: #ffffff;
|
|
112
|
+
width: 100%;
|
|
113
|
+
bottom: 0;
|
|
114
|
+
left: 0;
|
|
115
|
+
z-index: 1000;
|
|
116
|
+
`,
|
|
117
|
+
)}
|
|
118
|
+
>
|
|
119
|
+
<SchemaComponent
|
|
120
|
+
onlyRenderProperties
|
|
121
|
+
filterProperties={(schema) => {
|
|
122
|
+
return schema['x-component'] === 'MTabBar';
|
|
123
|
+
}}
|
|
124
|
+
schema={fieldSchema}
|
|
125
|
+
></SchemaComponent>
|
|
126
|
+
</div>
|
|
127
|
+
</SortableItem>
|
|
128
|
+
);
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
export const MContainer = InternalContainer as unknown as typeof InternalContainer & {
|
|
132
|
+
Designer: typeof ContainerDesigner;
|
|
133
|
+
};
|
|
134
|
+
MContainer.Designer = ContainerDesigner;
|
|
135
|
+
MContainer.displayName = 'MContainer';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './Container';
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { Schema, useField, useFieldSchema } from '@formily/react';
|
|
2
|
+
import { GeneralSchemaDesigner, SchemaSettings, useDesignable } from '@nocobase/client';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import { Switch } from '@formily/antd';
|
|
5
|
+
import { useTranslation } from '../../../../locale';
|
|
6
|
+
import { useSchemaPatch } from '../../hooks';
|
|
7
|
+
|
|
8
|
+
export const HeaderDesigner = () => {
|
|
9
|
+
const field = useField();
|
|
10
|
+
const { onUpdateComponentProps } = useSchemaPatch();
|
|
11
|
+
const { t } = useTranslation();
|
|
12
|
+
return (
|
|
13
|
+
<GeneralSchemaDesigner draggable={false}>
|
|
14
|
+
<SchemaSettings.ModalItem
|
|
15
|
+
title={t('Edit info')}
|
|
16
|
+
components={{ Switch }}
|
|
17
|
+
initialValues={field.componentProps}
|
|
18
|
+
schema={{
|
|
19
|
+
properties: {
|
|
20
|
+
title: {
|
|
21
|
+
type: 'string',
|
|
22
|
+
title: t('Title'),
|
|
23
|
+
required: true,
|
|
24
|
+
'x-component': 'Input',
|
|
25
|
+
'x-decorator': 'FormItem',
|
|
26
|
+
},
|
|
27
|
+
showBack: {
|
|
28
|
+
type: 'boolean',
|
|
29
|
+
title: t('Display back button'),
|
|
30
|
+
'x-component': 'Switch',
|
|
31
|
+
'x-decorator': 'FormItem',
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
}}
|
|
35
|
+
onSubmit={onUpdateComponentProps}
|
|
36
|
+
/>
|
|
37
|
+
</GeneralSchemaDesigner>
|
|
38
|
+
);
|
|
39
|
+
};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { css, cx } from '@emotion/css';
|
|
2
|
+
import { SortableItem, useCompile, useDesigner } from '@nocobase/client';
|
|
3
|
+
import { NavBar, NavBarProps } from 'antd-mobile';
|
|
4
|
+
import React, { useEffect } from 'react';
|
|
5
|
+
import { useNavigate } from 'react-router-dom';
|
|
6
|
+
import { HeaderDesigner } from './Header.Designer';
|
|
7
|
+
import { useField } from '@formily/react';
|
|
8
|
+
import { generateNTemplate } from '../../../../locale';
|
|
9
|
+
|
|
10
|
+
export interface HeaderProps extends NavBarProps {
|
|
11
|
+
title?: string;
|
|
12
|
+
showBack?: boolean;
|
|
13
|
+
}
|
|
14
|
+
const InternalHeader = (props: HeaderProps) => {
|
|
15
|
+
const field = useField();
|
|
16
|
+
const { title = generateNTemplate('Untitled'), showBack = false } = { ...props, ...field?.componentProps };
|
|
17
|
+
const Designer = useDesigner();
|
|
18
|
+
const compile = useCompile();
|
|
19
|
+
const compiledTitle = compile(title);
|
|
20
|
+
const navigate = useNavigate();
|
|
21
|
+
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
// sync title
|
|
24
|
+
document.title = `${compiledTitle} - NocoBase`;
|
|
25
|
+
}, [compiledTitle]);
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
<SortableItem
|
|
29
|
+
className={cx(
|
|
30
|
+
'nb-mobile-header',
|
|
31
|
+
css`
|
|
32
|
+
width: 100%;
|
|
33
|
+
background: #fff;
|
|
34
|
+
`,
|
|
35
|
+
)}
|
|
36
|
+
>
|
|
37
|
+
<NavBar backArrow={showBack} onBack={() => navigate(-1)}>
|
|
38
|
+
{compiledTitle}
|
|
39
|
+
</NavBar>
|
|
40
|
+
<Designer />
|
|
41
|
+
</SortableItem>
|
|
42
|
+
);
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export const MHeader = InternalHeader as unknown as typeof InternalHeader & {
|
|
46
|
+
Designer: typeof HeaderDesigner;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
MHeader.Designer = HeaderDesigner;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './Header';
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { GeneralSchemaDesigner, SchemaSettings, useDesignable } from '@nocobase/client';
|
|
2
|
+
import { MenuOutlined } from '@ant-design/icons';
|
|
3
|
+
import React from 'react';
|
|
4
|
+
import { useTranslation } from '../../../../locale';
|
|
5
|
+
import { Button } from 'antd';
|
|
6
|
+
import { useFieldSchema, useField } from '@formily/react';
|
|
7
|
+
|
|
8
|
+
export const MenuDesigner: React.FC = (props) => {
|
|
9
|
+
const { t } = useTranslation();
|
|
10
|
+
const fieldSchema = useFieldSchema();
|
|
11
|
+
const { dn } = useDesignable();
|
|
12
|
+
const field = useField();
|
|
13
|
+
const schemaSettingsProps = {
|
|
14
|
+
dn,
|
|
15
|
+
field,
|
|
16
|
+
fieldSchema,
|
|
17
|
+
};
|
|
18
|
+
return (
|
|
19
|
+
<SchemaSettings
|
|
20
|
+
title={
|
|
21
|
+
<Button
|
|
22
|
+
style={{
|
|
23
|
+
borderColor: 'rgb(241, 139, 98)',
|
|
24
|
+
color: 'rgb(241, 139, 98)',
|
|
25
|
+
}}
|
|
26
|
+
icon={<MenuOutlined />}
|
|
27
|
+
type="dashed"
|
|
28
|
+
>
|
|
29
|
+
{t('Menu configuration')}
|
|
30
|
+
</Button>
|
|
31
|
+
}
|
|
32
|
+
{...schemaSettingsProps}
|
|
33
|
+
>
|
|
34
|
+
<SchemaSettings.Remove
|
|
35
|
+
key="remove"
|
|
36
|
+
removeParentsIfNoChildren
|
|
37
|
+
confirm={{
|
|
38
|
+
title: t('Delete menu block'),
|
|
39
|
+
}}
|
|
40
|
+
breakRemoveOn={{
|
|
41
|
+
'x-component': 'Grid',
|
|
42
|
+
}}
|
|
43
|
+
/>
|
|
44
|
+
</SchemaSettings>
|
|
45
|
+
);
|
|
46
|
+
};
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { css, cx } from '@emotion/css';
|
|
2
|
+
import { useField, useFieldSchema } from '@formily/react';
|
|
3
|
+
import { GeneralSchemaDesigner, Icon, SchemaSettings, SortableItem, useCompile, useDesigner } from '@nocobase/client';
|
|
4
|
+
import { List, ListItemProps } from 'antd-mobile';
|
|
5
|
+
import React from 'react';
|
|
6
|
+
import { useLocation, useNavigate, useParams } from 'react-router-dom';
|
|
7
|
+
import { useTranslation } from '../../../../locale';
|
|
8
|
+
import { useSchemaPatch } from '../../hooks';
|
|
9
|
+
|
|
10
|
+
interface MMenuItemProps extends ListItemProps {
|
|
11
|
+
name: string;
|
|
12
|
+
icon: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const InternalMenuItem: React.FC<MMenuItemProps> = (props) => {
|
|
16
|
+
const { icon, name } = props;
|
|
17
|
+
const Designer = useDesigner();
|
|
18
|
+
const navigate = useNavigate();
|
|
19
|
+
const location = useLocation();
|
|
20
|
+
const fieldSchema = useFieldSchema();
|
|
21
|
+
const compile = useCompile();
|
|
22
|
+
const params = useParams<{ name: string }>();
|
|
23
|
+
|
|
24
|
+
const onToPage = () => {
|
|
25
|
+
const locationPath = location.pathname.endsWith('/') ? location.pathname.slice(0, -1) : location.pathname;
|
|
26
|
+
navigate(params.name ? `/mobile/${fieldSchema['x-uid']}` : `${locationPath}/${fieldSchema['x-uid']}`);
|
|
27
|
+
};
|
|
28
|
+
return (
|
|
29
|
+
<SortableItem
|
|
30
|
+
className={cx(
|
|
31
|
+
'nb-mobile-menu-item',
|
|
32
|
+
css`
|
|
33
|
+
width: 100%;
|
|
34
|
+
background: var(--adm-color-background);
|
|
35
|
+
> .adm-list-item {
|
|
36
|
+
background: inherit;
|
|
37
|
+
}
|
|
38
|
+
`,
|
|
39
|
+
)}
|
|
40
|
+
>
|
|
41
|
+
<List.Item arrow clickable {...props} prefix={<Icon type={icon} />} onClick={onToPage}>
|
|
42
|
+
{compile(name)}
|
|
43
|
+
</List.Item>
|
|
44
|
+
<Designer></Designer>
|
|
45
|
+
</SortableItem>
|
|
46
|
+
);
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
const MenuItemDesigner: React.FC = () => {
|
|
50
|
+
const { t } = useTranslation();
|
|
51
|
+
const { onUpdateComponentProps } = useSchemaPatch();
|
|
52
|
+
const field = useField();
|
|
53
|
+
|
|
54
|
+
return (
|
|
55
|
+
<GeneralSchemaDesigner>
|
|
56
|
+
<SchemaSettings.ModalItem
|
|
57
|
+
title={t('Edit menu info')}
|
|
58
|
+
initialValues={field.componentProps}
|
|
59
|
+
schema={{
|
|
60
|
+
properties: {
|
|
61
|
+
name: {
|
|
62
|
+
type: 'string',
|
|
63
|
+
title: t('Menu name'),
|
|
64
|
+
required: true,
|
|
65
|
+
'x-component': 'Input',
|
|
66
|
+
'x-decorator': 'FormItem',
|
|
67
|
+
},
|
|
68
|
+
icon: {
|
|
69
|
+
required: true,
|
|
70
|
+
'x-decorator': 'FormItem',
|
|
71
|
+
'x-component': 'IconPicker',
|
|
72
|
+
title: t('Icon'),
|
|
73
|
+
'x-component-props': {},
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
}}
|
|
77
|
+
onSubmit={onUpdateComponentProps}
|
|
78
|
+
/>
|
|
79
|
+
<SchemaSettings.Remove
|
|
80
|
+
key="remove"
|
|
81
|
+
removeParentsIfNoChildren
|
|
82
|
+
confirm={{
|
|
83
|
+
title: t('Delete menu item?'),
|
|
84
|
+
}}
|
|
85
|
+
breakRemoveOn={{
|
|
86
|
+
'x-component': 'MMenu',
|
|
87
|
+
}}
|
|
88
|
+
/>
|
|
89
|
+
</GeneralSchemaDesigner>
|
|
90
|
+
);
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
export const MenuItem = InternalMenuItem as typeof InternalMenuItem as unknown as {
|
|
94
|
+
Designer: typeof MenuItemDesigner;
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
MenuItem.Designer = MenuItemDesigner;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { MenuItem } from './Menu.Item';
|
|
3
|
+
import {
|
|
4
|
+
DndContext,
|
|
5
|
+
SchemaComponent,
|
|
6
|
+
SchemaInitializer,
|
|
7
|
+
SortableItem,
|
|
8
|
+
useDesignable,
|
|
9
|
+
useDesigner,
|
|
10
|
+
} from '@nocobase/client';
|
|
11
|
+
import { css, cx } from '@emotion/css';
|
|
12
|
+
import { MenuDesigner } from './Menu.Designer';
|
|
13
|
+
import { useFieldSchema } from '@formily/react';
|
|
14
|
+
import { List } from 'antd-mobile';
|
|
15
|
+
import { useTranslation } from '../../../../locale';
|
|
16
|
+
import { menuItemSchema } from './schema';
|
|
17
|
+
import { PageSchema } from '../../common';
|
|
18
|
+
|
|
19
|
+
const InternalMenu: React.FC = (props) => {
|
|
20
|
+
const Designer = useDesigner();
|
|
21
|
+
const fieldSchema = useFieldSchema();
|
|
22
|
+
const { insertBeforeEnd, designable } = useDesignable();
|
|
23
|
+
|
|
24
|
+
const { t } = useTranslation();
|
|
25
|
+
|
|
26
|
+
const onAddMenuItem = (values: any) => {
|
|
27
|
+
const properties = {
|
|
28
|
+
page: PageSchema,
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
return insertBeforeEnd({
|
|
32
|
+
type: 'void',
|
|
33
|
+
title: values.name,
|
|
34
|
+
'x-component': 'MMenu.Item',
|
|
35
|
+
'x-component-props': values,
|
|
36
|
+
'x-designer': 'MMenu.Item.Designer',
|
|
37
|
+
properties,
|
|
38
|
+
});
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
return (
|
|
42
|
+
<SortableItem
|
|
43
|
+
className={cx(
|
|
44
|
+
'nb-mobile-menu',
|
|
45
|
+
css`
|
|
46
|
+
background: #ffffff;
|
|
47
|
+
width: 100%;
|
|
48
|
+
margin-bottom: var(--nb-spacing);
|
|
49
|
+
`,
|
|
50
|
+
)}
|
|
51
|
+
>
|
|
52
|
+
<List>
|
|
53
|
+
{designable && (
|
|
54
|
+
<List.Item>
|
|
55
|
+
<Designer />
|
|
56
|
+
</List.Item>
|
|
57
|
+
)}
|
|
58
|
+
<DndContext>
|
|
59
|
+
<SchemaComponent onlyRenderProperties schema={fieldSchema}></SchemaComponent>
|
|
60
|
+
</DndContext>
|
|
61
|
+
{designable ? (
|
|
62
|
+
<List.Item>
|
|
63
|
+
<SchemaInitializer.ActionModal
|
|
64
|
+
buttonText={t('Add menu item')}
|
|
65
|
+
title={t('Add menu item')}
|
|
66
|
+
schema={menuItemSchema}
|
|
67
|
+
onSubmit={onAddMenuItem}
|
|
68
|
+
/>
|
|
69
|
+
</List.Item>
|
|
70
|
+
) : null}
|
|
71
|
+
</List>
|
|
72
|
+
</SortableItem>
|
|
73
|
+
);
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
export const MMenu = InternalMenu as unknown as typeof InternalMenu & {
|
|
77
|
+
Item: typeof MenuItem;
|
|
78
|
+
Designer: typeof MenuDesigner;
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
MMenu.Item = MenuItem;
|
|
82
|
+
MMenu.Designer = MenuDesigner;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { MenuOutlined } from '@ant-design/icons';
|
|
3
|
+
import { SchemaInitializer } from '@nocobase/client';
|
|
4
|
+
|
|
5
|
+
export const MMenuBlockInitializer = (props) => {
|
|
6
|
+
const { insert } = props;
|
|
7
|
+
return (
|
|
8
|
+
<SchemaInitializer.Item
|
|
9
|
+
icon={<MenuOutlined />}
|
|
10
|
+
onClick={async () => {
|
|
11
|
+
insert({
|
|
12
|
+
type: 'void',
|
|
13
|
+
'x-component': 'MMenu',
|
|
14
|
+
'x-designer': 'MMenu.Designer',
|
|
15
|
+
'x-component-props': {},
|
|
16
|
+
});
|
|
17
|
+
}}
|
|
18
|
+
/>
|
|
19
|
+
);
|
|
20
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export const menuItemSchema = {
|
|
2
|
+
properties: {
|
|
3
|
+
name: {
|
|
4
|
+
type: 'string',
|
|
5
|
+
title: `{{t('Menu name')}}`,
|
|
6
|
+
required: true,
|
|
7
|
+
'x-component': 'Input',
|
|
8
|
+
'x-decorator': 'FormItem',
|
|
9
|
+
},
|
|
10
|
+
icon: {
|
|
11
|
+
'x-decorator': 'FormItem',
|
|
12
|
+
'x-component': 'IconPicker',
|
|
13
|
+
title: `{{t('Icon')}}`,
|
|
14
|
+
'x-component-props': {},
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
};
|