@jupyterlab/extensionmanager-extension 4.0.0-alpha.2 → 4.0.0-alpha.21
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/lib/index.js +61 -43
- package/lib/index.js.map +1 -1
- package/package.json +11 -10
- package/schema/plugin.json +3 -21
- package/src/index.ts +191 -0
package/lib/index.js
CHANGED
|
@@ -4,11 +4,11 @@
|
|
|
4
4
|
* @packageDocumentation
|
|
5
5
|
* @module extensionmanager-extension
|
|
6
6
|
*/
|
|
7
|
-
import {
|
|
7
|
+
import { ILayoutRestorer } from '@jupyterlab/application';
|
|
8
8
|
import { Dialog, ICommandPalette, showDialog } from '@jupyterlab/apputils';
|
|
9
|
-
import {
|
|
9
|
+
import { ExtensionsPanel, ListModel } from '@jupyterlab/extensionmanager';
|
|
10
10
|
import { ISettingRegistry } from '@jupyterlab/settingregistry';
|
|
11
|
-
import { ITranslator } from '@jupyterlab/translation';
|
|
11
|
+
import { ITranslator, nullTranslator } from '@jupyterlab/translation';
|
|
12
12
|
import { extensionIcon } from '@jupyterlab/ui-components';
|
|
13
13
|
const PLUGIN_ID = '@jupyterlab/extensionmanager-extension:plugin';
|
|
14
14
|
/**
|
|
@@ -25,52 +25,71 @@ var CommandIDs;
|
|
|
25
25
|
const plugin = {
|
|
26
26
|
id: PLUGIN_ID,
|
|
27
27
|
autoStart: true,
|
|
28
|
-
requires: [ISettingRegistry
|
|
29
|
-
optional: [
|
|
30
|
-
activate: async (app, registry, translator,
|
|
28
|
+
requires: [ISettingRegistry],
|
|
29
|
+
optional: [ITranslator, ILayoutRestorer, ICommandPalette],
|
|
30
|
+
activate: async (app, registry, translator, restorer, palette) => {
|
|
31
|
+
const { commands, shell, serviceManager } = app;
|
|
32
|
+
translator = translator !== null && translator !== void 0 ? translator : nullTranslator;
|
|
31
33
|
const trans = translator.load('jupyterlab');
|
|
32
|
-
const
|
|
33
|
-
let enabled = settings.composite['enabled'] === true;
|
|
34
|
-
const { commands, serviceManager } = app;
|
|
35
|
-
let view;
|
|
34
|
+
const model = new ListModel(serviceManager, translator);
|
|
36
35
|
const createView = () => {
|
|
37
|
-
const v = new
|
|
36
|
+
const v = new ExtensionsPanel({ model, translator: translator });
|
|
38
37
|
v.id = 'extensionmanager.main-view';
|
|
39
38
|
v.title.icon = extensionIcon;
|
|
40
39
|
v.title.caption = trans.__('Extension Manager');
|
|
40
|
+
v.node.setAttribute('role', 'region');
|
|
41
|
+
v.node.setAttribute('aria-label', trans.__('Extension Manager section'));
|
|
41
42
|
if (restorer) {
|
|
42
43
|
restorer.add(v, v.id);
|
|
43
44
|
}
|
|
45
|
+
shell.add(v, 'left', { rank: 1000 });
|
|
44
46
|
return v;
|
|
45
47
|
};
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
view.node.setAttribute('role', 'region');
|
|
49
|
-
view.node.setAttribute('aria-label', trans.__('Extension Manager section'));
|
|
50
|
-
labShell.add(view, 'left', { rank: 1000 });
|
|
51
|
-
}
|
|
48
|
+
// Create a view by default, so it can be restored when loading the workspace.
|
|
49
|
+
let view = createView();
|
|
52
50
|
// If the extension is enabled or disabled,
|
|
53
51
|
// add or remove it from the left area.
|
|
54
52
|
Promise.all([app.restored, registry.load(PLUGIN_ID)])
|
|
55
53
|
.then(([, settings]) => {
|
|
54
|
+
model.isDisclaimed = settings.get('disclaimed').composite;
|
|
55
|
+
model.isEnabled = settings.get('enabled').composite;
|
|
56
|
+
model.stateChanged.connect(() => {
|
|
57
|
+
if (model.isDisclaimed !==
|
|
58
|
+
settings.get('disclaimed').composite) {
|
|
59
|
+
settings.set('disclaimed', model.isDisclaimed).catch(reason => {
|
|
60
|
+
console.error(`Failed to set setting 'disclaimed'.\n${reason}`);
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
if (model.isEnabled !== settings.get('enabled').composite) {
|
|
64
|
+
settings.set('enabled', model.isEnabled).catch(reason => {
|
|
65
|
+
console.error(`Failed to set setting 'enabled'.\n${reason}`);
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
if (model.isEnabled) {
|
|
70
|
+
view = view !== null && view !== void 0 ? view : createView();
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
view === null || view === void 0 ? void 0 : view.dispose();
|
|
74
|
+
view = null;
|
|
75
|
+
}
|
|
56
76
|
settings.changed.connect(async () => {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
if (labShell) {
|
|
68
|
-
labShell.add(view, 'left', { rank: 1000 });
|
|
77
|
+
model.isDisclaimed = settings.get('disclaimed').composite;
|
|
78
|
+
model.isEnabled = settings.get('enabled').composite;
|
|
79
|
+
app.commands.notifyCommandChanged(CommandIDs.toggle);
|
|
80
|
+
if (model.isEnabled) {
|
|
81
|
+
if (view === null || !view.isAttached) {
|
|
82
|
+
const accepted = await Private.showWarning(trans);
|
|
83
|
+
if (!accepted) {
|
|
84
|
+
void settings.set('enabled', false);
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
69
87
|
}
|
|
88
|
+
view = view !== null && view !== void 0 ? view : createView();
|
|
70
89
|
}
|
|
71
|
-
else
|
|
72
|
-
|
|
73
|
-
view
|
|
90
|
+
else {
|
|
91
|
+
view === null || view === void 0 ? void 0 : view.dispose();
|
|
92
|
+
view = null;
|
|
74
93
|
}
|
|
75
94
|
});
|
|
76
95
|
})
|
|
@@ -81,25 +100,25 @@ const plugin = {
|
|
|
81
100
|
label: trans.__('Extension Manager'),
|
|
82
101
|
execute: () => {
|
|
83
102
|
if (view) {
|
|
84
|
-
|
|
103
|
+
shell.activateById(view.id);
|
|
85
104
|
}
|
|
86
105
|
},
|
|
87
|
-
isVisible: () =>
|
|
106
|
+
isVisible: () => model.isEnabled
|
|
88
107
|
});
|
|
89
108
|
commands.addCommand(CommandIDs.toggle, {
|
|
90
109
|
label: trans.__('Enable Extension Manager'),
|
|
91
110
|
execute: () => {
|
|
92
111
|
if (registry) {
|
|
93
|
-
void registry.set(plugin.id, 'enabled', !
|
|
112
|
+
void registry.set(plugin.id, 'enabled', !model.isEnabled);
|
|
94
113
|
}
|
|
95
114
|
},
|
|
96
|
-
isToggled: () =>
|
|
97
|
-
isEnabled: () => serviceManager.builder.isAvailable
|
|
115
|
+
isToggled: () => model.isEnabled
|
|
98
116
|
});
|
|
99
|
-
const category = trans.__('Extension Manager');
|
|
100
|
-
const command = CommandIDs.toggle;
|
|
101
117
|
if (palette) {
|
|
102
|
-
palette.addItem({
|
|
118
|
+
palette.addItem({
|
|
119
|
+
command: CommandIDs.toggle,
|
|
120
|
+
category: trans.__('Extension Manager')
|
|
121
|
+
});
|
|
103
122
|
}
|
|
104
123
|
}
|
|
105
124
|
};
|
|
@@ -118,7 +137,7 @@ var Private;
|
|
|
118
137
|
* @returns whether the user accepted the dialog.
|
|
119
138
|
*/
|
|
120
139
|
async function showWarning(trans) {
|
|
121
|
-
|
|
140
|
+
const result = await showDialog({
|
|
122
141
|
title: trans.__('Enable Extension Manager?'),
|
|
123
142
|
body: trans.__(`Thanks for trying out JupyterLab's extension manager.
|
|
124
143
|
The JupyterLab development team is excited to have a robust
|
|
@@ -130,9 +149,8 @@ Do you want to continue?`),
|
|
|
130
149
|
Dialog.cancelButton({ label: trans.__('Disable') }),
|
|
131
150
|
Dialog.warnButton({ label: trans.__('Enable') })
|
|
132
151
|
]
|
|
133
|
-
}).then(result => {
|
|
134
|
-
return result.button.accept;
|
|
135
152
|
});
|
|
153
|
+
return result.button.accept;
|
|
136
154
|
}
|
|
137
155
|
Private.showWarning = showWarning;
|
|
138
156
|
})(Private || (Private = {}));
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,0CAA0C;AAC1C,2DAA2D;AAC3D;;;GAGG;AAEH,OAAO,EACL,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jupyterlab/extensionmanager-extension",
|
|
3
|
-
"version": "4.0.0-alpha.
|
|
3
|
+
"version": "4.0.0-alpha.21",
|
|
4
4
|
"description": "JupyterLab - Extension Manager Extension",
|
|
5
5
|
"homepage": "https://github.com/jupyterlab/jupyterlab",
|
|
6
6
|
"bugs": {
|
|
@@ -29,7 +29,8 @@
|
|
|
29
29
|
"schema/*.json",
|
|
30
30
|
"listing/*.json",
|
|
31
31
|
"style/*.css",
|
|
32
|
-
"style/index.js"
|
|
32
|
+
"style/index.js",
|
|
33
|
+
"src/**/*.{ts,tsx}"
|
|
33
34
|
],
|
|
34
35
|
"scripts": {
|
|
35
36
|
"build": "tsc -b",
|
|
@@ -38,17 +39,17 @@
|
|
|
38
39
|
"watch": "tsc -b --watch"
|
|
39
40
|
},
|
|
40
41
|
"dependencies": {
|
|
41
|
-
"@jupyterlab/application": "^4.0.0-alpha.
|
|
42
|
-
"@jupyterlab/apputils": "^4.0.0-alpha.
|
|
43
|
-
"@jupyterlab/extensionmanager": "^4.0.0-alpha.
|
|
44
|
-
"@jupyterlab/settingregistry": "^4.0.0-alpha.
|
|
45
|
-
"@jupyterlab/translation": "^4.0.0-alpha.
|
|
46
|
-
"@jupyterlab/ui-components": "^4.0.0-alpha.
|
|
42
|
+
"@jupyterlab/application": "^4.0.0-alpha.21",
|
|
43
|
+
"@jupyterlab/apputils": "^4.0.0-alpha.21",
|
|
44
|
+
"@jupyterlab/extensionmanager": "^4.0.0-alpha.21",
|
|
45
|
+
"@jupyterlab/settingregistry": "^4.0.0-alpha.21",
|
|
46
|
+
"@jupyterlab/translation": "^4.0.0-alpha.21",
|
|
47
|
+
"@jupyterlab/ui-components": "^4.0.0-alpha.36"
|
|
47
48
|
},
|
|
48
49
|
"devDependencies": {
|
|
49
50
|
"rimraf": "~3.0.0",
|
|
50
|
-
"typedoc": "~0.
|
|
51
|
-
"typescript": "~
|
|
51
|
+
"typedoc": "~0.23.25",
|
|
52
|
+
"typescript": "~5.0.1-rc"
|
|
52
53
|
},
|
|
53
54
|
"publishConfig": {
|
|
54
55
|
"access": "public"
|
package/schema/plugin.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"title": "Extension Manager",
|
|
3
3
|
"description": "Extension manager settings.",
|
|
4
|
-
"jupyter.lab.setting-icon": "ui-components:
|
|
4
|
+
"jupyter.lab.setting-icon": "ui-components:extension",
|
|
5
5
|
"jupyter.lab.setting-icon-label": "Extension Manager",
|
|
6
6
|
"jupyter.lab.menus": {
|
|
7
7
|
"main": [
|
|
@@ -43,33 +43,15 @@
|
|
|
43
43
|
"properties": {
|
|
44
44
|
"enabled": {
|
|
45
45
|
"title": "Enabled Status",
|
|
46
|
-
"description": "Enables extension manager
|
|
46
|
+
"description": "Enables extension manager.\nWARNING: installing untrusted extensions may be unsafe.",
|
|
47
47
|
"default": true,
|
|
48
48
|
"type": "boolean"
|
|
49
49
|
},
|
|
50
50
|
"disclaimed": {
|
|
51
51
|
"title": "Disclaimed Status",
|
|
52
|
-
"description": "Whether the user
|
|
52
|
+
"description": "Whether the user agrees the access to external web services and understands extensions may introduce security risks or contain malicious code that runs on his machine.",
|
|
53
53
|
"default": false,
|
|
54
54
|
"type": "boolean"
|
|
55
|
-
},
|
|
56
|
-
"npmRegistry": {
|
|
57
|
-
"title": "NPM Registry",
|
|
58
|
-
"description": "The URI of the NPM registry to use for searching for jupyterlab extensions",
|
|
59
|
-
"default": "https://registry.npmjs.org/-/v1/",
|
|
60
|
-
"type": "string"
|
|
61
|
-
},
|
|
62
|
-
"npmCdn": {
|
|
63
|
-
"title": "NPM CDN",
|
|
64
|
-
"description": "The URI of the CDN to use for fetching full package data",
|
|
65
|
-
"default": "https://unpkg.com",
|
|
66
|
-
"type": "string"
|
|
67
|
-
},
|
|
68
|
-
"enableCdn": {
|
|
69
|
-
"title": "Enable CDN",
|
|
70
|
-
"description": "Enables using the CDN to fetch full package data. Otherwise, the configured NPM registry will be used. Due to a lack of CORS support by NPM registry, only disable if supplying a custom registry",
|
|
71
|
-
"default": true,
|
|
72
|
-
"type": "boolean"
|
|
73
55
|
}
|
|
74
56
|
},
|
|
75
57
|
"additionalProperties": false,
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
// Copyright (c) Jupyter Development Team.
|
|
2
|
+
// Distributed under the terms of the Modified BSD License.
|
|
3
|
+
/**
|
|
4
|
+
* @packageDocumentation
|
|
5
|
+
* @module extensionmanager-extension
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import {
|
|
9
|
+
ILayoutRestorer,
|
|
10
|
+
JupyterFrontEnd,
|
|
11
|
+
JupyterFrontEndPlugin
|
|
12
|
+
} from '@jupyterlab/application';
|
|
13
|
+
import { Dialog, ICommandPalette, showDialog } from '@jupyterlab/apputils';
|
|
14
|
+
import { ExtensionsPanel, ListModel } from '@jupyterlab/extensionmanager';
|
|
15
|
+
import { ISettingRegistry } from '@jupyterlab/settingregistry';
|
|
16
|
+
import {
|
|
17
|
+
ITranslator,
|
|
18
|
+
nullTranslator,
|
|
19
|
+
TranslationBundle
|
|
20
|
+
} from '@jupyterlab/translation';
|
|
21
|
+
import { extensionIcon } from '@jupyterlab/ui-components';
|
|
22
|
+
|
|
23
|
+
const PLUGIN_ID = '@jupyterlab/extensionmanager-extension:plugin';
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* IDs of the commands added by this extension.
|
|
27
|
+
*/
|
|
28
|
+
namespace CommandIDs {
|
|
29
|
+
export const showPanel = 'extensionmanager:show-panel';
|
|
30
|
+
export const toggle = 'extensionmanager:toggle';
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* The extension manager plugin.
|
|
35
|
+
*/
|
|
36
|
+
const plugin: JupyterFrontEndPlugin<void> = {
|
|
37
|
+
id: PLUGIN_ID,
|
|
38
|
+
autoStart: true,
|
|
39
|
+
requires: [ISettingRegistry],
|
|
40
|
+
optional: [ITranslator, ILayoutRestorer, ICommandPalette],
|
|
41
|
+
activate: async (
|
|
42
|
+
app: JupyterFrontEnd,
|
|
43
|
+
registry: ISettingRegistry,
|
|
44
|
+
translator: ITranslator | null,
|
|
45
|
+
restorer: ILayoutRestorer | null,
|
|
46
|
+
palette: ICommandPalette | null
|
|
47
|
+
) => {
|
|
48
|
+
const { commands, shell, serviceManager } = app;
|
|
49
|
+
translator = translator ?? nullTranslator;
|
|
50
|
+
const trans = translator.load('jupyterlab');
|
|
51
|
+
|
|
52
|
+
const model = new ListModel(serviceManager, translator);
|
|
53
|
+
|
|
54
|
+
const createView = () => {
|
|
55
|
+
const v = new ExtensionsPanel({ model, translator: translator! });
|
|
56
|
+
v.id = 'extensionmanager.main-view';
|
|
57
|
+
v.title.icon = extensionIcon;
|
|
58
|
+
v.title.caption = trans.__('Extension Manager');
|
|
59
|
+
v.node.setAttribute('role', 'region');
|
|
60
|
+
v.node.setAttribute('aria-label', trans.__('Extension Manager section'));
|
|
61
|
+
if (restorer) {
|
|
62
|
+
restorer.add(v, v.id);
|
|
63
|
+
}
|
|
64
|
+
shell.add(v, 'left', { rank: 1000 });
|
|
65
|
+
|
|
66
|
+
return v;
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
// Create a view by default, so it can be restored when loading the workspace.
|
|
70
|
+
let view: ExtensionsPanel | null = createView();
|
|
71
|
+
|
|
72
|
+
// If the extension is enabled or disabled,
|
|
73
|
+
// add or remove it from the left area.
|
|
74
|
+
Promise.all([app.restored, registry.load(PLUGIN_ID)])
|
|
75
|
+
.then(([, settings]) => {
|
|
76
|
+
model.isDisclaimed = settings.get('disclaimed').composite as boolean;
|
|
77
|
+
model.isEnabled = settings.get('enabled').composite as boolean;
|
|
78
|
+
model.stateChanged.connect(() => {
|
|
79
|
+
if (
|
|
80
|
+
model.isDisclaimed !==
|
|
81
|
+
(settings.get('disclaimed').composite as boolean)
|
|
82
|
+
) {
|
|
83
|
+
settings.set('disclaimed', model.isDisclaimed).catch(reason => {
|
|
84
|
+
console.error(`Failed to set setting 'disclaimed'.\n${reason}`);
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
if (
|
|
88
|
+
model.isEnabled !== (settings.get('enabled').composite as boolean)
|
|
89
|
+
) {
|
|
90
|
+
settings.set('enabled', model.isEnabled).catch(reason => {
|
|
91
|
+
console.error(`Failed to set setting 'enabled'.\n${reason}`);
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
if (model.isEnabled) {
|
|
97
|
+
view = view ?? createView();
|
|
98
|
+
} else {
|
|
99
|
+
view?.dispose();
|
|
100
|
+
view = null;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
settings.changed.connect(async () => {
|
|
104
|
+
model.isDisclaimed = settings.get('disclaimed').composite as boolean;
|
|
105
|
+
model.isEnabled = settings.get('enabled').composite as boolean;
|
|
106
|
+
app.commands.notifyCommandChanged(CommandIDs.toggle);
|
|
107
|
+
|
|
108
|
+
if (model.isEnabled) {
|
|
109
|
+
if (view === null || !view.isAttached) {
|
|
110
|
+
const accepted = await Private.showWarning(trans);
|
|
111
|
+
if (!accepted) {
|
|
112
|
+
void settings.set('enabled', false);
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
view = view ?? createView();
|
|
117
|
+
} else {
|
|
118
|
+
view?.dispose();
|
|
119
|
+
view = null;
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
})
|
|
123
|
+
.catch(reason => {
|
|
124
|
+
console.error(
|
|
125
|
+
`Something went wrong when reading the settings.\n${reason}`
|
|
126
|
+
);
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
commands.addCommand(CommandIDs.showPanel, {
|
|
130
|
+
label: trans.__('Extension Manager'),
|
|
131
|
+
execute: () => {
|
|
132
|
+
if (view) {
|
|
133
|
+
shell.activateById(view.id);
|
|
134
|
+
}
|
|
135
|
+
},
|
|
136
|
+
isVisible: () => model.isEnabled
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
commands.addCommand(CommandIDs.toggle, {
|
|
140
|
+
label: trans.__('Enable Extension Manager'),
|
|
141
|
+
execute: () => {
|
|
142
|
+
if (registry) {
|
|
143
|
+
void registry.set(plugin.id, 'enabled', !model.isEnabled);
|
|
144
|
+
}
|
|
145
|
+
},
|
|
146
|
+
isToggled: () => model.isEnabled
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
if (palette) {
|
|
150
|
+
palette.addItem({
|
|
151
|
+
command: CommandIDs.toggle,
|
|
152
|
+
category: trans.__('Extension Manager')
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Export the plugin as the default.
|
|
160
|
+
*/
|
|
161
|
+
export default plugin;
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* A namespace for module-private functions.
|
|
165
|
+
*/
|
|
166
|
+
namespace Private {
|
|
167
|
+
/**
|
|
168
|
+
* Show a warning dialog about extension security.
|
|
169
|
+
*
|
|
170
|
+
* @returns whether the user accepted the dialog.
|
|
171
|
+
*/
|
|
172
|
+
export async function showWarning(
|
|
173
|
+
trans: TranslationBundle
|
|
174
|
+
): Promise<boolean> {
|
|
175
|
+
const result = await showDialog({
|
|
176
|
+
title: trans.__('Enable Extension Manager?'),
|
|
177
|
+
body: trans.__(`Thanks for trying out JupyterLab's extension manager.
|
|
178
|
+
The JupyterLab development team is excited to have a robust
|
|
179
|
+
third-party extension community.
|
|
180
|
+
However, we cannot vouch for every extension,
|
|
181
|
+
and some may introduce security risks.
|
|
182
|
+
Do you want to continue?`),
|
|
183
|
+
buttons: [
|
|
184
|
+
Dialog.cancelButton({ label: trans.__('Disable') }),
|
|
185
|
+
Dialog.warnButton({ label: trans.__('Enable') })
|
|
186
|
+
]
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
return result.button.accept;
|
|
190
|
+
}
|
|
191
|
+
}
|