Skip to content

Commit 7af1cf7

Browse files
committed
feat: xconsole-context add the rc messenger
1 parent 37cee25 commit 7af1cf7

File tree

12 files changed

+272
-48
lines changed

12 files changed

+272
-48
lines changed

package.json

+3
Original file line numberDiff line numberDiff line change
@@ -32,5 +32,8 @@
3232
"lerna": "^2.11.0",
3333
"prettier": "^2.0.5",
3434
"typescript": "^3.9.3"
35+
},
36+
"dependencies": {
37+
"@alicloud/console-base-rc-messenger-region": "^1.1.2"
3538
}
3639
}

packages/console-utils/xconsole-context/package.json

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@alicloud/xconsole-context",
3-
"version": "2.4.3",
3+
"version": "2.4.11",
44
"main": "lib/index.js",
55
"module": "es/index.js",
66
"types": "lib/index.d.ts",
@@ -20,7 +20,7 @@
2020
"url": "https://github.com/Boelroy"
2121
},
2222
"scripts": {
23-
"prepublish": "npm run clean && npm run babel && npm run babel:esm",
23+
"prepare": "npm run clean && npm run babel && npm run babel:esm",
2424
"babel": "breezr build --engine babel && tsc --emitDeclarationOnly -d true --declarationDir ./lib",
2525
"babel:esm": "breezr build --engine babel --es-module",
2626
"build": "breezr build --engine webpack",
@@ -48,6 +48,8 @@
4848
"react-dom": "^16.8.6"
4949
},
5050
"dependencies": {
51+
"@alicloud/console-base-rc-messenger-region": "^1.1.2",
52+
"@alicloud/console-base-rc-messenger-resource-group": "^1.0.3",
5153
"@alicloud/xconsole-rc-base-link": "^1.0.0-beta.1",
5254
"js-cookie": "^2.2.1",
5355
"lodash": "^4.17.19",

packages/console-utils/xconsole-context/src/console/ConsoleBase.ts

-7
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,6 @@ export const ConsoleBaseBroadcast = {
1414
*/
1515
toggleTopNav(payload: boolean): void {/* void */},
1616

17-
/**
18-
* 打开教程
19-
*/
20-
launchTutorial(payload: IPayloadLaunchTutorial): Promise<void> {
21-
return Promise.resolve();
22-
},
23-
2417
// ------- region ------- //
2518

2619
/**

packages/console-utils/xconsole-context/src/index.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import region from './region/index';
44
export { ConsoleContext } from './context/Context';
55
export { RegionContext } from './context/RegionContext';
66

7-
export { default as withConsoleConfig } from './withConsoleContext';
7+
export { default as withConsoleConfig, withRcBaseMessenger } from './withConsoleContext';
88

99
export default {
1010
consoleConfig,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
import { useEffect, useState, useContext } from 'react';
2+
import { matchPath, generatePath } from 'react-router';
3+
4+
import ConsoleRegion from './index';
5+
import { getActiveId } from './cookies';
6+
import { determineRegionId } from './determineRegionId';
7+
import { RegionContext } from '../context/RegionContext';
8+
import { IConsoleContextRegionProp } from '../types/index';
9+
10+
11+
const hasRegionId = (match) => {
12+
// eslint-disable-next-line no-prototype-builtins
13+
return match.params && match.params.hasOwnProperty('regionId');
14+
}
15+
16+
export const reroute = (props: IConsoleContextRegionProp<{regionId?: string}>, nextRegionId: string) => {
17+
const { history, match, location } = props;
18+
if (match && match.path && hasRegionId(match)) {
19+
const { path, params } = match;
20+
21+
if (nextRegionId === params.regionId) {
22+
return;
23+
}
24+
25+
const nextPath = generatePath(path, {
26+
...(params || {}),
27+
regionId: nextRegionId
28+
});
29+
const suff = location.pathname.slice(match.url.length);
30+
31+
history[props.region?.historyAction || 'push']({
32+
pathname: match.isExact ? nextPath : `${nextPath}/${suff}`.replace('//', '/'),
33+
search: location.search,
34+
hash: location.hash,
35+
});
36+
}
37+
}
38+
39+
/**
40+
* 为了适配新版本的 region, 但是由于
41+
* @param props
42+
* @returns
43+
*/
44+
const useRcRegionProps = (props: IConsoleContextRegionProp<{regionId?: string}>) => {
45+
const { consoleBase, match, location, region: regionConfig = {} } = props;
46+
const { regionList, regionbarVisiblePaths = [], globalVisiblePaths = [] } = regionConfig;
47+
// 默认 Region = 路由的Region > Cookie 的 region > Region 列表中第一个 > 用户指定默认Region >'cn-hangzhou'
48+
const [currentRegionId, setCurrentRegionId] = useState<string>('');
49+
const regionContext = useContext(RegionContext);
50+
51+
// 设置内存变量中的 Id, 也设置设置临时变量中的 ID
52+
const setRegionIdWithMemo = (regionId: string) => {
53+
// @ts-ignore
54+
window.__XCONSOLE_CURRENT_REGION_ID__ = regionId;
55+
56+
// 兼容旧版本的应用
57+
regionContext.setActiveRegionId(regionId);
58+
59+
setCurrentRegionId(regionId);
60+
}
61+
62+
/**
63+
* 处理路由
64+
*/
65+
useEffect(() => {
66+
// 如果 regionId 不在 region 列表重定向到 regionId 上
67+
const regionId = determineRegionId(match.params.regionId, currentRegionId, regionList);
68+
69+
if (currentRegionId !== regionId) {
70+
setRegionIdWithMemo(regionId)
71+
return reroute(props, regionId);
72+
}
73+
}, [match.params.regionId]);
74+
75+
const showGlobal = globalVisiblePaths.some((globalPath) => {
76+
const matches = matchPath(location.pathname, {
77+
path: globalPath,
78+
exact: true,
79+
strict: true,
80+
});
81+
if (matches) {
82+
return true;
83+
}
84+
return false;
85+
})
86+
87+
88+
const onRegionChange = (id: string, regionName: string, correctedFrom?: string) => {
89+
if (correctedFrom) {
90+
return;
91+
}
92+
const regionId = determineRegionId(id, currentRegionId, regionList);
93+
if (regionId !== currentRegionId) {
94+
reroute(props, regionId);
95+
}
96+
}
97+
98+
const regionsVisible = regionbarVisiblePaths.some((showRegionPath) => {
99+
const matches = matchPath(location.pathname, {
100+
path: showRegionPath,
101+
exact: true,
102+
strict: true,
103+
});
104+
return !!matches;
105+
});
106+
107+
return {
108+
global: showGlobal,
109+
regions: regionList,
110+
visible: regionsVisible,
111+
regionId: currentRegionId,
112+
onChange: onRegionChange,
113+
// 为了兼容老版版本提供出去的 region context 的 value
114+
region: {
115+
...(consoleBase || ConsoleRegion),
116+
getCurrentRegionId: (): string => currentRegionId || determineRegionId(match.params.regionId, getActiveId(), regionList),
117+
setCurrentRegionId: setRegionIdWithMemo
118+
}
119+
}
120+
}
121+
122+
export default useRcRegionProps;

packages/console-utils/xconsole-context/src/region/useRegion.ts

+1-28
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { useEffect, useState, useContext } from 'react';
22
import { matchPath, generatePath } from 'react-router';
33

44
import ConsoleRegion from './index';
5+
import { reroute } from './useRcRegionProps';
56
import ConsoleBase from '../console/ConsoleBase';
67
import { IConsoleContextRegionProp } from '../types/index';
78
import { determineRegionId } from './determineRegionId';
@@ -14,34 +15,6 @@ interface Region extends ConsoleRegion {
1415
loading?: boolean;
1516
}
1617

17-
const hasRegionId = (match) => {
18-
// eslint-disable-next-line no-prototype-builtins
19-
return match.params && match.params.hasOwnProperty('regionId');
20-
}
21-
22-
const reroute = (props: IConsoleContextRegionProp<{regionId?: string}>, nextRegionId: string) => {
23-
const { history, match, location } = props;
24-
if (match && match.path && hasRegionId(match)) {
25-
const { path, params } = match;
26-
27-
if (nextRegionId === params.regionId) {
28-
return;
29-
}
30-
31-
const nextPath = generatePath(path, {
32-
...(params || {}),
33-
regionId: nextRegionId
34-
});
35-
const suff = location.pathname.slice(match.url.length);
36-
37-
history.push({
38-
pathname: match.isExact ? nextPath : `${nextPath}/${suff}`.replace('//', '/'),
39-
search: location.search,
40-
hash: location.hash,
41-
});
42-
}
43-
}
44-
4518
/**
4619
* regionbar 相关的交互
4720
* - 发送 region 列表给 regionbar
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import { useEffect, useState } from 'react';
2+
import { History } from 'history'
3+
import qs from 'query-string'
4+
import { IConsoleContextProp } from '../types/index';
5+
import ConsoleResourceGroup, { getCurrentRGId } from '../resourceGroup/index';
6+
import { matchPath } from 'react-router-dom';
7+
8+
const reroute = (history: History, currentRGId: string) => {
9+
const url = new URL(window.location.href);
10+
url.searchParams.delete('resourceGroupId');
11+
url.searchParams.append('resourceGroupId', currentRGId);
12+
history.replace({
13+
pathname: url.pathname,
14+
search: url.search,
15+
hash: url.hash,
16+
});
17+
}
18+
19+
export default (props: IConsoleContextProp<{regionId?: string}>) => {
20+
const { history, consoleBase, location } = props;
21+
const { resourceGroupVisiblePaths = [] } = props.resourceGroup || {};
22+
const searchParam = qs.parse(location.search);
23+
const [currentRGId, setCurrentRGId] = useState<string>(
24+
searchParam.resourceGroupId || getCurrentRGId()
25+
);
26+
27+
const enable = resourceGroupVisiblePaths.some((showRegionPath) => {
28+
const matches = matchPath(location.pathname, {
29+
path: showRegionPath,
30+
exact: true,
31+
strict: true,
32+
});
33+
return !!matches
34+
});
35+
36+
const onChange = (id: string) => {
37+
const url = new URL(window.location.href);
38+
39+
if (!id) {
40+
setCurrentRGId('');
41+
url.searchParams.delete('resourceGroupId');
42+
url.searchParams.append('resourceGroupId', '');
43+
} else {
44+
setCurrentRGId(id);
45+
url.searchParams.delete('resourceGroupId');
46+
url.searchParams.append('resourceGroupId', id);
47+
}
48+
49+
history.push({
50+
pathname: url.pathname,
51+
search: url.search,
52+
hash: url.hash,
53+
});
54+
}
55+
56+
useEffect(() => {
57+
if (currentRGId) {
58+
reroute(history, currentRGId);
59+
}
60+
}, []);
61+
62+
useEffect(() => {
63+
// add presistents for resource group
64+
const unlisten = history.listen((loc) => {
65+
const query = qs.parse(loc.search);
66+
if (enable && query.resourceGroupId === undefined) {
67+
reroute(history, currentRGId);
68+
}
69+
});
70+
71+
return () => {
72+
unlisten();
73+
};
74+
}, [
75+
enable,
76+
history,
77+
currentRGId,
78+
]);
79+
80+
return {
81+
onChange,
82+
visible: enable,
83+
resourceGroupId: currentRGId,
84+
resourceGroup: {
85+
...(consoleBase || ConsoleResourceGroup),
86+
getCurrentResourceGroup: () => currentRGId,
87+
}
88+
};
89+
};

packages/console-utils/xconsole-context/src/types/index.ts

+2
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ export interface RegionConfig {
2323

2424
// 路由匹配到 全球的 展示或者隐藏
2525
globalVisiblePaths?: PathRule;
26+
27+
historyAction?: 'push' | 'replace';
2628
}
2729

2830
export interface IRegionConfigProps extends RegionConfig {

packages/console-utils/xconsole-context/src/withConsoleContext.tsx

+36-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,45 @@
11
import React, { useEffect, useState } from 'react';
22
import isFunction from 'lodash/isFunction'
33
import useRegion from './region/useRegion';
4+
import ConsoleBaseMessengerRegion from '@alicloud/console-base-rc-messenger-region';
5+
import ConsoleBaseMessengerResourceGroup from '@alicloud/console-base-rc-messenger-resource-group';
6+
import useRcRegionProps from './region/useRcRegionProps';
7+
import useRcResourceGroupProps from './resourceGroup/useRcResourceGroupProps';
48
import useResourceGroup from './resourceGroup/useResourceGroup';
59
import consoleConfig from './console/index';
610
import { IConsoleContextProp } from './types/index';
711
import { ConsoleContext } from './context/Context';
812

13+
/**
14+
* 为了实现组件式阿里云吊顶交互的逻辑兼容, 目前 mobile 在使用
15+
* @param Comp
16+
* @returns
17+
*/
18+
export function withRcBaseMessenger<P extends IConsoleContextProp, S = {}>(
19+
Comp: new () => React.Component<P, S>
20+
) {
21+
22+
return (props: P) => {
23+
const regionProps = useRcRegionProps(props as any);
24+
const resourceGroupProps = useRcResourceGroupProps(props);
25+
26+
return (
27+
<>
28+
<ConsoleBaseMessengerRegion {...regionProps}/>
29+
<ConsoleBaseMessengerResourceGroup {...resourceGroupProps} />
30+
<Comp
31+
{...props}
32+
// 这里是为了覆盖 useRegion 中返回的 region, 取代 useRegion 中 ConsoleBase Messenger 的逻辑
33+
// 没办法 sb boshi 做的升级徒增工作量
34+
_injectRegionContextValue={regionProps.region}
35+
_injectResourceGroupContextValue={resourceGroupProps.resourceGroup}
36+
/>
37+
</>
38+
);
39+
}
40+
}
41+
42+
943
/**
1044
* 为了实现异步的逻辑
1145
*/
@@ -43,9 +77,9 @@ const ConsoleContextComponent = withAsyncRegionList(
4377
// @ts-ignore
4478
(props: P) => {
4579
// 初始化 regionbar 逻辑
46-
const region = useRegion(props)
80+
const region = props._injectRegionContextValue ? props._injectRegionContextValue : useRegion(props)
4781
// 初始化 resourceGroup 逻辑
48-
const resourceGroup = useResourceGroup(props);
82+
const resourceGroup = props._injectResourceGroupContextValue ? props._injectResourceGroupContextValue : useResourceGroup(props);
4983

5084
const context = { consoleConfig, region, resourceGroup };
5185

packages/console-utils/xconsole-context/stories/config.js

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)