botmux 2.98.4-canary.2 → 2.99.0
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/README.en.md +2 -2
- package/README.md +2 -2
- package/dist/adapters/cli/genius.d.ts +4 -0
- package/dist/adapters/cli/genius.d.ts.map +1 -0
- package/dist/adapters/cli/genius.js +216 -0
- package/dist/adapters/cli/genius.js.map +1 -0
- package/dist/adapters/cli/registry.d.ts +2 -1
- package/dist/adapters/cli/registry.d.ts.map +1 -1
- package/dist/adapters/cli/registry.js +3 -1
- package/dist/adapters/cli/registry.js.map +1 -1
- package/dist/adapters/cli/types.d.ts +1 -1
- package/dist/adapters/cli/types.d.ts.map +1 -1
- package/dist/core/dashboard-rows.d.ts +1 -1
- package/dist/core/dashboard-rows.d.ts.map +1 -1
- package/dist/core/dashboard-rows.js +2 -1
- package/dist/core/dashboard-rows.js.map +1 -1
- package/dist/dashboard/session-card-model.d.ts +2 -2
- package/dist/dashboard/session-card-model.d.ts.map +1 -1
- package/dist/dashboard/session-card-model.js +5 -2
- package/dist/dashboard/session-card-model.js.map +1 -1
- package/dist/dashboard/web/app.d.ts.map +1 -1
- package/dist/dashboard/web/app.js +28 -63
- package/dist/dashboard/web/app.js.map +1 -1
- package/dist/dashboard/web/bot-defaults-page.d.ts +3 -0
- package/dist/dashboard/web/bot-defaults-page.d.ts.map +1 -0
- package/dist/dashboard/web/bot-defaults-page.js +23 -0
- package/dist/dashboard/web/bot-defaults-page.js.map +1 -0
- package/dist/dashboard/web/bot-defaults.d.ts +2 -1
- package/dist/dashboard/web/bot-defaults.d.ts.map +1 -1
- package/dist/dashboard/web/bot-defaults.js +30 -30
- package/dist/dashboard/web/bot-defaults.js.map +1 -1
- package/dist/dashboard/web/connectors-page.d.ts +14 -0
- package/dist/dashboard/web/connectors-page.d.ts.map +1 -0
- package/dist/dashboard/web/connectors-page.js +303 -0
- package/dist/dashboard/web/connectors-page.js.map +1 -0
- package/dist/dashboard/web/connectors.d.ts +1 -12
- package/dist/dashboard/web/connectors.d.ts.map +1 -1
- package/dist/dashboard/web/connectors.js +1 -325
- package/dist/dashboard/web/connectors.js.map +1 -1
- package/dist/dashboard/web/dashboard-routes.d.ts +14 -0
- package/dist/dashboard/web/dashboard-routes.d.ts.map +1 -0
- package/dist/dashboard/web/dashboard-routes.js +176 -0
- package/dist/dashboard/web/dashboard-routes.js.map +1 -0
- package/dist/dashboard/web/groups-page.d.ts +3 -0
- package/dist/dashboard/web/groups-page.d.ts.map +1 -0
- package/dist/dashboard/web/groups-page.js +26 -0
- package/dist/dashboard/web/groups-page.js.map +1 -0
- package/dist/dashboard/web/groups.d.ts +1 -1
- package/dist/dashboard/web/groups.d.ts.map +1 -1
- package/dist/dashboard/web/groups.js +113 -52
- package/dist/dashboard/web/groups.js.map +1 -1
- package/dist/dashboard/web/i18n.d.ts.map +1 -1
- package/dist/dashboard/web/i18n.js +18 -0
- package/dist/dashboard/web/i18n.js.map +1 -1
- package/dist/dashboard/web/insights-page.d.ts +3 -0
- package/dist/dashboard/web/insights-page.d.ts.map +1 -0
- package/dist/dashboard/web/insights-page.js +26 -0
- package/dist/dashboard/web/insights-page.js.map +1 -0
- package/dist/dashboard/web/insights.d.ts +18 -1
- package/dist/dashboard/web/insights.d.ts.map +1 -1
- package/dist/dashboard/web/insights.js +25 -61
- package/dist/dashboard/web/insights.js.map +1 -1
- package/dist/dashboard/web/office-page.d.ts +3 -0
- package/dist/dashboard/web/office-page.d.ts.map +1 -0
- package/dist/dashboard/web/office-page.js +149 -0
- package/dist/dashboard/web/office-page.js.map +1 -0
- package/dist/dashboard/web/office.d.ts +1 -1
- package/dist/dashboard/web/office.d.ts.map +1 -1
- package/dist/dashboard/web/office.js +1 -139
- package/dist/dashboard/web/office.js.map +1 -1
- package/dist/dashboard/web/overview-page.d.ts +3 -0
- package/dist/dashboard/web/overview-page.d.ts.map +1 -0
- package/dist/dashboard/web/overview-page.js +149 -0
- package/dist/dashboard/web/overview-page.js.map +1 -0
- package/dist/dashboard/web/overview.d.ts +2 -2
- package/dist/dashboard/web/overview.d.ts.map +1 -1
- package/dist/dashboard/web/overview.js +14 -3
- package/dist/dashboard/web/overview.js.map +1 -1
- package/dist/dashboard/web/react-hooks.d.ts +8 -0
- package/dist/dashboard/web/react-hooks.d.ts.map +1 -0
- package/dist/dashboard/web/react-hooks.js +43 -0
- package/dist/dashboard/web/react-hooks.js.map +1 -0
- package/dist/dashboard/web/react-mount.d.ts +4 -0
- package/dist/dashboard/web/react-mount.d.ts.map +1 -0
- package/dist/dashboard/web/react-mount.js +7 -0
- package/dist/dashboard/web/react-mount.js.map +1 -0
- package/dist/dashboard/web/roles-page.d.ts +4 -0
- package/dist/dashboard/web/roles-page.d.ts.map +1 -0
- package/dist/dashboard/web/roles-page.js +26 -0
- package/dist/dashboard/web/roles-page.js.map +1 -0
- package/dist/dashboard/web/roles.d.ts +1 -2
- package/dist/dashboard/web/roles.d.ts.map +1 -1
- package/dist/dashboard/web/roles.js +189 -135
- package/dist/dashboard/web/roles.js.map +1 -1
- package/dist/dashboard/web/route-lifecycle.d.ts +14 -0
- package/dist/dashboard/web/route-lifecycle.d.ts.map +1 -0
- package/dist/dashboard/web/route-lifecycle.js +29 -0
- package/dist/dashboard/web/route-lifecycle.js.map +1 -0
- package/dist/dashboard/web/schedules-page.d.ts +14 -0
- package/dist/dashboard/web/schedules-page.d.ts.map +1 -0
- package/dist/dashboard/web/schedules-page.js +84 -0
- package/dist/dashboard/web/schedules-page.js.map +1 -0
- package/dist/dashboard/web/schedules.d.ts +1 -1
- package/dist/dashboard/web/schedules.d.ts.map +1 -1
- package/dist/dashboard/web/schedules.js +1 -115
- package/dist/dashboard/web/schedules.js.map +1 -1
- package/dist/dashboard/web/sessions-page.d.ts +3 -0
- package/dist/dashboard/web/sessions-page.d.ts.map +1 -0
- package/dist/dashboard/web/sessions-page.js +28 -0
- package/dist/dashboard/web/sessions-page.js.map +1 -0
- package/dist/dashboard/web/sessions.d.ts +4 -1
- package/dist/dashboard/web/sessions.d.ts.map +1 -1
- package/dist/dashboard/web/sessions.js +43 -10
- package/dist/dashboard/web/sessions.js.map +1 -1
- package/dist/dashboard/web/settings-page.d.ts +3 -0
- package/dist/dashboard/web/settings-page.d.ts.map +1 -0
- package/dist/dashboard/web/settings-page.js +387 -0
- package/dist/dashboard/web/settings-page.js.map +1 -0
- package/dist/dashboard/web/settings.d.ts +1 -1
- package/dist/dashboard/web/settings.d.ts.map +1 -1
- package/dist/dashboard/web/settings.js +1 -534
- package/dist/dashboard/web/settings.js.map +1 -1
- package/dist/dashboard/web/skills-page.d.ts +33 -0
- package/dist/dashboard/web/skills-page.d.ts.map +1 -0
- package/dist/dashboard/web/skills-page.js +515 -0
- package/dist/dashboard/web/skills-page.js.map +1 -0
- package/dist/dashboard/web/skills.d.ts +1 -1
- package/dist/dashboard/web/skills.d.ts.map +1 -1
- package/dist/dashboard/web/skills.js +1 -711
- package/dist/dashboard/web/skills.js.map +1 -1
- package/dist/dashboard/web/store.d.ts +9 -0
- package/dist/dashboard/web/store.d.ts.map +1 -1
- package/dist/dashboard/web/store.js +19 -2
- package/dist/dashboard/web/store.js.map +1 -1
- package/dist/dashboard/web/team-federation-page.d.ts +4 -0
- package/dist/dashboard/web/team-federation-page.d.ts.map +1 -0
- package/dist/dashboard/web/team-federation-page.js +47 -0
- package/dist/dashboard/web/team-federation-page.js.map +1 -0
- package/dist/dashboard/web/team-federation.d.ts +2 -2
- package/dist/dashboard/web/team-federation.d.ts.map +1 -1
- package/dist/dashboard/web/team-federation.js +104 -97
- package/dist/dashboard/web/team-federation.js.map +1 -1
- package/dist/dashboard/web/v3-page.d.ts +3 -0
- package/dist/dashboard/web/v3-page.d.ts.map +1 -0
- package/dist/dashboard/web/v3-page.js +27 -0
- package/dist/dashboard/web/v3-page.js.map +1 -0
- package/dist/dashboard/web/v3.d.ts +2 -1
- package/dist/dashboard/web/v3.d.ts.map +1 -1
- package/dist/dashboard/web/v3.js +18 -43
- package/dist/dashboard/web/v3.js.map +1 -1
- package/dist/dashboard/web/whiteboards-page.d.ts +3 -0
- package/dist/dashboard/web/whiteboards-page.d.ts.map +1 -0
- package/dist/dashboard/web/whiteboards-page.js +203 -0
- package/dist/dashboard/web/whiteboards-page.js.map +1 -0
- package/dist/dashboard/web/whiteboards.d.ts +1 -1
- package/dist/dashboard/web/whiteboards.d.ts.map +1 -1
- package/dist/dashboard/web/whiteboards.js +1 -275
- package/dist/dashboard/web/whiteboards.js.map +1 -1
- package/dist/dashboard-web/app.js +36 -2550
- package/dist/dashboard-web/chunks/bot-defaults-page-3EV7K6LJ.js +358 -0
- package/dist/dashboard-web/chunks/chunk-5E3MJJL4.js +1 -0
- package/dist/dashboard-web/chunks/chunk-76J7PNZI.js +1 -0
- package/dist/dashboard-web/chunks/chunk-7SZRL6FY.js +1 -0
- package/dist/dashboard-web/chunks/chunk-JTSE5VP6.js +54 -0
- package/dist/dashboard-web/chunks/chunk-JXLHRRJD.js +31 -0
- package/dist/dashboard-web/chunks/chunk-NASYW5FD.js +1 -0
- package/dist/dashboard-web/chunks/connectors-XPZKEHF6.js +1 -0
- package/dist/dashboard-web/chunks/groups-page-C54PVKYP.js +207 -0
- package/dist/dashboard-web/chunks/insights-page-BBQYR7WY.js +309 -0
- package/dist/dashboard-web/chunks/office-page-6DXYOG55.js +1 -0
- package/dist/dashboard-web/chunks/overview-page-5PJCAMID.js +1 -0
- package/dist/dashboard-web/chunks/roles-page-APUDLPVM.js +98 -0
- package/dist/dashboard-web/chunks/schedules-WG2UKHSO.js +1 -0
- package/dist/dashboard-web/chunks/sessions-page-F3U5NFPD.js +238 -0
- package/dist/dashboard-web/chunks/settings-page-OSBZNCXL.js +2 -0
- package/dist/dashboard-web/chunks/skills-page-Y3VUAOYG.js +2 -0
- package/dist/dashboard-web/chunks/team-federation-page-CRH3WZPH.js +10 -0
- package/dist/dashboard-web/chunks/v3-page-FVPUL665.js +149 -0
- package/dist/dashboard-web/chunks/whiteboards-page-HLCTYSSV.js +1 -0
- package/dist/dashboard-web/chunks/workflows-UB7OPYGI.js +184 -0
- package/dist/dashboard-web/index.html +1 -1
- package/dist/dashboard-web/style.css +82 -1
- package/dist/dashboard.js +5 -6
- package/dist/dashboard.js.map +1 -1
- package/dist/i18n/en.d.ts.map +1 -1
- package/dist/i18n/en.js +1 -0
- package/dist/i18n/en.js.map +1 -1
- package/dist/i18n/zh.d.ts.map +1 -1
- package/dist/i18n/zh.js +1 -0
- package/dist/i18n/zh.js.map +1 -1
- package/dist/im/lark/card-builder.d.ts.map +1 -1
- package/dist/im/lark/card-builder.js +1 -0
- package/dist/im/lark/card-builder.js.map +1 -1
- package/dist/im/lark/event-dispatcher.d.ts.map +1 -1
- package/dist/im/lark/event-dispatcher.js +7 -0
- package/dist/im/lark/event-dispatcher.js.map +1 -1
- package/dist/im/lark/sessions-card.d.ts.map +1 -1
- package/dist/im/lark/sessions-card.js +4 -1
- package/dist/im/lark/sessions-card.js.map +1 -1
- package/dist/setup/bot-config-editor.d.ts.map +1 -1
- package/dist/setup/bot-config-editor.js +16 -14
- package/dist/setup/bot-config-editor.js.map +1 -1
- package/dist/worker.js +1 -1
- package/dist/worker.js.map +1 -1
- package/package.json +8 -2
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
export const dashboardRoutes = [
|
|
2
|
+
{
|
|
3
|
+
id: 'legacy-workflow',
|
|
4
|
+
routePrefix: '#/legacy-workflow',
|
|
5
|
+
load: async () => {
|
|
6
|
+
const mod = await import('./workflows.js');
|
|
7
|
+
return root => mod.renderWorkflowsPage(root);
|
|
8
|
+
},
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
id: 'workflows',
|
|
12
|
+
routePrefix: '#/workflows',
|
|
13
|
+
rerenderOnUiChange: false,
|
|
14
|
+
load: async () => {
|
|
15
|
+
const mod = await import('./v3-page.js');
|
|
16
|
+
return root => mod.renderV3RunsPage(root);
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
id: 'groups',
|
|
21
|
+
routePrefix: '#/groups',
|
|
22
|
+
// Groups is currently a render-once React scaffold around the existing
|
|
23
|
+
// imperative matrix/dialog controller, so locale/theme changes full-remount
|
|
24
|
+
// it until those controller-owned subtrees become React components.
|
|
25
|
+
rerenderOnUiChange: true,
|
|
26
|
+
load: async () => {
|
|
27
|
+
const mod = await import('./groups-page.js');
|
|
28
|
+
return root => mod.renderGroupsPage(root);
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
id: 'settings',
|
|
33
|
+
routePrefix: '#/settings',
|
|
34
|
+
rerenderOnUiChange: false,
|
|
35
|
+
load: async () => {
|
|
36
|
+
const mod = await import('./settings-page.js');
|
|
37
|
+
return root => mod.renderSettingsPage(root);
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
id: 'bot-defaults',
|
|
42
|
+
routePrefix: '#/bot-defaults',
|
|
43
|
+
// Bot defaults is currently a render-once React scaffold around the
|
|
44
|
+
// imperative settings controller, so ui changes still full-remount it to
|
|
45
|
+
// refresh translations without partial React renders fighting innerHTML.
|
|
46
|
+
rerenderOnUiChange: true,
|
|
47
|
+
load: async () => {
|
|
48
|
+
const mod = await import('./bot-defaults-page.js');
|
|
49
|
+
return root => mod.renderBotDefaultsPage(root);
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
id: 'skills',
|
|
54
|
+
routePrefix: '#/skills',
|
|
55
|
+
rerenderOnUiChange: false,
|
|
56
|
+
load: async () => {
|
|
57
|
+
const mod = await import('./skills-page.js');
|
|
58
|
+
return root => mod.renderSkillsPage(root);
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
{
|
|
62
|
+
id: 'connectors',
|
|
63
|
+
routePrefix: '#/connectors',
|
|
64
|
+
rerenderOnUiChange: false,
|
|
65
|
+
load: async () => {
|
|
66
|
+
const mod = await import('./connectors.js');
|
|
67
|
+
return root => mod.renderConnectorsPage(root);
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
id: 'team-manage',
|
|
72
|
+
routePrefix: '#/team/manage',
|
|
73
|
+
// Team pages are render-once React scaffolds around the existing
|
|
74
|
+
// federation controller, so ui changes full-remount translated subtrees.
|
|
75
|
+
rerenderOnUiChange: true,
|
|
76
|
+
load: async () => {
|
|
77
|
+
const mod = await import('./team-federation-page.js');
|
|
78
|
+
return root => mod.renderTeamManagePage(root);
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
id: 'team',
|
|
83
|
+
routePrefix: '#/team',
|
|
84
|
+
// Team pages are render-once React scaffolds around the existing
|
|
85
|
+
// federation controller, so ui changes full-remount translated subtrees.
|
|
86
|
+
rerenderOnUiChange: true,
|
|
87
|
+
load: async () => {
|
|
88
|
+
const mod = await import('./team-federation-page.js');
|
|
89
|
+
return root => mod.renderTeamFederationPage(root);
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
id: 'roles-profile',
|
|
94
|
+
routePrefix: '#/roles/profile',
|
|
95
|
+
// Roles still uses a render-once React scaffold around the imperative
|
|
96
|
+
// editor/profile controller, so ui changes full-remount it until the
|
|
97
|
+
// controller-owned subtrees become reactive components.
|
|
98
|
+
rerenderOnUiChange: true,
|
|
99
|
+
load: async () => {
|
|
100
|
+
const mod = await import('./roles-page.js');
|
|
101
|
+
return root => mod.renderRoleProfilesPage(root);
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
id: 'roles',
|
|
106
|
+
routePrefix: '#/roles',
|
|
107
|
+
// Roles still uses a render-once React scaffold around the imperative
|
|
108
|
+
// editor/profile controller, so ui changes full-remount it until the
|
|
109
|
+
// controller-owned subtrees become reactive components.
|
|
110
|
+
rerenderOnUiChange: true,
|
|
111
|
+
load: async () => {
|
|
112
|
+
const mod = await import('./roles-page.js');
|
|
113
|
+
return root => mod.renderRolesPage(root);
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
id: 'schedules',
|
|
118
|
+
routePrefix: '#/schedules',
|
|
119
|
+
rerenderOnUiChange: false,
|
|
120
|
+
load: async () => {
|
|
121
|
+
const mod = await import('./schedules.js');
|
|
122
|
+
return root => mod.renderSchedulesPage(root);
|
|
123
|
+
},
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
id: 'whiteboards',
|
|
127
|
+
routePrefix: '#/whiteboards',
|
|
128
|
+
rerenderOnUiChange: false,
|
|
129
|
+
load: async () => {
|
|
130
|
+
const mod = await import('./whiteboards-page.js');
|
|
131
|
+
return root => mod.renderWhiteboardsPage(root);
|
|
132
|
+
},
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
id: 'sessions',
|
|
136
|
+
routePrefix: '#/sessions',
|
|
137
|
+
// Sessions is a render-once React scaffold around the legacy imperative
|
|
138
|
+
// controller. Keep full remounts on locale/theme changes until the
|
|
139
|
+
// controller is split into reactive components, so translated scaffold text
|
|
140
|
+
// and command-owned DOM stay in sync without partial React re-renders.
|
|
141
|
+
rerenderOnUiChange: true,
|
|
142
|
+
load: async () => {
|
|
143
|
+
const mod = await import('./sessions-page.js');
|
|
144
|
+
return root => mod.renderSessionsPage(root);
|
|
145
|
+
},
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
id: 'office',
|
|
149
|
+
routePrefix: '#/office',
|
|
150
|
+
rerenderOnUiChange: false,
|
|
151
|
+
load: async () => {
|
|
152
|
+
const mod = await import('./office-page.js');
|
|
153
|
+
return root => mod.renderOfficePage(root);
|
|
154
|
+
},
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
id: 'insights',
|
|
158
|
+
routePrefix: '#/insights',
|
|
159
|
+
// Insights is a render-once React scaffold around a large imperative
|
|
160
|
+
// workbench controller; remount on ui changes until that controller is
|
|
161
|
+
// split into reactive components.
|
|
162
|
+
rerenderOnUiChange: true,
|
|
163
|
+
load: async () => {
|
|
164
|
+
const mod = await import('./insights-page.js');
|
|
165
|
+
return root => mod.renderInsightsPage(root);
|
|
166
|
+
},
|
|
167
|
+
},
|
|
168
|
+
];
|
|
169
|
+
export function findDashboardRoute(hash) {
|
|
170
|
+
return dashboardRoutes.find(route => route.exact ? hash === route.routePrefix : hash.startsWith(route.routePrefix));
|
|
171
|
+
}
|
|
172
|
+
export async function loadOverviewPage() {
|
|
173
|
+
const mod = await import('./overview-page.js');
|
|
174
|
+
return root => mod.renderOverviewPage(root);
|
|
175
|
+
}
|
|
176
|
+
//# sourceMappingURL=dashboard-routes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dashboard-routes.js","sourceRoot":"","sources":["../../../src/dashboard/web/dashboard-routes.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"groups-page.d.ts","sourceRoot":"","sources":["../../../src/dashboard/web/groups-page.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAkB,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC;AA8CrE,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,WAAW,GAAG,YAAY,CAEhE"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useRef } from 'react';
|
|
3
|
+
import { loadingHtml } from './ui.js';
|
|
4
|
+
import { useT } from './react-hooks.js';
|
|
5
|
+
import { mountReactPage } from './react-mount.js';
|
|
6
|
+
import { wireGroupsPage } from './groups.js';
|
|
7
|
+
function Html(props) {
|
|
8
|
+
return _jsx("span", { style: { display: 'contents' }, dangerouslySetInnerHTML: { __html: props.html } });
|
|
9
|
+
}
|
|
10
|
+
// Render-once scaffold: React owns the translated route shell, while
|
|
11
|
+
// wireGroupsPage owns the matrix and dialog flows until those controllers are
|
|
12
|
+
// split into reactive components. Keep ui-change rerenders as full remounts.
|
|
13
|
+
function GroupsPage() {
|
|
14
|
+
const tr = useT();
|
|
15
|
+
const rootRef = useRef(null);
|
|
16
|
+
useEffect(() => {
|
|
17
|
+
if (!rootRef.current)
|
|
18
|
+
return undefined;
|
|
19
|
+
return wireGroupsPage(rootRef.current);
|
|
20
|
+
}, []);
|
|
21
|
+
return (_jsxs("section", { className: "page", ref: rootRef, children: [_jsx("div", { className: "page-heading", children: _jsxs("div", { children: [_jsx("p", { className: "eyebrow", children: tr('nav.groups') }), _jsx("h1", { children: tr('groups.title') }), _jsx("p", { children: tr('groups.subtitle') })] }) }), _jsxs("form", { id: "g-filters", className: "filters", children: [_jsx("input", { type: "search", name: "q", placeholder: tr('groups.search') }), _jsxs("label", { children: [_jsx("input", { type: "checkbox", name: "missing" }), " ", tr('groups.missingOnly')] }), _jsx("button", { type: "button", id: "g-refresh", children: tr('groups.refresh') }), _jsx("button", { type: "button", id: "g-create", className: "primary", children: tr('groups.create') })] }), _jsx("div", { id: "g-loading", children: _jsx(Html, { html: loadingHtml() }) }), _jsx("div", { className: "table-scroll matrix-scroll", id: "g-table-wrap", hidden: true, children: _jsxs("table", { children: [_jsx("thead", { id: "g-head" }), _jsx("tbody", { id: "g-body" })] }) }), _jsx("dialog", { id: "g-drawer" })] }));
|
|
22
|
+
}
|
|
23
|
+
export function renderGroupsPage(root) {
|
|
24
|
+
return mountReactPage(root, _jsx(GroupsPage, {}));
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=groups-page.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"groups-page.js","sourceRoot":"","sources":["../../../src/dashboard/web/groups-page.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AACtC,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACxC,OAAO,EAAE,cAAc,EAAqB,MAAM,kBAAkB,CAAC;AACrE,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7C,SAAS,IAAI,CAAC,KAAuB;IACnC,OAAO,eAAM,KAAK,EAAE,EAAE,OAAO,EAAE,UAAU,EAAE,EAAE,uBAAuB,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,IAAI,EAAE,GAAI,CAAC;AACnG,CAAC;AAED,qEAAqE;AACrE,8EAA8E;AAC9E,6EAA6E;AAC7E,SAAS,UAAU;IACjB,MAAM,EAAE,GAAG,IAAI,EAAE,CAAC;IAClB,MAAM,OAAO,GAAG,MAAM,CAAqB,IAAI,CAAC,CAAC;IAEjD,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,OAAO,CAAC,OAAO;YAAE,OAAO,SAAS,CAAC;QACvC,OAAO,cAAc,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IACzC,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,OAAO,CACL,mBAAS,SAAS,EAAC,MAAM,EAAC,GAAG,EAAE,OAAO,aACpC,cAAK,SAAS,EAAC,cAAc,YAC3B,0BACE,YAAG,SAAS,EAAC,SAAS,YAAE,EAAE,CAAC,YAAY,CAAC,GAAK,EAC7C,uBAAK,EAAE,CAAC,cAAc,CAAC,GAAM,EAC7B,sBAAI,EAAE,CAAC,iBAAiB,CAAC,GAAK,IAC1B,GACF,EACN,gBAAM,EAAE,EAAC,WAAW,EAAC,SAAS,EAAC,SAAS,aACtC,gBAAO,IAAI,EAAC,QAAQ,EAAC,IAAI,EAAC,GAAG,EAAC,WAAW,EAAE,EAAE,CAAC,eAAe,CAAC,GAAI,EAClE,4BAAO,gBAAO,IAAI,EAAC,UAAU,EAAC,IAAI,EAAC,SAAS,GAAG,OAAE,EAAE,CAAC,oBAAoB,CAAC,IAAS,EAClF,iBAAQ,IAAI,EAAC,QAAQ,EAAC,EAAE,EAAC,WAAW,YAAE,EAAE,CAAC,gBAAgB,CAAC,GAAU,EACpE,iBAAQ,IAAI,EAAC,QAAQ,EAAC,EAAE,EAAC,UAAU,EAAC,SAAS,EAAC,SAAS,YAAE,EAAE,CAAC,eAAe,CAAC,GAAU,IACjF,EACP,cAAK,EAAE,EAAC,WAAW,YAAC,KAAC,IAAI,IAAC,IAAI,EAAE,WAAW,EAAE,GAAI,GAAM,EACvD,cAAK,SAAS,EAAC,4BAA4B,EAAC,EAAE,EAAC,cAAc,EAAC,MAAM,kBAClE,4BACE,gBAAO,EAAE,EAAC,QAAQ,GAAG,EACrB,gBAAO,EAAE,EAAC,QAAQ,GAAG,IACf,GACJ,EACN,iBAAQ,EAAE,EAAC,UAAU,GAAG,IAChB,CACX,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,IAAiB;IAChD,OAAO,cAAc,CAAC,IAAI,EAAE,KAAC,UAAU,KAAG,CAAC,CAAC;AAC9C,CAAC"}
|
|
@@ -20,6 +20,6 @@ export declare function renderBotCheckboxes(bots: Array<{
|
|
|
20
20
|
}>, excludeIds?: Set<string>): string;
|
|
21
21
|
export declare function renderRoleProfileBootstrapSummary(profileId: string, messageId?: unknown, error?: unknown): string;
|
|
22
22
|
export declare function renderAddBotsResultSummary(result: GroupAddBotResult[]): string;
|
|
23
|
-
export declare function
|
|
23
|
+
export declare function wireGroupsPage(root: HTMLElement): () => void;
|
|
24
24
|
export {};
|
|
25
25
|
//# sourceMappingURL=groups.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"groups.d.ts","sourceRoot":"","sources":["../../../src/dashboard/web/groups.ts"],"names":[],"mappings":"AA4BA,KAAK,iBAAiB,GAAG;IACvB,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC;AAMF,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAQlE;
|
|
1
|
+
{"version":3,"file":"groups.d.ts","sourceRoot":"","sources":["../../../src/dashboard/web/groups.ts"],"names":[],"mappings":"AA4BA,KAAK,iBAAiB,GAAG;IACvB,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC;AAMF,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAQlE;AAgED;;;kEAGkE;AAClE,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,GAAG,EAAE,cAAc,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,OAAO,CAOhF;AAED;;;;iDAIiD;AACjD,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,KAAK,CAAC;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,EACpD,UAAU,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,GACvB,MAAM,CASR;AAED,wBAAgB,iCAAiC,CAC/C,SAAS,EAAE,MAAM,EACjB,SAAS,CAAC,EAAE,OAAO,EACnB,KAAK,CAAC,EAAE,OAAO,GACd,MAAM,CAoBR;AAED,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,iBAAiB,EAAE,GAAG,MAAM,CAkB9E;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,WAAW,GAAG,MAAM,IAAI,CAq9B5D"}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// The aggregator at /api/groups fans out to all online daemons and merges chats
|
|
3
3
|
// by chatId; the dashboard displays this as a matrix where each cell shows
|
|
4
4
|
// whether a bot is a member of a given chat.
|
|
5
|
-
import { chatAvatarHtml, escapeHtml,
|
|
5
|
+
import { chatAvatarHtml, escapeHtml, t } from './ui.js';
|
|
6
6
|
import { hasExplicitChatRole, summarizeGroupProfileMatches, } from './role-profile-match.js';
|
|
7
7
|
let cache = { chats: [], bots: [] };
|
|
8
8
|
const PROFILE_ID_RE = /^[A-Za-z0-9._-]{1,64}$/;
|
|
@@ -23,31 +23,6 @@ export function suggestRoleProfileIdFromChat(value) {
|
|
|
23
23
|
.slice(0, 64);
|
|
24
24
|
return isValidProfileId(cleaned) ? cleaned : 'profile';
|
|
25
25
|
}
|
|
26
|
-
function pageHtml() {
|
|
27
|
-
return `<section class="page">
|
|
28
|
-
<div class="page-heading">
|
|
29
|
-
<div>
|
|
30
|
-
<p class="eyebrow">${t('nav.groups')}</p>
|
|
31
|
-
<h1>${t('groups.title')}</h1>
|
|
32
|
-
<p>${t('groups.subtitle')}</p>
|
|
33
|
-
</div>
|
|
34
|
-
</div>
|
|
35
|
-
<form id="g-filters" class="filters">
|
|
36
|
-
<input type="search" name="q" placeholder="${t('groups.search')}" />
|
|
37
|
-
<label><input type="checkbox" name="missing"> ${t('groups.missingOnly')}</label>
|
|
38
|
-
<button type="button" id="g-refresh">${t('groups.refresh')}</button>
|
|
39
|
-
<button type="button" id="g-create" class="primary">${t('groups.create')}</button>
|
|
40
|
-
</form>
|
|
41
|
-
<div id="g-loading">${loadingHtml()}</div>
|
|
42
|
-
<div class="table-scroll matrix-scroll" id="g-table-wrap" hidden>
|
|
43
|
-
<table>
|
|
44
|
-
<thead id="g-head"></thead>
|
|
45
|
-
<tbody id="g-body"></tbody>
|
|
46
|
-
</table>
|
|
47
|
-
</div>
|
|
48
|
-
<dialog id="g-drawer"></dialog>
|
|
49
|
-
</section>`;
|
|
50
|
-
}
|
|
51
26
|
async function loadGroups() {
|
|
52
27
|
const r = await fetch('/api/groups');
|
|
53
28
|
cache = await r.json();
|
|
@@ -171,8 +146,28 @@ export function renderAddBotsResultSummary(result) {
|
|
|
171
146
|
<ul>${items}</ul>
|
|
172
147
|
</div>`;
|
|
173
148
|
}
|
|
174
|
-
export
|
|
175
|
-
|
|
149
|
+
export function wireGroupsPage(root) {
|
|
150
|
+
let disposed = false;
|
|
151
|
+
const timers = new Set();
|
|
152
|
+
const delayResolvers = new Map();
|
|
153
|
+
const setTimer = (fn, ms) => {
|
|
154
|
+
const id = window.setTimeout(() => {
|
|
155
|
+
timers.delete(id);
|
|
156
|
+
if (!disposed)
|
|
157
|
+
fn();
|
|
158
|
+
}, ms);
|
|
159
|
+
timers.add(id);
|
|
160
|
+
return id;
|
|
161
|
+
};
|
|
162
|
+
const delay = (ms) => new Promise(resolve => {
|
|
163
|
+
const id = window.setTimeout(() => {
|
|
164
|
+
timers.delete(id);
|
|
165
|
+
delayResolvers.delete(id);
|
|
166
|
+
resolve();
|
|
167
|
+
}, ms);
|
|
168
|
+
timers.add(id);
|
|
169
|
+
delayResolvers.set(id, resolve);
|
|
170
|
+
});
|
|
176
171
|
const head = root.querySelector('#g-head');
|
|
177
172
|
const body = root.querySelector('#g-body');
|
|
178
173
|
const form = root.querySelector('#g-filters');
|
|
@@ -182,11 +177,14 @@ export async function renderGroupsPage(root) {
|
|
|
182
177
|
refreshBtn.disabled = true;
|
|
183
178
|
try {
|
|
184
179
|
await loadGroups();
|
|
180
|
+
if (disposed)
|
|
181
|
+
return;
|
|
185
182
|
rerender();
|
|
186
183
|
void refreshRoleProfileContext();
|
|
187
184
|
}
|
|
188
185
|
finally {
|
|
189
|
-
|
|
186
|
+
if (!disposed)
|
|
187
|
+
refreshBtn.disabled = false;
|
|
190
188
|
}
|
|
191
189
|
};
|
|
192
190
|
const createBtn = root.querySelector('#g-create');
|
|
@@ -194,13 +192,19 @@ export async function renderGroupsPage(root) {
|
|
|
194
192
|
// /api/groups 要扇出到所有 daemon、逐群查成员,慢——先亮 loading,回来再换表格。
|
|
195
193
|
const loadingEl = root.querySelector('#g-loading');
|
|
196
194
|
const tableWrap = root.querySelector('#g-table-wrap');
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
195
|
+
void (async () => {
|
|
196
|
+
try {
|
|
197
|
+
await loadGroups();
|
|
198
|
+
}
|
|
199
|
+
finally {
|
|
200
|
+
if (disposed)
|
|
201
|
+
return;
|
|
202
|
+
loadingEl.remove();
|
|
203
|
+
tableWrap.hidden = false;
|
|
204
|
+
rerender();
|
|
205
|
+
void refreshRoleProfileContext();
|
|
206
|
+
}
|
|
207
|
+
})();
|
|
204
208
|
async function refreshRoleProfileContext() {
|
|
205
209
|
try {
|
|
206
210
|
await loadGroupRoleProfileContext();
|
|
@@ -211,6 +215,8 @@ export async function renderGroupsPage(root) {
|
|
|
211
215
|
groupRoleContentByBot = new Map();
|
|
212
216
|
}
|
|
213
217
|
finally {
|
|
218
|
+
if (disposed)
|
|
219
|
+
return;
|
|
214
220
|
roleProfileContextLoaded = true;
|
|
215
221
|
rerender();
|
|
216
222
|
}
|
|
@@ -240,6 +246,8 @@ export async function renderGroupsPage(root) {
|
|
|
240
246
|
roleProfiles = data.profiles ?? [];
|
|
241
247
|
}
|
|
242
248
|
catch { /* profile selector is optional */ }
|
|
249
|
+
if (disposed)
|
|
250
|
+
return;
|
|
243
251
|
drawer.innerHTML = `
|
|
244
252
|
<article>
|
|
245
253
|
<header><h3>${t('groups.createTitle')}</h3></header>
|
|
@@ -305,6 +313,8 @@ export async function renderGroupsPage(root) {
|
|
|
305
313
|
}),
|
|
306
314
|
});
|
|
307
315
|
const respBody = await r.json();
|
|
316
|
+
if (disposed)
|
|
317
|
+
return;
|
|
308
318
|
if (respBody.ok && respBody.chatId) {
|
|
309
319
|
renderCreateSuccess(respBody);
|
|
310
320
|
// Lark's chat.list has eventual consistency: the chat we just
|
|
@@ -370,7 +380,9 @@ export async function renderGroupsPage(root) {
|
|
|
370
380
|
// Refresh will reconcile.
|
|
371
381
|
const delays = [600, 1200, 1200, 1200, 1200, 1200];
|
|
372
382
|
for (const d of delays) {
|
|
373
|
-
await
|
|
383
|
+
await delay(d);
|
|
384
|
+
if (disposed)
|
|
385
|
+
return;
|
|
374
386
|
let next;
|
|
375
387
|
try {
|
|
376
388
|
next = await fetchGroups();
|
|
@@ -378,6 +390,8 @@ export async function renderGroupsPage(root) {
|
|
|
378
390
|
catch {
|
|
379
391
|
continue;
|
|
380
392
|
}
|
|
393
|
+
if (disposed)
|
|
394
|
+
return;
|
|
381
395
|
const row = (next.chats ?? []).find((c) => c.chatId === chatId);
|
|
382
396
|
if (row && allExpectedInChat(row, expectedBotIds)) {
|
|
383
397
|
cache = next;
|
|
@@ -455,7 +469,7 @@ export async function renderGroupsPage(root) {
|
|
|
455
469
|
b.onclick = () => {
|
|
456
470
|
navigator.clipboard.writeText(b.dataset.copy ?? '');
|
|
457
471
|
b.textContent = t('sessions.copied');
|
|
458
|
-
|
|
472
|
+
setTimer(() => { b.textContent = t('sessions.copy'); }, 800);
|
|
459
473
|
};
|
|
460
474
|
});
|
|
461
475
|
drawer.querySelector('#g-create-close').onclick = () => drawer.close();
|
|
@@ -532,9 +546,7 @@ export async function renderGroupsPage(root) {
|
|
|
532
546
|
</td>
|
|
533
547
|
</tr>`).join('');
|
|
534
548
|
}
|
|
535
|
-
|
|
536
|
-
void refreshRoleProfileContext();
|
|
537
|
-
body.addEventListener('click', async (e) => {
|
|
549
|
+
const onAddBotsClick = async (e) => {
|
|
538
550
|
const btn = e.target.closest('button.add-bots');
|
|
539
551
|
if (!btn)
|
|
540
552
|
return;
|
|
@@ -589,6 +601,8 @@ export async function renderGroupsPage(root) {
|
|
|
589
601
|
body: JSON.stringify({ larkAppIds: ids }),
|
|
590
602
|
});
|
|
591
603
|
const respBody = await r.json();
|
|
604
|
+
if (disposed)
|
|
605
|
+
return;
|
|
592
606
|
if (respBody.error === 'no_proxy_bot') {
|
|
593
607
|
setDialogStatus(statusEl, renderDialogError('无法添加 bot', '当前群里没有可代理操作的 bot。请先在飞书里手动拉入一个 bot,然后重试。'));
|
|
594
608
|
}
|
|
@@ -597,11 +611,15 @@ export async function renderGroupsPage(root) {
|
|
|
597
611
|
setDialogStatus(statusEl, resultHtml);
|
|
598
612
|
try {
|
|
599
613
|
await loadGroups();
|
|
614
|
+
if (disposed)
|
|
615
|
+
return;
|
|
600
616
|
rerender();
|
|
601
617
|
void refreshRoleProfileContext();
|
|
602
618
|
}
|
|
603
619
|
catch (e) {
|
|
604
|
-
|
|
620
|
+
if (!disposed) {
|
|
621
|
+
setDialogStatus(statusEl, `${resultHtml}${renderDialogError('刷新失败', `添加结果已返回,但刷新群组列表失败:${e}`)}`);
|
|
622
|
+
}
|
|
605
623
|
}
|
|
606
624
|
}
|
|
607
625
|
else {
|
|
@@ -612,11 +630,13 @@ export async function renderGroupsPage(root) {
|
|
|
612
630
|
setDialogStatus(statusEl, renderDialogError('网络错误', e));
|
|
613
631
|
}
|
|
614
632
|
finally {
|
|
615
|
-
|
|
633
|
+
if (!disposed)
|
|
634
|
+
restoreSubmit(submitBtn, t('groups.addBots'));
|
|
616
635
|
}
|
|
617
636
|
};
|
|
618
|
-
}
|
|
619
|
-
body.addEventListener('click',
|
|
637
|
+
};
|
|
638
|
+
body.addEventListener('click', onAddBotsClick);
|
|
639
|
+
const onSaveProfileClick = async (e) => {
|
|
620
640
|
const btn = e.target.closest('button.save-profile');
|
|
621
641
|
if (!btn)
|
|
622
642
|
return;
|
|
@@ -626,7 +646,8 @@ export async function renderGroupsPage(root) {
|
|
|
626
646
|
if (!chat)
|
|
627
647
|
return;
|
|
628
648
|
await saveGroupRolesAsProfile(chat, btn);
|
|
629
|
-
}
|
|
649
|
+
};
|
|
650
|
+
body.addEventListener('click', onSaveProfileClick);
|
|
630
651
|
async function saveGroupRolesAsProfile(chat, btn) {
|
|
631
652
|
const suggestedByName = suggestRoleProfileIdFromChat(chat.name ?? '');
|
|
632
653
|
const suggested = suggestedByName === 'profile'
|
|
@@ -640,11 +661,15 @@ export async function renderGroupsPage(root) {
|
|
|
640
661
|
collectGroupProfileEntries(chat),
|
|
641
662
|
fetchRoleProfileSummaries(),
|
|
642
663
|
]);
|
|
664
|
+
if (disposed)
|
|
665
|
+
return;
|
|
643
666
|
openSaveProfileDialog(chat, suggested, entries, profiles);
|
|
644
667
|
}
|
|
645
668
|
finally {
|
|
646
|
-
|
|
647
|
-
|
|
669
|
+
if (!disposed) {
|
|
670
|
+
btn.disabled = false;
|
|
671
|
+
btn.textContent = originalText;
|
|
672
|
+
}
|
|
648
673
|
}
|
|
649
674
|
}
|
|
650
675
|
async function collectGroupProfileEntries(chat) {
|
|
@@ -851,6 +876,8 @@ export async function renderGroupsPage(root) {
|
|
|
851
876
|
});
|
|
852
877
|
return r.ok;
|
|
853
878
|
}));
|
|
879
|
+
if (disposed)
|
|
880
|
+
return;
|
|
854
881
|
const saved = results.filter(Boolean).length;
|
|
855
882
|
if (saved !== entries.length) {
|
|
856
883
|
statusEl.textContent = t('groups.saveProfileFailed', { saved, total: entries.length });
|
|
@@ -864,7 +891,9 @@ export async function renderGroupsPage(root) {
|
|
|
864
891
|
statusEl.textContent = t('groups.saveProfileDone', { name: profileId, count: saved });
|
|
865
892
|
statusEl.className = 'g-save-profile-status ok';
|
|
866
893
|
await refreshRoleProfileContext();
|
|
867
|
-
|
|
894
|
+
if (disposed)
|
|
895
|
+
return;
|
|
896
|
+
setTimer(() => drawer.close(), 700);
|
|
868
897
|
}
|
|
869
898
|
catch (err) {
|
|
870
899
|
statusEl.textContent = String(err);
|
|
@@ -876,7 +905,7 @@ export async function renderGroupsPage(root) {
|
|
|
876
905
|
}
|
|
877
906
|
};
|
|
878
907
|
}
|
|
879
|
-
|
|
908
|
+
const onManageChatClick = async (e) => {
|
|
880
909
|
const btn = e.target.closest('button.manage-chat');
|
|
881
910
|
if (!btn)
|
|
882
911
|
return;
|
|
@@ -886,7 +915,8 @@ export async function renderGroupsPage(root) {
|
|
|
886
915
|
if (!chat)
|
|
887
916
|
return;
|
|
888
917
|
openManageDrawer(chat);
|
|
889
|
-
}
|
|
918
|
+
};
|
|
919
|
+
body.addEventListener('click', onManageChatClick);
|
|
890
920
|
function openManageDrawer(chat) {
|
|
891
921
|
const inChat = chat.memberBots.filter((m) => m.inChat);
|
|
892
922
|
// Lark `owner_id` returns app_id format for bot owners (string match works).
|
|
@@ -978,6 +1008,8 @@ export async function renderGroupsPage(root) {
|
|
|
978
1008
|
})
|
|
979
1009
|
: await fetch(url, { method: 'DELETE' });
|
|
980
1010
|
const body = await r.json().catch(() => ({}));
|
|
1011
|
+
if (disposed)
|
|
1012
|
+
return;
|
|
981
1013
|
if (r.ok && body.ok) {
|
|
982
1014
|
statusEl.textContent = want
|
|
983
1015
|
? `✓ 已绑定 → ${body.resolvedPath ?? wd}`
|
|
@@ -987,6 +1019,8 @@ export async function renderGroupsPage(root) {
|
|
|
987
1019
|
// (current row reflects the just-saved values).
|
|
988
1020
|
try {
|
|
989
1021
|
await loadGroups();
|
|
1022
|
+
if (disposed)
|
|
1023
|
+
return;
|
|
990
1024
|
rerender();
|
|
991
1025
|
void refreshRoleProfileContext();
|
|
992
1026
|
}
|
|
@@ -1022,6 +1056,8 @@ export async function renderGroupsPage(root) {
|
|
|
1022
1056
|
body: JSON.stringify({ larkAppIds: checked }),
|
|
1023
1057
|
});
|
|
1024
1058
|
const respBody = await r.json();
|
|
1059
|
+
if (disposed)
|
|
1060
|
+
return;
|
|
1025
1061
|
const lines = (respBody.result ?? []).map((x) => {
|
|
1026
1062
|
if (!x.ok)
|
|
1027
1063
|
return `${x.larkAppId}: 失败 (${x.error ?? 'unknown'})`;
|
|
@@ -1035,6 +1071,8 @@ export async function renderGroupsPage(root) {
|
|
|
1035
1071
|
}).join('\n');
|
|
1036
1072
|
alert(lines || `Unexpected: ${JSON.stringify(respBody)}`);
|
|
1037
1073
|
await loadGroups();
|
|
1074
|
+
if (disposed)
|
|
1075
|
+
return;
|
|
1038
1076
|
rerender();
|
|
1039
1077
|
void refreshRoleProfileContext();
|
|
1040
1078
|
}
|
|
@@ -1042,7 +1080,8 @@ export async function renderGroupsPage(root) {
|
|
|
1042
1080
|
alert('Network error: ' + e);
|
|
1043
1081
|
}
|
|
1044
1082
|
finally {
|
|
1045
|
-
|
|
1083
|
+
if (!disposed)
|
|
1084
|
+
drawer.close();
|
|
1046
1085
|
}
|
|
1047
1086
|
};
|
|
1048
1087
|
drawer.querySelector('#g-disband-btn').onclick = async () => {
|
|
@@ -1063,6 +1102,8 @@ export async function renderGroupsPage(root) {
|
|
|
1063
1102
|
body: JSON.stringify({ larkAppId: m.larkAppId }),
|
|
1064
1103
|
});
|
|
1065
1104
|
const respBody = await r.json();
|
|
1105
|
+
if (disposed)
|
|
1106
|
+
return;
|
|
1066
1107
|
if (respBody.ok) {
|
|
1067
1108
|
const closed = (respBody.closedSessions ?? []);
|
|
1068
1109
|
const failed = closed.filter(c => !c.ok).length;
|
|
@@ -1072,6 +1113,8 @@ export async function renderGroupsPage(root) {
|
|
|
1072
1113
|
: failed === 0 ? `\n关闭了 ${ok} 个会话。` : `\n关闭了 ${ok} 个会话,${failed} 个会话关闭失败。`;
|
|
1073
1114
|
alert(`已解散(由 ${m.botName ?? m.larkAppId} 执行)${closedNote}`);
|
|
1074
1115
|
await loadGroups();
|
|
1116
|
+
if (disposed)
|
|
1117
|
+
return;
|
|
1075
1118
|
rerender();
|
|
1076
1119
|
void refreshRoleProfileContext();
|
|
1077
1120
|
drawer.close();
|
|
@@ -1087,5 +1130,23 @@ export async function renderGroupsPage(root) {
|
|
|
1087
1130
|
};
|
|
1088
1131
|
}
|
|
1089
1132
|
form.addEventListener('input', rerender);
|
|
1133
|
+
return () => {
|
|
1134
|
+
disposed = true;
|
|
1135
|
+
for (const id of timers)
|
|
1136
|
+
window.clearTimeout(id);
|
|
1137
|
+
timers.clear();
|
|
1138
|
+
for (const resolve of delayResolvers.values())
|
|
1139
|
+
resolve();
|
|
1140
|
+
delayResolvers.clear();
|
|
1141
|
+
refreshBtn.onclick = null;
|
|
1142
|
+
createBtn.onclick = null;
|
|
1143
|
+
form.removeEventListener('input', rerender);
|
|
1144
|
+
body.removeEventListener('click', onAddBotsClick);
|
|
1145
|
+
body.removeEventListener('click', onSaveProfileClick);
|
|
1146
|
+
body.removeEventListener('click', onManageChatClick);
|
|
1147
|
+
if (drawer.open)
|
|
1148
|
+
drawer.close();
|
|
1149
|
+
drawer.replaceChildren();
|
|
1150
|
+
};
|
|
1090
1151
|
}
|
|
1091
1152
|
//# sourceMappingURL=groups.js.map
|