meerschaum 2.7.8__py3-none-any.whl → 2.7.10__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- meerschaum/_internal/term/TermPageHandler.py +54 -4
- meerschaum/_internal/term/__init__.py +13 -5
- meerschaum/_internal/term/tools.py +41 -6
- meerschaum/actions/api.py +36 -10
- meerschaum/actions/start.py +25 -10
- meerschaum/api/dash/callbacks/dashboard.py +43 -2
- meerschaum/api/dash/components.py +13 -6
- meerschaum/api/dash/keys.py +82 -108
- meerschaum/api/dash/pages/dashboard.py +17 -17
- meerschaum/api/dash/sessions.py +1 -0
- meerschaum/api/dash/webterm.py +17 -6
- meerschaum/api/resources/static/js/terminado.js +0 -2
- meerschaum/api/resources/templates/termpage.html +47 -4
- meerschaum/api/routes/_webterm.py +15 -11
- meerschaum/config/_default.py +6 -0
- meerschaum/config/_version.py +1 -1
- meerschaum/config/static/__init__.py +2 -2
- meerschaum/core/Pipe/_sync.py +7 -7
- meerschaum/core/Pipe/_verify.py +1 -1
- meerschaum/utils/daemon/Daemon.py +15 -9
- meerschaum/utils/dtypes/__init__.py +9 -0
- meerschaum/utils/dtypes/sql.py +19 -13
- meerschaum/utils/formatting/_pprint.py +1 -1
- meerschaum/utils/misc.py +16 -0
- meerschaum/utils/venv/__init__.py +10 -14
- {meerschaum-2.7.8.dist-info → meerschaum-2.7.10.dist-info}/METADATA +1 -1
- {meerschaum-2.7.8.dist-info → meerschaum-2.7.10.dist-info}/RECORD +33 -33
- {meerschaum-2.7.8.dist-info → meerschaum-2.7.10.dist-info}/LICENSE +0 -0
- {meerschaum-2.7.8.dist-info → meerschaum-2.7.10.dist-info}/NOTICE +0 -0
- {meerschaum-2.7.8.dist-info → meerschaum-2.7.10.dist-info}/WHEEL +0 -0
- {meerschaum-2.7.8.dist-info → meerschaum-2.7.10.dist-info}/entry_points.txt +0 -0
- {meerschaum-2.7.8.dist-info → meerschaum-2.7.10.dist-info}/top_level.txt +0 -0
- {meerschaum-2.7.8.dist-info → meerschaum-2.7.10.dist-info}/zip-safe +0 -0
@@ -7,14 +7,64 @@ Define the terminal page handler class.
|
|
7
7
|
"""
|
8
8
|
|
9
9
|
from __future__ import annotations
|
10
|
-
from
|
11
|
-
|
10
|
+
from typing import Any
|
11
|
+
|
12
|
+
import meerschaum as mrsm
|
13
|
+
from meerschaum.utils.warnings import warn
|
14
|
+
tornado_web = mrsm.attempt_import('tornado.web', lazy=False)
|
15
|
+
terminado = mrsm.attempt_import('terminado', lazy=False)
|
16
|
+
|
17
|
+
tmux_suffix = mrsm.get_config('system', 'webterm', 'tmux', 'session_suffix')
|
18
|
+
|
12
19
|
|
13
20
|
class TermPageHandler(tornado_web.RequestHandler):
|
14
|
-
|
21
|
+
|
22
|
+
def get(self, term_name):
|
23
|
+
term_manager = self.application.settings['term_manager']
|
24
|
+
shell_command = [
|
25
|
+
cmd.replace('MRSM_SESSION', term_name + tmux_suffix)
|
26
|
+
for cmd in term_manager.shell_command
|
27
|
+
]
|
28
|
+
terminal = term_manager.new_terminal(shell_command=shell_command)
|
29
|
+
terminal.term_name = term_name
|
30
|
+
term_manager.terminals[term_name] = terminal
|
31
|
+
term_manager.start_reading(terminal)
|
15
32
|
return self.render(
|
16
33
|
"termpage.html",
|
17
34
|
static=self.static_url,
|
18
|
-
ws_url_path="/websocket",
|
35
|
+
ws_url_path=f"/websocket/{term_name}",
|
19
36
|
)
|
20
37
|
|
38
|
+
|
39
|
+
class CustomTermSocket(terminado.TermSocket):
|
40
|
+
|
41
|
+
def open(self, url_component: Any = None) -> None:
|
42
|
+
super(terminado.TermSocket, self).open(url_component)
|
43
|
+
url_component = (
|
44
|
+
url_component.decode("utf-8")
|
45
|
+
if isinstance(url_component, bytes)
|
46
|
+
else url_component
|
47
|
+
)
|
48
|
+
self.term_name = url_component
|
49
|
+
shell_command = [
|
50
|
+
cmd.replace('MRSM_SESSION', self.term_name + tmux_suffix)
|
51
|
+
for cmd in self.term_manager.shell_command
|
52
|
+
]
|
53
|
+
if self.term_name not in self.term_manager.terminals:
|
54
|
+
self.terminal = self.term_manager.new_terminal(shell_command=shell_command)
|
55
|
+
self.terminal.term_name = self.term_name
|
56
|
+
self.term_manager.terminals[self.term_name] = self.terminal
|
57
|
+
self.term_manager.start_reading(self.terminal)
|
58
|
+
else:
|
59
|
+
self.terminal = self.term_manager.terminals[self.term_name]
|
60
|
+
self.terminal.clients.append(self)
|
61
|
+
self.send_json_message(["setup", {}])
|
62
|
+
buffered = ""
|
63
|
+
preopen_buffer = self.terminal.read_buffer.copy()
|
64
|
+
while True:
|
65
|
+
if not preopen_buffer:
|
66
|
+
break
|
67
|
+
s = preopen_buffer.popleft()
|
68
|
+
buffered += s
|
69
|
+
if buffered:
|
70
|
+
self.on_pty_read(buffered)
|
@@ -9,10 +9,14 @@ Build the web console virtual terminal using Tornado and xterm.js.
|
|
9
9
|
from __future__ import annotations
|
10
10
|
|
11
11
|
from typing import Optional, Tuple
|
12
|
+
|
13
|
+
import meerschaum as mrsm
|
12
14
|
from meerschaum.utils.packages import attempt_import
|
13
|
-
from meerschaum._internal.term.TermPageHandler import TermPageHandler
|
15
|
+
from meerschaum._internal.term.TermPageHandler import TermPageHandler, CustomTermSocket
|
14
16
|
from meerschaum.config._paths import API_TEMPLATES_PATH, API_STATIC_PATH
|
15
17
|
from meerschaum.utils.venv import venv_executable
|
18
|
+
from meerschaum.utils.misc import is_tmux_available
|
19
|
+
from meerschaum.utils.daemon._names import get_new_daemon_name
|
16
20
|
|
17
21
|
tornado, tornado_ioloop, terminado = attempt_import(
|
18
22
|
'tornado', 'tornado.ioloop', 'terminado', lazy=False,
|
@@ -40,16 +44,19 @@ def get_webterm_app_and_manager(
|
|
40
44
|
"from meerschaum._internal.entry import get_shell; "
|
41
45
|
f"get_shell({shell_kwargs_str}).cmdloop()"
|
42
46
|
]
|
47
|
+
webterm_cf = mrsm.get_config('system', 'webterm')
|
48
|
+
if webterm_cf.get('tmux', {}).get('enabled', False) and is_tmux_available():
|
49
|
+
commands = ['tmux', 'new-session', '-A', '-s', 'MRSM_SESSION'] + commands
|
43
50
|
|
44
|
-
term_manager = terminado.
|
51
|
+
term_manager = terminado.NamedTermManager(shell_command=commands)
|
45
52
|
handlers = [
|
46
53
|
(
|
47
|
-
r"/websocket",
|
48
|
-
|
54
|
+
r"/websocket/(.+)/?",
|
55
|
+
CustomTermSocket,
|
49
56
|
{'term_manager': term_manager}
|
50
57
|
),
|
51
58
|
(
|
52
|
-
r"/",
|
59
|
+
r"/webterm/(.+)/?",
|
53
60
|
TermPageHandler
|
54
61
|
),
|
55
62
|
]
|
@@ -57,5 +64,6 @@ def get_webterm_app_and_manager(
|
|
57
64
|
handlers,
|
58
65
|
static_path=API_STATIC_PATH,
|
59
66
|
template_path=API_TEMPLATES_PATH,
|
67
|
+
term_manager=term_manager,
|
60
68
|
)
|
61
69
|
return tornado_app, term_manager
|
@@ -6,16 +6,21 @@
|
|
6
6
|
Utility functions regarding the webterm.
|
7
7
|
"""
|
8
8
|
|
9
|
-
|
9
|
+
import meerschaum as mrsm
|
10
|
+
from meerschaum.utils.typing import List
|
10
11
|
|
11
|
-
|
12
|
+
|
13
|
+
def is_webterm_running(
|
14
|
+
host: str,
|
15
|
+
port: int,
|
16
|
+
protocol: str = 'http',
|
17
|
+
session_id: str = 'mrsm',
|
18
|
+
) -> int:
|
12
19
|
"""
|
13
20
|
Determine whether the webterm service is running on a given host and port.
|
14
21
|
"""
|
15
|
-
|
16
|
-
|
17
|
-
requests = attempt_import('requests')
|
18
|
-
url = f'{protocol}://{host}:{port}'
|
22
|
+
requests = mrsm.attempt_import('requests', lazy=False)
|
23
|
+
url = f'{protocol}://{host}:{port}/webterm/{session_id}'
|
19
24
|
try:
|
20
25
|
r = requests.get(url, timeout=3)
|
21
26
|
except Exception as e:
|
@@ -23,3 +28,33 @@ def is_webterm_running(host: str, port: int, protocol: str = 'http') -> int:
|
|
23
28
|
if not r:
|
24
29
|
return False
|
25
30
|
return '<title>Meerschaum Shell</title>' in r.text
|
31
|
+
|
32
|
+
|
33
|
+
def kill_tmux_session(session: str) -> bool:
|
34
|
+
"""
|
35
|
+
Kill a tmux session if it exists.
|
36
|
+
"""
|
37
|
+
from meerschaum.utils.process import run_process
|
38
|
+
command = ['tmux', 'kill-session', '-t', session]
|
39
|
+
return run_process(command, capture_output=True) == 0
|
40
|
+
|
41
|
+
|
42
|
+
def get_mrsm_tmux_sessions() -> List[str]:
|
43
|
+
"""
|
44
|
+
Return a list of tmux sessions created by Meerschaum.
|
45
|
+
"""
|
46
|
+
from meerschaum.utils.process import run_process
|
47
|
+
tmux_suffix = mrsm.get_config('system', 'webterm', 'tmux', 'session_suffix')
|
48
|
+
command = ['tmux', 'ls']
|
49
|
+
proc = run_process(command, capture_output=True, as_proc=True)
|
50
|
+
if proc.returncode != 0:
|
51
|
+
return []
|
52
|
+
sessions = [
|
53
|
+
line.split(':', maxsplit=1)[0]
|
54
|
+
for line in proc.stdout.read().decode('utf-8').split('\n')
|
55
|
+
]
|
56
|
+
return [
|
57
|
+
session
|
58
|
+
for session in sessions
|
59
|
+
if session.endswith(tmux_suffix)
|
60
|
+
]
|
meerschaum/actions/api.py
CHANGED
@@ -140,16 +140,28 @@ def _api_start(
|
|
140
140
|
If provided, serve over HTTPS with this certfile.
|
141
141
|
Requires `--keyfile`.
|
142
142
|
"""
|
143
|
+
import json
|
144
|
+
import sys
|
145
|
+
import shutil
|
146
|
+
import pathlib
|
147
|
+
from copy import deepcopy
|
148
|
+
|
143
149
|
from meerschaum.utils.packages import (
|
144
|
-
attempt_import,
|
150
|
+
attempt_import,
|
151
|
+
venv_contains_package,
|
152
|
+
pip_install,
|
153
|
+
run_python_package,
|
145
154
|
)
|
146
155
|
from meerschaum.utils.misc import is_int, filter_keywords
|
156
|
+
from meerschaum.utils.dtypes import json_serialize_value
|
147
157
|
from meerschaum.utils.formatting import pprint, ANSI, _init
|
148
158
|
from meerschaum.utils.debug import dprint
|
149
159
|
from meerschaum.utils.warnings import error, warn
|
150
160
|
from meerschaum.config import get_config, _config
|
151
161
|
from meerschaum.config._paths import (
|
152
|
-
API_UVICORN_RESOURCES_PATH,
|
162
|
+
API_UVICORN_RESOURCES_PATH,
|
163
|
+
API_UVICORN_CONFIG_PATH,
|
164
|
+
CACHE_RESOURCES_PATH,
|
153
165
|
PACKAGE_ROOT_PATH,
|
154
166
|
)
|
155
167
|
from meerschaum.config._patch import apply_patch_to_config
|
@@ -157,8 +169,6 @@ def _api_start(
|
|
157
169
|
from meerschaum.config.static import STATIC_CONFIG, SERVER_ID
|
158
170
|
from meerschaum.connectors.parse import parse_instance_keys
|
159
171
|
from meerschaum.utils.pool import get_pool
|
160
|
-
import shutil
|
161
|
-
from copy import deepcopy
|
162
172
|
|
163
173
|
if action is None:
|
164
174
|
action = []
|
@@ -256,7 +266,6 @@ def _api_start(
|
|
256
266
|
custom_keys = ['mrsm_instance', 'no_dash', 'no_auth', 'private', 'debug', 'production']
|
257
267
|
|
258
268
|
### write config to a temporary file to communicate with uvicorn threads
|
259
|
-
import json, sys
|
260
269
|
try:
|
261
270
|
if uvicorn_config_path.exists():
|
262
271
|
os.remove(uvicorn_config_path)
|
@@ -275,12 +284,25 @@ def _api_start(
|
|
275
284
|
MRSM_RUNTIME = STATIC_CONFIG['environment']['runtime']
|
276
285
|
MRSM_PATCH = STATIC_CONFIG['environment']['patch']
|
277
286
|
MRSM_ROOT_DIR = STATIC_CONFIG['environment']['root']
|
278
|
-
env_dict = {
|
287
|
+
env_dict = {}
|
288
|
+
env_dict.update({
|
279
289
|
MRSM_SERVER_ID: SERVER_ID,
|
280
290
|
MRSM_RUNTIME: 'api',
|
281
291
|
MRSM_CONFIG: json.loads(os.environ.get(MRSM_CONFIG, '{}')),
|
282
292
|
'FORWARDED_ALLOW_IPS': forwarded_allow_ips,
|
283
|
-
|
293
|
+
'TERM': os.environ.get('TERM', 'screen-256color'),
|
294
|
+
'SHELL': os.environ.get('SHELL', '/bin/bash'),
|
295
|
+
'LANG': os.environ.get('LANG', 'C.UTF-8'),
|
296
|
+
'HOME': os.environ.get('HOME', pathlib.Path.home().as_posix()),
|
297
|
+
'PATH': os.environ.get(
|
298
|
+
'PATH',
|
299
|
+
(
|
300
|
+
'/usr/local/bin:/usr/local/sbin:/usr/sbin:/usr/bin:/sbin:/bin:'
|
301
|
+
f'{pathlib.Path.home().as_posix().rstrip("/")}/.local/bin'
|
302
|
+
)
|
303
|
+
),
|
304
|
+
'HOSTNAME': os.environ.get('HOSTNAME', 'api'),
|
305
|
+
})
|
284
306
|
for env_var in get_env_vars():
|
285
307
|
if env_var in env_dict:
|
286
308
|
continue
|
@@ -294,10 +316,10 @@ def _api_start(
|
|
294
316
|
env_text = ''
|
295
317
|
for key, val in env_dict.items():
|
296
318
|
value = str(
|
297
|
-
json.dumps(val)
|
319
|
+
json.dumps(val, default=json_serialize_value)
|
298
320
|
if isinstance(val, (dict))
|
299
321
|
else val
|
300
|
-
).replace('\\', '\\\\')
|
322
|
+
).replace('\\', '\\\\').replace("'", "'\\''")
|
301
323
|
env_text += f"{key}='{value}'\n"
|
302
324
|
with open(uvicorn_env_path, 'w+', encoding='utf-8') as f:
|
303
325
|
if debug:
|
@@ -329,7 +351,11 @@ def _api_start(
|
|
329
351
|
for key, val in env_dict.items():
|
330
352
|
gunicorn_args += [
|
331
353
|
'--env', key + "="
|
332
|
-
+ (
|
354
|
+
+ (
|
355
|
+
json.dumps(val, default=json_serialize_value)
|
356
|
+
if isinstance(val, (dict, list))
|
357
|
+
else val
|
358
|
+
)
|
333
359
|
]
|
334
360
|
if workers is not None:
|
335
361
|
gunicorn_args += ['--workers', str(workers)]
|
meerschaum/actions/start.py
CHANGED
@@ -314,6 +314,11 @@ def _start_gui(
|
|
314
314
|
"""
|
315
315
|
Start the Meerschaum GUI application.
|
316
316
|
"""
|
317
|
+
import json
|
318
|
+
import time
|
319
|
+
import uuid
|
320
|
+
import platform
|
321
|
+
|
317
322
|
from meerschaum.utils.venv import venv_exec
|
318
323
|
from meerschaum.utils.packages import attempt_import
|
319
324
|
from meerschaum.utils.warnings import warn
|
@@ -321,17 +326,14 @@ def _start_gui(
|
|
321
326
|
from meerschaum.utils.networking import find_open_ports
|
322
327
|
from meerschaum.connectors.parse import parse_instance_keys
|
323
328
|
from meerschaum._internal.term.tools import is_webterm_running
|
324
|
-
import platform
|
325
329
|
webview, requests = attempt_import('webview', 'requests')
|
326
|
-
import json
|
327
|
-
import time
|
328
330
|
|
329
331
|
success, msg = True, "Success"
|
330
332
|
host = '127.0.0.1'
|
331
333
|
if port is None:
|
332
334
|
port = 8765
|
333
335
|
|
334
|
-
if not is_webterm_running(host, port):
|
336
|
+
if not is_webterm_running(host, port, session_id='mrsm'):
|
335
337
|
port = next(find_open_ports(port, 9000))
|
336
338
|
|
337
339
|
api_kw = {
|
@@ -350,7 +352,7 @@ def _start_gui(
|
|
350
352
|
)
|
351
353
|
if debug:
|
352
354
|
print(start_tornado_code)
|
353
|
-
base_url = 'http://' + api_kw['host'] + ':' + str(api_kw['port'])
|
355
|
+
base_url = 'http://' + api_kw['host'] + ':' + str(api_kw['port']) + '/webterm/mrsm'
|
354
356
|
|
355
357
|
process = venv_exec(
|
356
358
|
start_tornado_code, as_proc=True, debug=debug, capture_output=(not debug)
|
@@ -375,7 +377,7 @@ def _start_gui(
|
|
375
377
|
try:
|
376
378
|
webview.create_window(
|
377
379
|
'Meerschaum Shell',
|
378
|
-
f'http://127.0.0.1:{port}',
|
380
|
+
f'http://127.0.0.1:{port}/webterm/mrsm',
|
379
381
|
height=650,
|
380
382
|
width=1000
|
381
383
|
)
|
@@ -415,8 +417,13 @@ def _start_webterm(
|
|
415
417
|
- `-i`, '--instance'
|
416
418
|
The default instance to use for the Webterm shell.
|
417
419
|
"""
|
420
|
+
import uuid
|
418
421
|
from meerschaum._internal.term import get_webterm_app_and_manager, tornado_ioloop
|
419
|
-
from meerschaum._internal.term.tools import
|
422
|
+
from meerschaum._internal.term.tools import (
|
423
|
+
is_webterm_running,
|
424
|
+
get_mrsm_tmux_sessions,
|
425
|
+
kill_tmux_session,
|
426
|
+
)
|
420
427
|
from meerschaum.utils.networking import find_open_ports
|
421
428
|
from meerschaum.utils.warnings import info
|
422
429
|
|
@@ -426,19 +433,23 @@ def _start_webterm(
|
|
426
433
|
port = 8765
|
427
434
|
if sysargs is None:
|
428
435
|
sysargs = ['start', 'webterm']
|
436
|
+
session_id = 'mrsm'
|
429
437
|
tornado_app, term_manager = get_webterm_app_and_manager(instance_keys=mrsm_instance)
|
430
438
|
|
431
|
-
if is_webterm_running(host, port):
|
439
|
+
if is_webterm_running(host, port, session_id=session_id):
|
432
440
|
if force:
|
433
441
|
port = next(find_open_ports(port + 1, 9000))
|
434
442
|
else:
|
435
443
|
return False, (
|
436
|
-
f"The webterm is already running at http://{host}:{port}\n\n"
|
444
|
+
f"The webterm is already running at http://{host}:{port}/webterm/{session_id}\n\n"
|
437
445
|
+ " Include `-f` to start another server on a new port\n"
|
438
446
|
+ " or specify a different port with `-p`."
|
439
447
|
)
|
440
448
|
if not nopretty:
|
441
|
-
info(
|
449
|
+
info(
|
450
|
+
f"Starting the webterm at http://{host}:{port}/webterm/{session_id} ..."
|
451
|
+
"\n Press CTRL+C to quit."
|
452
|
+
)
|
442
453
|
tornado_app.listen(port, host)
|
443
454
|
loop = tornado_ioloop.IOLoop.instance()
|
444
455
|
try:
|
@@ -451,6 +462,10 @@ def _start_webterm(
|
|
451
462
|
term_manager.shutdown()
|
452
463
|
loop.close()
|
453
464
|
|
465
|
+
sessions = get_mrsm_tmux_sessions()
|
466
|
+
for session in sessions:
|
467
|
+
kill_tmux_session(session)
|
468
|
+
|
454
469
|
return True, "Success"
|
455
470
|
|
456
471
|
|
@@ -190,6 +190,7 @@ def update_page_layout_div(
|
|
190
190
|
Input('go-button', 'n_clicks'),
|
191
191
|
Input('get-pipes-button', 'n_clicks'),
|
192
192
|
Input('get-jobs-button', 'n_clicks'),
|
193
|
+
Input('show-webterm-button', 'n_clicks'),
|
193
194
|
Input('get-plugins-button', 'n_clicks'),
|
194
195
|
Input('get-users-button', 'n_clicks'),
|
195
196
|
Input('get-graphs-button', 'n_clicks'),
|
@@ -229,7 +230,7 @@ def update_content(*args):
|
|
229
230
|
### NOTE: functions MUST return a list of content and a list of alerts
|
230
231
|
triggers = {
|
231
232
|
'go-button': lambda x: ([], []),
|
232
|
-
'
|
233
|
+
'show-webterm-button': lambda x: ([], []),
|
233
234
|
'get-pipes-button': get_pipes_cards,
|
234
235
|
'get-jobs-button': get_jobs_cards,
|
235
236
|
'get-plugins-button': get_plugins_cards,
|
@@ -251,7 +252,12 @@ def update_content(*args):
|
|
251
252
|
webterm_style = {
|
252
253
|
'display': (
|
253
254
|
'none'
|
254
|
-
if trigger not in (
|
255
|
+
if trigger not in (
|
256
|
+
'instance-select',
|
257
|
+
'cancel-button',
|
258
|
+
'go-button',
|
259
|
+
'show-webterm-button',
|
260
|
+
)
|
255
261
|
else 'block'
|
256
262
|
)
|
257
263
|
}
|
@@ -650,6 +656,41 @@ dash_app.clientside_callback(
|
|
650
656
|
State('mrsm-location', 'href'),
|
651
657
|
)
|
652
658
|
|
659
|
+
dash_app.clientside_callback(
|
660
|
+
"""
|
661
|
+
function(n_clicks, url){
|
662
|
+
if (!n_clicks) { return dash_clientside.no_update; }
|
663
|
+
iframe = document.getElementById('webterm-iframe');
|
664
|
+
if (!iframe){ return dash_clientside.no_update; }
|
665
|
+
|
666
|
+
iframe.contentWindow.postMessage(
|
667
|
+
{
|
668
|
+
action: "__TMUX_NEW_WINDOW"
|
669
|
+
},
|
670
|
+
url
|
671
|
+
);
|
672
|
+
return dash_clientside.no_update;
|
673
|
+
}
|
674
|
+
""",
|
675
|
+
Output('mrsm-location', 'href'),
|
676
|
+
Input('webterm-new-tab-button', 'n_clicks'),
|
677
|
+
State('mrsm-location', 'href'),
|
678
|
+
)
|
679
|
+
|
680
|
+
dash_app.clientside_callback(
|
681
|
+
"""
|
682
|
+
function(n_clicks, url){
|
683
|
+
if (!n_clicks) { return dash_clientside.no_update; }
|
684
|
+
iframe = document.getElementById('webterm-iframe');
|
685
|
+
if (!iframe){ return dash_clientside.no_update; }
|
686
|
+
iframe.src = iframe.src;
|
687
|
+
return dash_clientside.no_update;
|
688
|
+
}
|
689
|
+
""",
|
690
|
+
Output('mrsm-location', 'href'),
|
691
|
+
Input('webterm-refresh-button', 'n_clicks'),
|
692
|
+
State('mrsm-location', 'href'),
|
693
|
+
)
|
653
694
|
|
654
695
|
@dash_app.callback(
|
655
696
|
Output(component_id='connector-keys-input', component_property='value'),
|
@@ -23,7 +23,7 @@ dex = attempt_import('dash_extensions', lazy=False, check_update=CHECK_UPDATE)
|
|
23
23
|
dash_ace = attempt_import('dash_ace', lazy=False, check_update=CHECK_UPDATE)
|
24
24
|
_load_builtin_custom_connectors()
|
25
25
|
|
26
|
-
go_button = dbc.Button('
|
26
|
+
go_button = dbc.Button('Exec', id='go-button', color='primary', style={'width': '100%'})
|
27
27
|
test_button = dbc.Button('Test', id='test-button', color='danger', style={'display': 'none'})
|
28
28
|
get_items_menu = dbc.DropdownMenu(
|
29
29
|
label='More', id='get-items-menu', children=[
|
@@ -50,19 +50,26 @@ show_jobs_button = dbc.Button(
|
|
50
50
|
style={'width': '100%'},
|
51
51
|
)
|
52
52
|
cancel_button = dbc.Button(
|
53
|
-
'
|
53
|
+
'Term',
|
54
54
|
id='cancel-button',
|
55
55
|
color='dark',
|
56
56
|
style={'width': '100%', 'background-color': 'black', 'display': 'none'},
|
57
57
|
)
|
58
|
+
show_webterm_button = dbc.Button(
|
59
|
+
'Term',
|
60
|
+
id='show-webterm-button',
|
61
|
+
color='dark',
|
62
|
+
style={'width': '100%', 'background-color': 'black'},
|
63
|
+
)
|
58
64
|
bottom_buttons_content = dbc.Card(
|
59
65
|
dbc.CardBody(
|
60
66
|
dbc.Row([
|
61
|
-
dbc.Col(go_button, lg=3, md=
|
62
|
-
dbc.Col(show_pipes_button, lg=3, md=
|
63
|
-
dbc.Col(show_jobs_button, lg=3, md=
|
67
|
+
dbc.Col(go_button, xl=2, lg=3, md=3, sm=12),
|
68
|
+
dbc.Col(show_pipes_button, xl=2, lg=3, md=3, sm=12),
|
69
|
+
dbc.Col(show_jobs_button, xl=2, lg=3, md=3, sm=12),
|
70
|
+
dbc.Col(show_webterm_button, xl=2, lg=3, md=3, sm=12),
|
64
71
|
dbc.Col(lg=True, md=False, sm=False),
|
65
|
-
dbc.Col(get_items_menu,
|
72
|
+
dbc.Col(get_items_menu, xl=2, lg=12, md=12, sm=12),
|
66
73
|
])
|
67
74
|
)
|
68
75
|
)
|