@qlover/create-app 0.7.5 → 0.7.6
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/CHANGELOG.md +20 -0
- package/dist/index.cjs +1 -1
- package/dist/index.js +1 -1
- package/dist/templates/react-app/.env.template +0 -2
- package/dist/templates/react-app/__tests__/src/base/services/I18nService.test.ts +1 -1
- package/dist/templates/react-app/__tests__/src/core/IOC.test.ts +6 -31
- package/dist/templates/react-app/__tests__/src/core/bootstraps/BootstrapsApp.test.ts +1 -1
- package/dist/templates/react-app/config/IOCIdentifier.ts +77 -5
- package/dist/templates/react-app/config/app.router.ts +2 -2
- package/dist/templates/react-app/package.json +4 -7
- package/dist/templates/react-app/public/locales/en/common.json +1 -1
- package/dist/templates/react-app/public/locales/zh/common.json +1 -1
- package/dist/templates/react-app/src/App.tsx +9 -4
- package/dist/templates/react-app/src/base/apis/userApi/UserApi.ts +1 -1
- package/dist/templates/react-app/src/base/apis/userApi/UserApiBootstarp.ts +4 -0
- package/dist/templates/react-app/src/base/cases/DialogHandler.ts +16 -13
- package/dist/templates/react-app/src/base/cases/I18nKeyErrorPlugin.ts +4 -3
- package/dist/templates/react-app/src/base/cases/InversifyContainer.ts +2 -2
- package/dist/templates/react-app/src/base/cases/RequestLanguages.ts +39 -0
- package/dist/templates/react-app/src/base/cases/RequestState.ts +20 -0
- package/dist/templates/react-app/src/base/cases/RequestStatusCatcher.ts +2 -2
- package/dist/templates/react-app/src/base/cases/RouterLoader.ts +8 -2
- package/dist/templates/react-app/src/base/port/AsyncStateInterface.ts +7 -0
- package/dist/templates/react-app/src/base/port/ExecutorPageBridgeInterface.ts +24 -0
- package/dist/templates/react-app/src/base/port/I18nServiceInterface.ts +10 -0
- package/dist/templates/react-app/src/base/port/JSONStoragePageBridgeInterface.ts +20 -0
- package/dist/templates/react-app/src/base/port/ProcesserExecutorInterface.ts +20 -0
- package/dist/templates/react-app/src/base/port/RequestPageBridgeInterface.ts +23 -0
- package/dist/templates/react-app/src/base/port/RequestStatusInterface.ts +5 -0
- package/dist/templates/react-app/src/base/port/RouteServiceInterface.ts +27 -0
- package/dist/templates/react-app/src/base/port/UserServiceInterface.ts +12 -0
- package/dist/templates/react-app/src/base/services/I18nService.ts +10 -6
- package/dist/templates/react-app/src/base/services/ProcesserExecutor.ts +23 -5
- package/dist/templates/react-app/src/base/services/RouteService.ts +25 -54
- package/dist/templates/react-app/src/base/services/UserService.ts +10 -20
- package/dist/templates/react-app/src/core/IOC.ts +1 -26
- package/dist/templates/react-app/src/core/IocRegisterImpl.ts +125 -0
- package/dist/templates/react-app/src/core/bootstraps/BootstrapApp.ts +4 -6
- package/dist/templates/react-app/src/core/bootstraps/BootstrapsRegistry.ts +8 -6
- package/dist/templates/react-app/src/core/bootstraps/IocIdentifierTest.ts +26 -0
- package/dist/templates/react-app/src/pages/auth/Layout.tsx +2 -2
- package/dist/templates/react-app/src/pages/auth/LoginPage.tsx +5 -6
- package/dist/templates/react-app/src/pages/auth/RegisterPage.tsx +8 -7
- package/dist/templates/react-app/src/pages/base/ExecutorPage.tsx +8 -19
- package/dist/templates/react-app/src/pages/base/{ErrorIdentifierPage.tsx → IdentifierPage.tsx} +1 -1
- package/dist/templates/react-app/src/pages/base/JSONStoragePage.tsx +11 -15
- package/dist/templates/react-app/src/pages/base/Layout.tsx +1 -1
- package/dist/templates/react-app/src/pages/base/RedirectPathname.tsx +2 -2
- package/dist/templates/react-app/src/pages/base/RequestPage.tsx +34 -46
- package/dist/templates/react-app/src/styles/css/antd-themes/_default.css +2 -2
- package/dist/templates/react-app/src/styles/css/antd-themes/dark.css +2 -2
- package/dist/templates/react-app/src/styles/css/antd-themes/pink.css +2 -2
- package/dist/templates/react-app/src/styles/css/index.css +1 -0
- package/dist/templates/react-app/src/styles/css/page.css +8 -0
- package/dist/templates/react-app/src/styles/css/zIndex.css +9 -0
- package/dist/templates/react-app/src/uikit/{controllers/ExecutorController.ts → bridges/ExecutorPageBridge.ts} +13 -36
- package/dist/templates/react-app/src/uikit/bridges/JSONStoragePageBridge.ts +41 -0
- package/dist/templates/react-app/src/uikit/bridges/NavigateBridge.ts +16 -0
- package/dist/templates/react-app/src/uikit/bridges/RequestPageBridge.ts +136 -0
- package/dist/templates/react-app/src/uikit/components/LanguageSwitcher.tsx +3 -2
- package/dist/templates/react-app/src/uikit/components/LogoutButton.tsx +2 -2
- package/dist/templates/react-app/src/uikit/{providers → components}/ProcessExecutorProvider.tsx +4 -4
- package/dist/templates/react-app/src/uikit/components/RouterRenderComponent.tsx +1 -1
- package/dist/templates/react-app/src/uikit/components/ThemeSwitcher.tsx +3 -5
- package/dist/templates/react-app/src/uikit/{providers → components}/UserAuthProvider.tsx +3 -3
- package/dist/templates/react-app/src/uikit/hooks/useI18nGuard.ts +5 -2
- package/dist/templates/react-app/src/uikit/hooks/{userRouterService.ts → useNavigateBridge.ts} +3 -3
- package/dist/templates/react-app/src/uikit/hooks/useStore.ts +5 -2
- package/dist/templates/react-app/tsconfig.json +1 -4
- package/package.json +1 -1
- package/dist/templates/react-app/src/base/port/InteractionHubInterface.ts +0 -94
- package/dist/templates/react-app/src/base/port/UIDependenciesInterface.ts +0 -37
- package/dist/templates/react-app/src/core/registers/IocRegisterImpl.ts +0 -25
- package/dist/templates/react-app/src/core/registers/RegisterCommon.ts +0 -74
- package/dist/templates/react-app/src/core/registers/RegisterControllers.ts +0 -26
- package/dist/templates/react-app/src/core/registers/RegisterGlobals.ts +0 -30
- package/dist/templates/react-app/src/uikit/controllers/JSONStorageController.ts +0 -49
- package/dist/templates/react-app/src/uikit/controllers/RequestController.ts +0 -158
- /package/dist/templates/react-app/src/uikit/{providers → components}/BaseRouteProvider.tsx +0 -0
|
@@ -7,16 +7,13 @@ import {
|
|
|
7
7
|
} from '@qlover/fe-corekit';
|
|
8
8
|
import { inject, injectable } from 'inversify';
|
|
9
9
|
import {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
} from '
|
|
10
|
+
ExecutorPageBridgeInterface,
|
|
11
|
+
ExecutorPageStateInterface
|
|
12
|
+
} from '@/base/port/ExecutorPageBridgeInterface';
|
|
13
|
+
import { RequestState } from '@/base/cases/RequestState';
|
|
13
14
|
|
|
14
|
-
class
|
|
15
|
-
helloState =
|
|
16
|
-
loading: false,
|
|
17
|
-
result: null as Record<string, unknown> | null,
|
|
18
|
-
error: null as unknown
|
|
19
|
-
};
|
|
15
|
+
class ExecutorPageBridgeState implements ExecutorPageStateInterface {
|
|
16
|
+
helloState = new RequestState();
|
|
20
17
|
}
|
|
21
18
|
|
|
22
19
|
const TestPlugin: ExecutorPlugin<RequestAdapterFetchConfig> = {
|
|
@@ -34,13 +31,9 @@ const TestPlugin: ExecutorPlugin<RequestAdapterFetchConfig> = {
|
|
|
34
31
|
};
|
|
35
32
|
|
|
36
33
|
@injectable()
|
|
37
|
-
export class
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
constructor(@inject(FeApi) private feApi: FeApi) {
|
|
43
|
-
super(ExecutorController.create);
|
|
34
|
+
export class ExecutorPageBridge extends ExecutorPageBridgeInterface {
|
|
35
|
+
constructor(@inject(FeApi) protected feApi: FeApi) {
|
|
36
|
+
super(() => new ExecutorPageBridgeState());
|
|
44
37
|
|
|
45
38
|
// FIXME: not cloneDeep, create a new instance
|
|
46
39
|
this.feApi = cloneDeep(feApi);
|
|
@@ -48,18 +41,10 @@ export class ExecutorController extends StoreInterface<ExecutorControllerState>
|
|
|
48
41
|
this.feApi.usePlugin(TestPlugin);
|
|
49
42
|
}
|
|
50
43
|
|
|
51
|
-
|
|
52
|
-
return new ExecutorControllerState();
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
onTestPlugins = async () => {
|
|
44
|
+
override onTestPlugins = async () => {
|
|
56
45
|
this.emit({
|
|
57
46
|
...this.state,
|
|
58
|
-
helloState:
|
|
59
|
-
loading: true,
|
|
60
|
-
result: null,
|
|
61
|
-
error: null
|
|
62
|
-
}
|
|
47
|
+
helloState: new RequestState(true)
|
|
63
48
|
});
|
|
64
49
|
|
|
65
50
|
try {
|
|
@@ -69,20 +54,12 @@ export class ExecutorController extends StoreInterface<ExecutorControllerState>
|
|
|
69
54
|
|
|
70
55
|
this.emit({
|
|
71
56
|
...this.state,
|
|
72
|
-
helloState:
|
|
73
|
-
loading: false,
|
|
74
|
-
result: res,
|
|
75
|
-
error: null
|
|
76
|
-
}
|
|
57
|
+
helloState: new RequestState(false, res).end()
|
|
77
58
|
});
|
|
78
59
|
} catch (error) {
|
|
79
60
|
this.emit({
|
|
80
61
|
...this.state,
|
|
81
|
-
helloState:
|
|
82
|
-
loading: false,
|
|
83
|
-
result: null,
|
|
84
|
-
error
|
|
85
|
-
}
|
|
62
|
+
helloState: new RequestState(false, null, error).end()
|
|
86
63
|
});
|
|
87
64
|
}
|
|
88
65
|
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { inject, injectable } from 'inversify';
|
|
2
|
+
import { JSONStoragePageBridgeInterface } from '@/base/port/JSONStoragePageBridgeInterface';
|
|
3
|
+
import { IOCIdentifier } from '@config/IOCIdentifier';
|
|
4
|
+
import type { SyncStorageInterface } from '@qlover/fe-corekit';
|
|
5
|
+
import random from 'lodash/random';
|
|
6
|
+
|
|
7
|
+
@injectable()
|
|
8
|
+
export class JSONStoragePageBridge extends JSONStoragePageBridgeInterface {
|
|
9
|
+
constructor(
|
|
10
|
+
@inject(IOCIdentifier.LocalStorage)
|
|
11
|
+
protected storage: SyncStorageInterface<string, unknown>
|
|
12
|
+
) {
|
|
13
|
+
super(() => ({
|
|
14
|
+
testKey1: storage.getItem('testKey1') ?? 0,
|
|
15
|
+
testKey2: storage.getItem('testKey2') ?? 0,
|
|
16
|
+
expireTime: 5000,
|
|
17
|
+
requestTimeout: storage.getItem('requestTimeout') ?? 5000
|
|
18
|
+
}));
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
override changeRandomTestKey1 = (): void => {
|
|
22
|
+
const value = random(100, 9000);
|
|
23
|
+
this.storage.setItem('testKey1', value);
|
|
24
|
+
this.emit({ ...this.state, testKey1: value });
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
override onChangeRandomTestKey2 = (): void => {
|
|
28
|
+
const value = random(100, 9000);
|
|
29
|
+
this.storage.setItem('testKey2', value, Date.now() + this.state.expireTime);
|
|
30
|
+
this.emit({ ...this.state, testKey2: value });
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
override changeExpireTime = (expireTime: number): void => {
|
|
34
|
+
this.emit({ ...this.state, expireTime });
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
override changeRequestTimeout = (requestTimeout: number): void => {
|
|
38
|
+
this.storage.setItem('requestTimeout', requestTimeout);
|
|
39
|
+
this.emit({ ...this.state, requestTimeout });
|
|
40
|
+
};
|
|
41
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { injectable } from 'inversify';
|
|
2
|
+
import { UIBridgeInterface } from '@qlover/corekit-bridge';
|
|
3
|
+
import { NavigateFunction } from 'react-router-dom';
|
|
4
|
+
|
|
5
|
+
@injectable()
|
|
6
|
+
export class NavigateBridge implements UIBridgeInterface<NavigateFunction> {
|
|
7
|
+
protected navigate: NavigateFunction | null = null;
|
|
8
|
+
|
|
9
|
+
setUIBridge(ui: NavigateFunction): void {
|
|
10
|
+
this.navigate = ui;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
getUIBridge(): NavigateFunction | null {
|
|
14
|
+
return this.navigate;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { inject, injectable } from 'inversify';
|
|
2
|
+
import { FeApi } from '@/base/apis/feApi/FeApi';
|
|
3
|
+
import { UserApi } from '@/base/apis/userApi/UserApi';
|
|
4
|
+
import { aiHello } from '@/base/apis/AiApi';
|
|
5
|
+
import {
|
|
6
|
+
RequestPageBridgeInterface,
|
|
7
|
+
RequestPageStateInterface
|
|
8
|
+
} from '@/base/port/RequestPageBridgeInterface';
|
|
9
|
+
import { RequestState } from '@/base/cases/RequestState';
|
|
10
|
+
import { IOCIdentifier } from '@config/IOCIdentifier';
|
|
11
|
+
import type { LoggerInterface } from '@qlover/logger';
|
|
12
|
+
|
|
13
|
+
function createDefaultState(): RequestPageStateInterface {
|
|
14
|
+
return {
|
|
15
|
+
helloState: new RequestState(),
|
|
16
|
+
ipInfoState: new RequestState(),
|
|
17
|
+
randomUserState: new RequestState(),
|
|
18
|
+
abortState: new RequestState(),
|
|
19
|
+
apiCatchResultState: new RequestState()
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export type RequestControllerState = ReturnType<typeof createDefaultState>;
|
|
24
|
+
|
|
25
|
+
@injectable()
|
|
26
|
+
export class RequestPageBridge extends RequestPageBridgeInterface {
|
|
27
|
+
constructor(
|
|
28
|
+
@inject(FeApi) protected feApi: FeApi,
|
|
29
|
+
@inject(UserApi) protected userApi: UserApi,
|
|
30
|
+
@inject(IOCIdentifier.Logger) protected logger: LoggerInterface
|
|
31
|
+
) {
|
|
32
|
+
super(createDefaultState);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
override onHello = async () => {
|
|
36
|
+
if (this.state.helloState.loading) {
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
this.emitState({ helloState: new RequestState(true) });
|
|
41
|
+
|
|
42
|
+
try {
|
|
43
|
+
const result = await aiHello({
|
|
44
|
+
messages: [{ role: 'user', content: 'Hello, world!' }]
|
|
45
|
+
});
|
|
46
|
+
this.emitState({ helloState: new RequestState(false, result).end() });
|
|
47
|
+
} catch (error) {
|
|
48
|
+
this.logger.error(error);
|
|
49
|
+
this.emitState({
|
|
50
|
+
helloState: new RequestState(false, null, error).end()
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
override onIpInfo = async () => {
|
|
56
|
+
if (this.state.ipInfoState.loading) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
this.emitState({ ipInfoState: new RequestState(true) });
|
|
61
|
+
|
|
62
|
+
try {
|
|
63
|
+
const result = await this.feApi.getIpInfo();
|
|
64
|
+
this.emitState({ ipInfoState: new RequestState(false, result).end() });
|
|
65
|
+
} catch (error) {
|
|
66
|
+
this.logger.error(error);
|
|
67
|
+
this.emitState({
|
|
68
|
+
ipInfoState: new RequestState(false, null, error).end()
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
override onRandomUser = async () => {
|
|
74
|
+
if (this.state.randomUserState.loading) {
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
this.emitState({ randomUserState: new RequestState(true) });
|
|
79
|
+
try {
|
|
80
|
+
const result = await this.userApi.getRandomUser();
|
|
81
|
+
this.emitState({
|
|
82
|
+
randomUserState: new RequestState(false, result).end()
|
|
83
|
+
});
|
|
84
|
+
} catch (error) {
|
|
85
|
+
this.logger.error(error);
|
|
86
|
+
this.emitState({
|
|
87
|
+
randomUserState: new RequestState(false, null, error).end()
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
override onTriggerApiCatchResult = async () => {
|
|
93
|
+
if (this.state.apiCatchResultState.loading) {
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
this.emitState({ apiCatchResultState: new RequestState(true) });
|
|
98
|
+
try {
|
|
99
|
+
const result = await this.userApi.testApiCatchResult();
|
|
100
|
+
this.emitState({
|
|
101
|
+
apiCatchResultState: new RequestState(false, result).end()
|
|
102
|
+
});
|
|
103
|
+
} catch (error) {
|
|
104
|
+
this.emitState({
|
|
105
|
+
apiCatchResultState: new RequestState(false, null, error).end()
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
override onTriggerAbortRequest = async () => {
|
|
111
|
+
if (this.state.abortState.loading) {
|
|
112
|
+
this.stopAbortRequest();
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
this.emitState({ abortState: new RequestState(true) });
|
|
117
|
+
try {
|
|
118
|
+
await this.userApi.request({
|
|
119
|
+
method: 'GET',
|
|
120
|
+
url: 'https://api.example.com/users',
|
|
121
|
+
disabledMock: true,
|
|
122
|
+
requestId: 'onTriggerAbortRequest'
|
|
123
|
+
});
|
|
124
|
+
} catch (error) {
|
|
125
|
+
this.emitState({
|
|
126
|
+
abortState: new RequestState(false, null, error).end()
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
override stopAbortRequest = async () => {
|
|
132
|
+
this.userApi.stop({
|
|
133
|
+
requestId: 'onTriggerAbortRequest'
|
|
134
|
+
});
|
|
135
|
+
};
|
|
136
|
+
}
|
|
@@ -3,15 +3,16 @@ import { GlobalOutlined } from '@ant-design/icons';
|
|
|
3
3
|
import { useLocation, useNavigate, useParams } from 'react-router-dom';
|
|
4
4
|
import i18nConfig from '@config/i18n';
|
|
5
5
|
import { IOC } from '@/core/IOC';
|
|
6
|
-
import {
|
|
6
|
+
import { I18nServiceLocale } from '@/base/services/I18nService';
|
|
7
7
|
import { useCallback } from 'react';
|
|
8
8
|
import { useStore } from '@/uikit/hooks/useStore';
|
|
9
|
+
import { IOCIdentifier } from '@config/IOCIdentifier';
|
|
9
10
|
|
|
10
11
|
const { supportedLngs } = i18nConfig;
|
|
11
12
|
|
|
12
13
|
export default function LanguageSwitcher() {
|
|
13
14
|
const navigate = useNavigate();
|
|
14
|
-
const i18nService = IOC(
|
|
15
|
+
const i18nService = IOC(IOCIdentifier.I18nServiceInterface);
|
|
15
16
|
const loading = useStore(i18nService, i18nService.selector.loading);
|
|
16
17
|
const { lng } = useParams<{ lng: I18nServiceLocale }>();
|
|
17
18
|
const { pathname } = useLocation();
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { UserService } from '@/base/services/UserService';
|
|
2
1
|
import { IOC } from '@/core/IOC';
|
|
3
2
|
import {
|
|
4
3
|
AUTH_LOGOUT_DIALOG_CONTENT,
|
|
5
4
|
AUTH_LOGOUT_DIALOG_TITLE
|
|
6
5
|
} from '@config/Identifier/common';
|
|
6
|
+
import { IOCIdentifier } from '@config/IOCIdentifier';
|
|
7
7
|
import { Button } from 'antd';
|
|
8
8
|
import { useCallback } from 'react';
|
|
9
9
|
import { useTranslation } from 'react-i18next';
|
|
@@ -19,7 +19,7 @@ export default function LogoutButton() {
|
|
|
19
19
|
title: tTitle,
|
|
20
20
|
content: tContent,
|
|
21
21
|
onOk: () => {
|
|
22
|
-
IOC(
|
|
22
|
+
IOC(IOCIdentifier.UserServiceInterface).logout();
|
|
23
23
|
}
|
|
24
24
|
});
|
|
25
25
|
}, [tTitle, tContent]);
|
package/dist/templates/react-app/src/uikit/{providers → components}/ProcessExecutorProvider.tsx
RENAMED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import { UserAuthProvider } from './UserAuthProvider';
|
|
2
2
|
import { useStrictEffect } from '../hooks/useStrictEffect';
|
|
3
3
|
import { IOC } from '@/core/IOC';
|
|
4
|
-
import { ProcesserExecutor } from '@/base/services/ProcesserExecutor';
|
|
5
4
|
import { useI18nGuard } from '../hooks/useI18nGuard';
|
|
6
|
-
import {
|
|
5
|
+
import { IOCIdentifier } from '@config/IOCIdentifier';
|
|
6
|
+
import { useNavigateBridge } from '../hooks/useNavigateBridge';
|
|
7
7
|
|
|
8
8
|
export function ProcessExecutorProvider({
|
|
9
9
|
children
|
|
10
10
|
}: {
|
|
11
11
|
children: React.ReactNode;
|
|
12
12
|
}) {
|
|
13
|
-
const processerExecutor = IOC(
|
|
13
|
+
const processerExecutor = IOC(IOCIdentifier.ProcesserExecutorInterface);
|
|
14
14
|
|
|
15
15
|
useI18nGuard();
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
useNavigateBridge();
|
|
18
18
|
|
|
19
19
|
useStrictEffect(() => {
|
|
20
20
|
processerExecutor.starup();
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Suspense } from 'react';
|
|
2
2
|
import { Loading } from './Loading';
|
|
3
|
-
import BaseRouteProvider from '@/uikit/
|
|
3
|
+
import BaseRouteProvider from '@/uikit/components/BaseRouteProvider';
|
|
4
4
|
import { RouterLoaderRender } from '@/base/cases/RouterLoader';
|
|
5
5
|
|
|
6
6
|
export const RouterRenderComponent: RouterLoaderRender = (route) => {
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { IOC } from '@/core/IOC';
|
|
2
|
-
import { ThemeService } from '@qlover/corekit-bridge';
|
|
3
2
|
import { useStore } from '@/uikit/hooks/useStore';
|
|
4
3
|
import { useTranslation } from 'react-i18next';
|
|
5
4
|
import { Select } from 'antd';
|
|
@@ -12,6 +11,7 @@ import {
|
|
|
12
11
|
import clsx from 'clsx';
|
|
13
12
|
import { useMemo } from 'react';
|
|
14
13
|
import * as i18nKeys from '@config/Identifier/common';
|
|
14
|
+
import { IOCIdentifier } from '@config/IOCIdentifier';
|
|
15
15
|
|
|
16
16
|
const colorMap: Record<
|
|
17
17
|
string,
|
|
@@ -35,10 +35,8 @@ const colorMap: Record<
|
|
|
35
35
|
};
|
|
36
36
|
|
|
37
37
|
export default function ThemeSwitcher() {
|
|
38
|
-
const themeService = IOC(ThemeService);
|
|
39
|
-
|
|
40
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
41
|
-
const { theme } = useStore(themeService as any);
|
|
38
|
+
const themeService = IOC(IOCIdentifier.ThemeService);
|
|
39
|
+
const { theme } = useStore(themeService);
|
|
42
40
|
const themes = themeService.getSupportedThemes();
|
|
43
41
|
const { t } = useTranslation('common');
|
|
44
42
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { IOC } from '@/core/IOC';
|
|
2
|
-
import { Loading } from '
|
|
3
|
-
import { UserService } from '@/base/services/UserService';
|
|
2
|
+
import { Loading } from './Loading';
|
|
4
3
|
import { useStore } from '../hooks/useStore';
|
|
4
|
+
import { IOCIdentifier } from '@config/IOCIdentifier';
|
|
5
5
|
|
|
6
6
|
export function UserAuthProvider({ children }: { children: React.ReactNode }) {
|
|
7
|
-
const userService = IOC(
|
|
7
|
+
const userService = IOC(IOCIdentifier.UserServiceInterface);
|
|
8
8
|
|
|
9
9
|
useStore(userService.store);
|
|
10
10
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { I18nServiceLocale } from '@/base/services/I18nService';
|
|
2
|
-
import { RouteService } from '@/base/services/RouteService';
|
|
3
2
|
import { IOC } from '@/core/IOC';
|
|
3
|
+
import { IOCIdentifier } from '@config/IOCIdentifier';
|
|
4
4
|
import { useEffect } from 'react';
|
|
5
5
|
import { useNavigate } from 'react-router-dom';
|
|
6
6
|
import { useParams } from 'react-router-dom';
|
|
@@ -17,6 +17,9 @@ export function useI18nGuard() {
|
|
|
17
17
|
const navigate = useNavigate();
|
|
18
18
|
|
|
19
19
|
useEffect(() => {
|
|
20
|
-
IOC(
|
|
20
|
+
IOC(IOCIdentifier.RouteServiceInterface).i18nGuard(
|
|
21
|
+
lng as I18nServiceLocale,
|
|
22
|
+
navigate
|
|
23
|
+
);
|
|
21
24
|
}, [lng, navigate]);
|
|
22
25
|
}
|
package/dist/templates/react-app/src/uikit/hooks/{userRouterService.ts → useNavigateBridge.ts}
RENAMED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { RouteService } from '@/base/services/RouteService';
|
|
2
1
|
import { IOC } from '@/core/IOC';
|
|
3
2
|
import { useEffect } from 'react';
|
|
4
3
|
import { useNavigate } from 'react-router-dom';
|
|
4
|
+
import { NavigateBridge } from '../bridges/NavigateBridge';
|
|
5
5
|
|
|
6
|
-
export function
|
|
6
|
+
export function useNavigateBridge() {
|
|
7
7
|
const navigate = useNavigate();
|
|
8
8
|
|
|
9
9
|
useEffect(() => {
|
|
10
|
-
IOC(
|
|
10
|
+
IOC(NavigateBridge).setUIBridge(navigate);
|
|
11
11
|
}, [navigate]);
|
|
12
12
|
}
|
|
@@ -2,11 +2,14 @@ import {
|
|
|
2
2
|
StoreInterface,
|
|
3
3
|
type StoreStateInterface
|
|
4
4
|
} from '@qlover/corekit-bridge';
|
|
5
|
-
import { useSliceStore } from '@qlover/slice-store-react';
|
|
5
|
+
import { SliceStore, useSliceStore } from '@qlover/slice-store-react';
|
|
6
6
|
|
|
7
7
|
export function useStore<
|
|
8
8
|
C extends StoreInterface<StoreStateInterface>,
|
|
9
9
|
State = C['state']
|
|
10
10
|
>(store: C, selector?: (state: C['state']) => State): State {
|
|
11
|
-
return useSliceStore(
|
|
11
|
+
return useSliceStore(
|
|
12
|
+
store as unknown as SliceStore<StoreStateInterface>,
|
|
13
|
+
selector
|
|
14
|
+
);
|
|
12
15
|
}
|
package/package.json
CHANGED
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
import type { ModalFuncProps } from 'antd';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Confirmation dialog configuration options
|
|
5
|
-
* Extends Ant Design's ModalFuncProps and requires a title
|
|
6
|
-
*/
|
|
7
|
-
export interface ConfirmOptions extends ModalFuncProps {
|
|
8
|
-
content: string;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Basic dialog configuration options
|
|
13
|
-
*/
|
|
14
|
-
export interface InteractionOptions {
|
|
15
|
-
/** Display duration (milliseconds) */
|
|
16
|
-
duration?: number;
|
|
17
|
-
/** Close callback function */
|
|
18
|
-
onClose?: () => void;
|
|
19
|
-
/** Error object */
|
|
20
|
-
error?: unknown;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Interaction Hub Interface
|
|
25
|
-
*
|
|
26
|
-
* This interface serves as the central interaction layer for the application,
|
|
27
|
-
* managing all user interface interactions, notifications, and feedback functionality.
|
|
28
|
-
* Main responsibilities include:
|
|
29
|
-
* 1. Providing a unified message notification mechanism (success/error/info/warn)
|
|
30
|
-
* 2. Handling user interaction confirmation scenarios (confirm)
|
|
31
|
-
* 3. Unified error display and handling approach
|
|
32
|
-
*
|
|
33
|
-
* Design Goals:
|
|
34
|
-
* - Uniformity: Provide consistent user interaction experience
|
|
35
|
-
* - Extensibility: Easy to add new interaction types
|
|
36
|
-
* - Configurability: Support custom interaction behaviors
|
|
37
|
-
* - Decoupling: Separate UI interaction layer from business logic
|
|
38
|
-
*
|
|
39
|
-
* Use Cases:
|
|
40
|
-
* - Operation success/failure feedback
|
|
41
|
-
* - Important operation confirmation prompts
|
|
42
|
-
* - System message notifications
|
|
43
|
-
* - Warning message display
|
|
44
|
-
*
|
|
45
|
-
* Implementation Notes:
|
|
46
|
-
* - Currently implemented based on Ant Design component library
|
|
47
|
-
* - Supports other UI libraries through different adapters
|
|
48
|
-
* - Supports global configuration of default behaviors
|
|
49
|
-
*
|
|
50
|
-
* @example
|
|
51
|
-
* // Success notification
|
|
52
|
-
* interactionHub.success("Operation successful", { duration: 3000 });
|
|
53
|
-
*
|
|
54
|
-
* // Confirmation dialog
|
|
55
|
-
* interactionHub.confirm({
|
|
56
|
-
* content: "Are you sure you want to delete?",
|
|
57
|
-
* onOk: () => handleDelete()
|
|
58
|
-
* });
|
|
59
|
-
*/
|
|
60
|
-
export interface InteractionHubInterface {
|
|
61
|
-
/**
|
|
62
|
-
* Display success notification
|
|
63
|
-
* @param message Notification message
|
|
64
|
-
* @param options Configuration options
|
|
65
|
-
*/
|
|
66
|
-
success(message: string, options?: InteractionOptions): void;
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Display error notification
|
|
70
|
-
* @param message Error message
|
|
71
|
-
* @param options Configuration options
|
|
72
|
-
*/
|
|
73
|
-
error(message: string, options?: InteractionOptions): void;
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Display information notification
|
|
77
|
-
* @param message Information message
|
|
78
|
-
* @param options Configuration options
|
|
79
|
-
*/
|
|
80
|
-
info(message: string, options?: InteractionOptions): void;
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* Display warning notification
|
|
84
|
-
* @param message Warning message
|
|
85
|
-
* @param options Configuration options
|
|
86
|
-
*/
|
|
87
|
-
warn(message: string, options?: InteractionOptions): void;
|
|
88
|
-
|
|
89
|
-
/**
|
|
90
|
-
* Display confirmation dialog
|
|
91
|
-
* @param options Confirmation dialog configuration options
|
|
92
|
-
*/
|
|
93
|
-
confirm(options: ConfirmOptions): void;
|
|
94
|
-
}
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Need to be used in the UI component
|
|
3
|
-
*
|
|
4
|
-
* eg. A service use window.localStorage, it should be like this:
|
|
5
|
-
*
|
|
6
|
-
*/
|
|
7
|
-
export interface UIDependenciesInterface<Dep = unknown> {
|
|
8
|
-
/**
|
|
9
|
-
* Represents the dependencies required by the UI component.
|
|
10
|
-
*
|
|
11
|
-
* @type {Dep}
|
|
12
|
-
* @description This allows for partial updates to the dependencies if `Dep` is an object, enabling flexibility in dependency management.
|
|
13
|
-
*
|
|
14
|
-
* @example
|
|
15
|
-
* const uiDependencies: UIDependenciesInterface<{ api: string, token: string }> = {
|
|
16
|
-
* dependencies: { api: 'https://api.example.com' }
|
|
17
|
-
* };
|
|
18
|
-
*
|
|
19
|
-
* const simpleDependencies: UIDependenciesInterface<string> = {
|
|
20
|
-
* dependencies: 'simple-dependency'
|
|
21
|
-
* };
|
|
22
|
-
*/
|
|
23
|
-
dependencies?: Dep;
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Sets the dependencies for the UI component.
|
|
27
|
-
*
|
|
28
|
-
* @param {Dep} dependencies - The dependencies to be set, allowing partial updates if `Dep` is an object.
|
|
29
|
-
* @description This method allows updating the dependencies, supporting partial updates if `Dep` is an object.
|
|
30
|
-
*
|
|
31
|
-
* @example
|
|
32
|
-
* uiDependencies.setDependencies({ token: 'new-token' });
|
|
33
|
-
*
|
|
34
|
-
* simpleDependencies.setDependencies('new-simple-dependency');
|
|
35
|
-
*/
|
|
36
|
-
setDependencies(dependencies: Dep): void;
|
|
37
|
-
}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import type { IOCContainer, IOCRegister, IocRegisterOptions } from '../IOC';
|
|
2
|
-
import type { IOCManagerInterface } from '@qlover/corekit-bridge';
|
|
3
|
-
import { RegisterGlobals } from './RegisterGlobals';
|
|
4
|
-
import { RegisterCommon } from './RegisterCommon';
|
|
5
|
-
import { RegisterControllers } from './RegisterControllers';
|
|
6
|
-
|
|
7
|
-
export class IocRegisterImpl implements IOCRegister {
|
|
8
|
-
constructor(protected options: IocRegisterOptions) {}
|
|
9
|
-
|
|
10
|
-
getRegisterList(): IOCRegister[] {
|
|
11
|
-
return [RegisterGlobals, RegisterCommon, new RegisterControllers()];
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* @override
|
|
16
|
-
*/
|
|
17
|
-
register(
|
|
18
|
-
ioc: IOCContainer,
|
|
19
|
-
manager: IOCManagerInterface<IOCContainer>
|
|
20
|
-
): void {
|
|
21
|
-
this.getRegisterList().forEach((Register) => {
|
|
22
|
-
Register.register(ioc, manager, this.options);
|
|
23
|
-
});
|
|
24
|
-
}
|
|
25
|
-
}
|