meerschaum 2.7.8__py3-none-any.whl → 2.7.10__py3-none-any.whl
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.
- 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
|
)
|