@uxland/primary-shell 7.41.2 → 7.41.3
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/dist/{component-QbgEdy0I.js → component-D15ByiOA.js} +2 -2
- package/dist/{component-QbgEdy0I.js.map → component-D15ByiOA.js.map} +1 -1
- package/dist/{index-CNpXjSPp.js → index-DSWQpDr0.js} +19 -2
- package/dist/index-DSWQpDr0.js.map +1 -0
- package/dist/index.js +1 -1
- package/dist/index.umd.cjs +1 -1
- package/dist/index.umd.cjs.map +1 -1
- package/dist/primary/shell/src/api/plugin-busy-manager/plugin-busy-list/component.d.ts +2 -2
- package/dist/primary/shell/src/features/exit/handler.d.ts +1 -0
- package/package.json +1 -1
- package/src/api/plugin-busy-manager/plugin-busy-list/component.ts +2 -2
- package/src/api/plugin-busy-manager/plugin-busy-list/template.ts +3 -3
- package/src/features/exit/handler.test.ts +65 -5
- package/src/features/exit/handler.ts +26 -3
- package/dist/index-CNpXjSPp.js.map +0 -1
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { LitElement } from 'lit';
|
|
2
|
-
import {
|
|
2
|
+
import { PluginTask } from '../plugin-busy-manager';
|
|
3
3
|
export declare class PluginBusyList extends LitElement {
|
|
4
4
|
static styles: import('lit').CSSResult;
|
|
5
5
|
render(): import('lit').TemplateResult<1>;
|
|
6
6
|
data: {
|
|
7
|
-
busyTasks:
|
|
7
|
+
busyTasks: PluginTask[];
|
|
8
8
|
};
|
|
9
9
|
}
|
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { LitElement, css, html, unsafeCSS } from "lit";
|
|
2
|
-
import {
|
|
2
|
+
import { PluginTask } from "../plugin-busy-manager";
|
|
3
3
|
import styles from "./styles.css?inline";
|
|
4
4
|
import { template } from "./template";
|
|
5
5
|
|
|
@@ -12,5 +12,5 @@ export class PluginBusyList extends LitElement {
|
|
|
12
12
|
return html`${template(this)}`;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
data: { busyTasks:
|
|
15
|
+
data: { busyTasks: PluginTask[] };
|
|
16
16
|
}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { html } from "lit";
|
|
2
|
-
import { PluginBusyList } from "./component";
|
|
3
|
-
import { PluginBusyTask } from "../plugin-busy-manager";
|
|
4
2
|
import { translate } from "../../../locales";
|
|
3
|
+
import { PluginTask } from "../plugin-busy-manager";
|
|
4
|
+
import { PluginBusyList } from "./component";
|
|
5
5
|
|
|
6
6
|
export const template = (props: PluginBusyList) => html`
|
|
7
7
|
<div class="container">
|
|
8
8
|
<div class="title">${translate("busyManager.title")}</div>
|
|
9
9
|
<div class="list">
|
|
10
10
|
${props.data?.busyTasks?.map(
|
|
11
|
-
(item:
|
|
11
|
+
(item: PluginTask) => html`
|
|
12
12
|
<div class="plugin-busy-item">
|
|
13
13
|
<dss-typography tag="div" variant="body-3" fontweight="regular">
|
|
14
14
|
${item.taskDescription}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
2
|
+
import { PrimariaApi } from "../../api/api";
|
|
3
|
+
import { PluginBusyList } from "../../api/plugin-busy-manager/plugin-busy-list/component";
|
|
4
|
+
import { disposeShell, raiseCloseEvent, raiseCustomCloseEvent } from "../../disposer";
|
|
5
|
+
import { disposePlugins } from "../../handle-plugins";
|
|
2
6
|
import { ExitShellHandler } from "./handler";
|
|
3
7
|
import { ExitShell } from "./request";
|
|
4
|
-
import { disposePlugins } from "../../handle-plugins";
|
|
5
|
-
import { disposeShell, raiseCloseEvent, raiseCustomCloseEvent } from "../../disposer";
|
|
6
|
-
import { PrimariaApi } from "../../api/api";
|
|
7
8
|
|
|
8
9
|
vi.mock("../../handle-plugins", () => ({
|
|
9
10
|
disposePlugins: vi.fn(),
|
|
@@ -18,7 +19,13 @@ vi.mock("../../disposer", () => ({
|
|
|
18
19
|
const createMockApi = (): PrimariaApi =>
|
|
19
20
|
({
|
|
20
21
|
exitGuardManager: {
|
|
21
|
-
canExit: vi.fn(),
|
|
22
|
+
canExit: vi.fn().mockResolvedValue(true),
|
|
23
|
+
},
|
|
24
|
+
pluginBusyManager: {
|
|
25
|
+
getTasks: vi.fn().mockReturnValue([]),
|
|
26
|
+
},
|
|
27
|
+
interactionService: {
|
|
28
|
+
confirm: vi.fn(),
|
|
22
29
|
},
|
|
23
30
|
notificationService: {
|
|
24
31
|
error: vi.fn(),
|
|
@@ -120,4 +127,57 @@ describe("ExitShellHandler", () => {
|
|
|
120
127
|
expect(raiseCloseEvent).toHaveBeenCalled();
|
|
121
128
|
expect(raiseCustomCloseEvent).not.toHaveBeenCalled();
|
|
122
129
|
});
|
|
130
|
+
|
|
131
|
+
describe("legacy pluginBusyManager fallback", () => {
|
|
132
|
+
it("asks for confirmation when canExit allows but legacy busy tasks exist", async () => {
|
|
133
|
+
const busyTasks = [{ taskId: "t1", taskDescription: "saving draft" }];
|
|
134
|
+
const message = { ecapEvent: {} } as ExitShell;
|
|
135
|
+
(mockApi.exitGuardManager.canExit as any).mockResolvedValue(true);
|
|
136
|
+
(mockApi.pluginBusyManager.getTasks as any).mockReturnValue(busyTasks);
|
|
137
|
+
(mockApi.interactionService.confirm as any).mockResolvedValue({ confirmed: true });
|
|
138
|
+
(disposePlugins as any).mockResolvedValue(undefined);
|
|
139
|
+
|
|
140
|
+
await handler.handle(message);
|
|
141
|
+
|
|
142
|
+
expect(mockApi.interactionService.confirm).toHaveBeenCalledWith(
|
|
143
|
+
{ busyTasks },
|
|
144
|
+
{ component: PluginBusyList },
|
|
145
|
+
{
|
|
146
|
+
title: "actions.askExit",
|
|
147
|
+
state: "error",
|
|
148
|
+
confirmButtonText: "Sí",
|
|
149
|
+
cancelButtonText: "No",
|
|
150
|
+
},
|
|
151
|
+
);
|
|
152
|
+
expect(disposePlugins).toHaveBeenCalled();
|
|
153
|
+
expect(disposeShell).toHaveBeenCalled();
|
|
154
|
+
expect(raiseCustomCloseEvent).toHaveBeenCalledWith(message);
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
it("aborts the exit when the legacy busy-task confirmation is declined", async () => {
|
|
158
|
+
const busyTasks = [{ taskId: "t1", taskDescription: "saving draft" }];
|
|
159
|
+
const message = { ecapEvent: {} } as ExitShell;
|
|
160
|
+
(mockApi.exitGuardManager.canExit as any).mockResolvedValue(true);
|
|
161
|
+
(mockApi.pluginBusyManager.getTasks as any).mockReturnValue(busyTasks);
|
|
162
|
+
(mockApi.interactionService.confirm as any).mockResolvedValue({ confirmed: false });
|
|
163
|
+
|
|
164
|
+
await handler.handle(message);
|
|
165
|
+
|
|
166
|
+
expect(mockApi.interactionService.confirm).toHaveBeenCalled();
|
|
167
|
+
expect(disposePlugins).not.toHaveBeenCalled();
|
|
168
|
+
expect(disposeShell).not.toHaveBeenCalled();
|
|
169
|
+
expect(raiseCustomCloseEvent).not.toHaveBeenCalled();
|
|
170
|
+
expect(raiseCloseEvent).not.toHaveBeenCalled();
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
it("does not consult legacy busy tasks when an ExitGuard already vetoed the exit", async () => {
|
|
174
|
+
const message = { ecapEvent: {} } as ExitShell;
|
|
175
|
+
(mockApi.exitGuardManager.canExit as any).mockResolvedValue(false);
|
|
176
|
+
|
|
177
|
+
await handler.handle(message);
|
|
178
|
+
|
|
179
|
+
expect(mockApi.pluginBusyManager.getTasks).not.toHaveBeenCalled();
|
|
180
|
+
expect(mockApi.interactionService.confirm).not.toHaveBeenCalled();
|
|
181
|
+
});
|
|
182
|
+
});
|
|
123
183
|
});
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
-
import { PrimariaApi } from "../../api/api";
|
|
2
|
-
import { TYPES } from "../../infrastructure/ioc/types";
|
|
3
1
|
import { inject } from "inversify";
|
|
4
|
-
import {
|
|
2
|
+
import { PrimariaApi } from "../../api/api";
|
|
3
|
+
import { PluginBusyList } from "../../api/plugin-busy-manager/plugin-busy-list/component";
|
|
4
|
+
import { PluginTask } from "../../api/plugin-busy-manager/plugin-busy-manager";
|
|
5
5
|
import { disposeShell, raiseCloseEvent, raiseCustomCloseEvent } from "../../disposer";
|
|
6
6
|
import { disposePlugins } from "../../handle-plugins";
|
|
7
|
+
import { TYPES } from "../../infrastructure/ioc/types";
|
|
7
8
|
import { translate } from "../../locales";
|
|
9
|
+
import { ExitShell } from "./request";
|
|
8
10
|
|
|
9
11
|
export class ExitShellHandler {
|
|
10
12
|
constructor(@inject(TYPES.primaryApi) private api: PrimariaApi) {}
|
|
@@ -15,6 +17,14 @@ export class ExitShellHandler {
|
|
|
15
17
|
const canExit = await this.api.exitGuardManager.canExit();
|
|
16
18
|
if (!canExit) return;
|
|
17
19
|
|
|
20
|
+
// Backwards-compat: external plugins still using the deprecated pluginBusyManager
|
|
21
|
+
// would otherwise lose their exit-confirmation modal. Remove once all consumers migrate.
|
|
22
|
+
const busyTasks = this.api.pluginBusyManager.getTasks();
|
|
23
|
+
if (busyTasks.length > 0) {
|
|
24
|
+
const { confirmed } = await this.askForClose(busyTasks);
|
|
25
|
+
if (!confirmed) return;
|
|
26
|
+
}
|
|
27
|
+
|
|
18
28
|
// Per si un plugin tarda molt en fer dispose, màxim deixarem 5 segons, per no interrompre el tancar infinitament
|
|
19
29
|
await Promise.race([
|
|
20
30
|
disposePlugins(), // S'intenta executar un dispose normal
|
|
@@ -32,6 +42,19 @@ export class ExitShellHandler {
|
|
|
32
42
|
return new Promise<void>((resolve) => setTimeout(resolve, ms));
|
|
33
43
|
}
|
|
34
44
|
|
|
45
|
+
private askForClose(busyTasks: PluginTask[]) {
|
|
46
|
+
return this.api.interactionService.confirm(
|
|
47
|
+
{ busyTasks },
|
|
48
|
+
{ component: PluginBusyList },
|
|
49
|
+
{
|
|
50
|
+
title: translate("actions.askExit"),
|
|
51
|
+
state: "error",
|
|
52
|
+
confirmButtonText: "Sí",
|
|
53
|
+
cancelButtonText: "No",
|
|
54
|
+
},
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
|
|
35
58
|
private emitClose(exitEvent?: ExitShell): void {
|
|
36
59
|
if (exitEvent) {
|
|
37
60
|
raiseCustomCloseEvent(exitEvent);
|