pywebexec 1.4.5__py3-none-any.whl → 1.4.7__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.
- pywebexec/pywebexec.py +4 -0
- pywebexec/static/css/style.css +12 -0
- pywebexec/static/images/favicon.svg +8 -1
- pywebexec/static/images/popup.svg +1 -0
- pywebexec/static/js/popup.js +130 -0
- pywebexec/static/js/script.js +11 -1
- pywebexec/templates/popup.html +21 -0
- pywebexec/version.py +2 -2
- {pywebexec-1.4.5.dist-info → pywebexec-1.4.7.dist-info}/METADATA +1 -1
- {pywebexec-1.4.5.dist-info → pywebexec-1.4.7.dist-info}/RECORD +14 -11
- {pywebexec-1.4.5.dist-info → pywebexec-1.4.7.dist-info}/LICENSE +0 -0
- {pywebexec-1.4.5.dist-info → pywebexec-1.4.7.dist-info}/WHEEL +0 -0
- {pywebexec-1.4.5.dist-info → pywebexec-1.4.7.dist-info}/entry_points.txt +0 -0
- {pywebexec-1.4.5.dist-info → pywebexec-1.4.7.dist-info}/top_level.txt +0 -0
pywebexec/pywebexec.py
CHANGED
@@ -682,6 +682,10 @@ def list_executables():
|
|
682
682
|
executables.sort() # Sort the list of executables alphabetically
|
683
683
|
return jsonify(executables)
|
684
684
|
|
685
|
+
@app.route('/popup/<command_id>')
|
686
|
+
def popup(command_id):
|
687
|
+
return render_template('popup.html', command_id=command_id)
|
688
|
+
|
685
689
|
def main():
|
686
690
|
basef = f"{CONFDIR}/pywebexec_{args.listen}:{args.port}"
|
687
691
|
if args.action == "start":
|
pywebexec/static/css/style.css
CHANGED
@@ -266,4 +266,16 @@ span {
|
|
266
266
|
#outputSlider {
|
267
267
|
width: 100%;
|
268
268
|
}
|
269
|
+
.popup-button {
|
270
|
+
background: none;
|
271
|
+
border: none;
|
272
|
+
cursor: pointer;
|
273
|
+
padding: 0;
|
274
|
+
margin-left: 5px;
|
275
|
+
vertical-align: middle;
|
276
|
+
}
|
277
|
+
.popup-button img {
|
278
|
+
width: 16px;
|
279
|
+
height: 16px;
|
280
|
+
}
|
269
281
|
|
@@ -1 +1,8 @@
|
|
1
|
-
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><g id="SVGRepo_bgCarrier" stroke-width="0"></g
|
1
|
+
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><g id="SVGRepo_bgCarrier" stroke-width="0"></g>
|
2
|
+
<g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g>
|
3
|
+
<g id="SVGRepo_iconCarrier">
|
4
|
+
<path opacity="0.8" d="M3 8C3 6.11438 3 5.17157 3.58579 4.58579C4.17157 4 5.11438 4 7 4H12H17C18.8856 4 19.8284 4 20.4142 4.58579C21 5.17157 21 6.11438 21 8V12V16C21 17.8856 21 18.8284 20.4142 19.4142C19.8284 20 18.8856 20 17 20H12H7C5.11438 20 4.17157 20 3.58579 19.4142C3 18.8284 3 17.8856 3 16V12V8Z" style="fill: rgba(5, 167, 98, 0.9);"></path>
|
5
|
+
<path d="M13 15H16" stroke="#323232" stroke-width="2" stroke-linecap="round"></path>
|
6
|
+
<path d="M8 15L10.5 12.5V12.5C10.7761 12.2239 10.7761 11.7761 10.5 11.5V11.5L8 9" stroke="#323232" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path>
|
7
|
+
<path d="M3 8C3 6.11438 3 5.17157 3.58579 4.58579C4.17157 4 5.11438 4 7 4H12H17C18.8856 4 19.8284 4 20.4142 4.58579C21 5.17157 21 6.11438 21 8V12V16C21 17.8856 21 18.8284 20.4142 19.4142C19.8284 20 18.8856 20 17 20H12H7C5.11438 20 4.17157 20 3.58579 19.4142C3 18.8284 3 17.8856 3 16V12V8Z" stroke="#323232" stroke-width="2" stroke-linejoin="round"></path>
|
8
|
+
</g></svg>
|
@@ -0,0 +1 @@
|
|
1
|
+
<svg fill="#000000" viewBox="0 0 32 32" version="1.1" xmlns="http://www.w3.org/2000/svg"><g id="SVGRepo_bgCarrier" stroke-width="0"></g><g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g><g id="SVGRepo_iconCarrier"> <title>popout</title> <path d="M15.694 13.541l2.666 2.665 5.016-5.017 2.59 2.59 0.004-7.734-7.785-0.046 2.526 2.525-5.017 5.017zM25.926 16.945l-1.92-1.947 0.035 9.007-16.015 0.009 0.016-15.973 8.958-0.040-2-2h-7c-1.104 0-2 0.896-2 2v16c0 1.104 0.896 2 2 2h16c1.104 0 2-0.896 2-2l-0.074-7.056z"></path> </g></svg>
|
@@ -0,0 +1,130 @@
|
|
1
|
+
let terminal = new Terminal({
|
2
|
+
cursorBlink: false,
|
3
|
+
cursorInactiveStyle: 'none',
|
4
|
+
disableStdin: true,
|
5
|
+
convertEol: true,
|
6
|
+
fontFamily: 'Consolas NF, monospace, courier-new, courier',
|
7
|
+
scrollback: 999999,
|
8
|
+
theme: {
|
9
|
+
background: '#111412',
|
10
|
+
black: '#111412',
|
11
|
+
green: '#088a5b',
|
12
|
+
blue: "#2760aa",
|
13
|
+
red: '#ba1611',
|
14
|
+
yellow: "#cf8700",
|
15
|
+
magenta: "#4c3d80",
|
16
|
+
cyan: "#00a7aa",
|
17
|
+
brightBlack: "#243C4F",
|
18
|
+
brightBlue: "#5584b1",
|
19
|
+
},
|
20
|
+
customGlyphs: false,
|
21
|
+
rescaleOverlappingGlyphs: true,
|
22
|
+
});
|
23
|
+
|
24
|
+
const fitAddon = new FitAddon.FitAddon();
|
25
|
+
terminal.loadAddon(fitAddon);
|
26
|
+
terminal.open(document.getElementById('output'));
|
27
|
+
fitAddon.fit();
|
28
|
+
|
29
|
+
let currentCommandId = null;
|
30
|
+
let outputInterval = null;
|
31
|
+
let nextOutputLink = null;
|
32
|
+
let fullOutput = '';
|
33
|
+
let outputLength = 0;
|
34
|
+
|
35
|
+
function getTokenParam() {
|
36
|
+
const urlParams = new URLSearchParams(window.location.search);
|
37
|
+
return urlParams.get('token') ? `?token=${urlParams.get('token')}` : '';
|
38
|
+
}
|
39
|
+
const urlToken = getTokenParam();
|
40
|
+
|
41
|
+
async function fetchOutput(url) {
|
42
|
+
try {
|
43
|
+
const response = await fetch(url);
|
44
|
+
if (!response.ok) {
|
45
|
+
return;
|
46
|
+
}
|
47
|
+
const data = await response.json();
|
48
|
+
if (data.error) {
|
49
|
+
terminal.write(data.error);
|
50
|
+
clearInterval(outputInterval);
|
51
|
+
} else {
|
52
|
+
slider = document.getElementById('outputSlider')
|
53
|
+
percentage = slider.value;
|
54
|
+
fullOutput += data.output;
|
55
|
+
if (percentage == 100)
|
56
|
+
terminal.write(data.output);
|
57
|
+
else {
|
58
|
+
percentage = Math.round((outputLength * 100)/fullOutput.length);
|
59
|
+
slider.value = percentage;
|
60
|
+
document.getElementById('outputPercentage').innerText = `${percentage}%`;
|
61
|
+
}
|
62
|
+
nextOutputLink = data.links.next;
|
63
|
+
if (data.status != 'running') {
|
64
|
+
clearInterval(outputInterval);
|
65
|
+
}
|
66
|
+
}
|
67
|
+
} catch (error) {
|
68
|
+
console.log('Error fetching output:', error);
|
69
|
+
}
|
70
|
+
}
|
71
|
+
|
72
|
+
async function viewOutput(command_id) {
|
73
|
+
document.getElementById('outputSlider').value = 100;
|
74
|
+
adjustOutputHeight();
|
75
|
+
currentCommandId = command_id;
|
76
|
+
nextOutputLink = `/command_output/${command_id}${urlToken}`;
|
77
|
+
clearInterval(outputInterval);
|
78
|
+
terminal.clear();
|
79
|
+
terminal.reset();
|
80
|
+
fullOutput = '';
|
81
|
+
try {
|
82
|
+
const response = await fetch(`/command_status/${command_id}${urlToken}`);
|
83
|
+
if (!response.ok) {
|
84
|
+
return;
|
85
|
+
}
|
86
|
+
const data = await response.json();
|
87
|
+
document.getElementsByTagName('title')[0].innerText = `${data.command} ${data.status}`;
|
88
|
+
if (data.command == 'term')
|
89
|
+
terminal.options.cursorInactiveStyle = 'outline';
|
90
|
+
else
|
91
|
+
terminal.options.cursorInactiveStyle = 'none';
|
92
|
+
if (data.status === 'running') {
|
93
|
+
fetchOutput(nextOutputLink);
|
94
|
+
outputInterval = setInterval(() => fetchOutput(nextOutputLink), 1000);
|
95
|
+
} else {
|
96
|
+
fetchOutput(nextOutputLink);
|
97
|
+
}
|
98
|
+
} catch (error) {
|
99
|
+
console.log('Error viewing output:', error);
|
100
|
+
}
|
101
|
+
}
|
102
|
+
|
103
|
+
function adjustOutputHeight() {
|
104
|
+
const outputDiv = document.getElementById('output');
|
105
|
+
const windowHeight = window.innerHeight;
|
106
|
+
const outputTop = outputDiv.getBoundingClientRect().top;
|
107
|
+
const maxHeight = windowHeight - outputTop - 60; // Adjusted for slider height
|
108
|
+
outputDiv.style.height = `${maxHeight}px`;
|
109
|
+
fitAddon.fit();
|
110
|
+
}
|
111
|
+
|
112
|
+
function sliderUpdateOutput() {
|
113
|
+
const slider = document.getElementById('outputSlider');
|
114
|
+
const percentage = slider.value;
|
115
|
+
outputLength = Math.floor((fullOutput.length * percentage) / 100);
|
116
|
+
const limitedOutput = fullOutput.slice(0, outputLength);
|
117
|
+
terminal.clear();
|
118
|
+
terminal.reset();
|
119
|
+
terminal.write(limitedOutput);
|
120
|
+
document.getElementById('outputPercentage').innerText = `${percentage}%`;
|
121
|
+
}
|
122
|
+
|
123
|
+
document.getElementById('outputSlider').addEventListener('input', sliderUpdateOutput);
|
124
|
+
|
125
|
+
window.addEventListener('resize', adjustOutputHeight);
|
126
|
+
window.addEventListener('load', () => {
|
127
|
+
const commandId = window.location.pathname.split('/').slice(-1)[0];
|
128
|
+
viewOutput(commandId);
|
129
|
+
});
|
130
|
+
|
pywebexec/static/js/script.js
CHANGED
@@ -107,7 +107,12 @@ async function fetchCommands() {
|
|
107
107
|
<td>
|
108
108
|
${command.command.startsWith('term') ? '' : command.status === 'running' ? `<button onclick="stopCommand('${command.command_id}', event)">Stop</button>` : `<button onclick="relaunchCommand('${command.command_id}', event)">Run</button>`}
|
109
109
|
</td>
|
110
|
-
<td class="monospace outcol"
|
110
|
+
<td class="monospace outcol">
|
111
|
+
<button class="popup-button" onclick="openPopup('${command.command_id}', event)">
|
112
|
+
<img src="/static/images/popup.svg" alt="Popup">
|
113
|
+
</button>
|
114
|
+
${command.last_output_line || ''}
|
115
|
+
</td>
|
111
116
|
`;
|
112
117
|
commandsTbody.appendChild(commandRow);
|
113
118
|
});
|
@@ -180,6 +185,11 @@ async function viewOutput(command_id) {
|
|
180
185
|
}
|
181
186
|
}
|
182
187
|
|
188
|
+
async function openPopup(command_id) {
|
189
|
+
const popupUrl = `/popup/${command_id}${urlToken}`;
|
190
|
+
window.open(popupUrl, '_blank', 'width=800,height=600');
|
191
|
+
}
|
192
|
+
|
183
193
|
async function relaunchCommand(command_id, event) {
|
184
194
|
event.stopPropagation();
|
185
195
|
event.stopImmediatePropagation();
|
@@ -0,0 +1,21 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html lang="en">
|
3
|
+
<head>
|
4
|
+
<meta charset="UTF-8">
|
5
|
+
<link rel="icon" href="/static/images/favicon.svg" type="image/svg+xml">
|
6
|
+
<title>Command Output</title>
|
7
|
+
<link rel="stylesheet" href="/static/css/style.css">
|
8
|
+
<link rel="stylesheet" href="/static/css/xterm.css">
|
9
|
+
</head>
|
10
|
+
<body>
|
11
|
+
<div id="output" class="output"></div>
|
12
|
+
<div class="slider-container">
|
13
|
+
<input type="range" id="outputSlider" min="0" max="100" value="100">
|
14
|
+
<label for="outputSlider"><span id="outputPercentage">100%</span></label>
|
15
|
+
</div>
|
16
|
+
<script src="/static/js/xterm/ansi_up.min.js"></script>
|
17
|
+
<script src="/static/js/xterm/xterm.js"></script>
|
18
|
+
<script src="/static/js/xterm/xterm-addon-fit.js"></script>
|
19
|
+
<script type="text/javascript" src="/static/js/popup.js"></script>
|
20
|
+
</body>
|
21
|
+
</html>
|
pywebexec/version.py
CHANGED
@@ -1,28 +1,31 @@
|
|
1
1
|
pywebexec/__init__.py,sha256=4spIsVaF8RJt8S58AG_wWoORRNkws9Iwqprj27C3ljM,99
|
2
|
-
pywebexec/pywebexec.py,sha256=
|
3
|
-
pywebexec/version.py,sha256=
|
2
|
+
pywebexec/pywebexec.py,sha256=wediupUiLmpCaER3b_-07QitIiTimgmEBBxFLGT6-DQ,26125
|
3
|
+
pywebexec/version.py,sha256=6M0bnfqGZEQvwGyTAgOkscrVPq1huIWdr9OdJlVIiPk,411
|
4
4
|
pywebexec/static/css/Consolas NF.ttf,sha256=DJEOzF0eqZ-kxu3Gs_VE8X0NJqiobBzmxWDGpdgGRxI,1313900
|
5
|
-
pywebexec/static/css/style.css,sha256=
|
5
|
+
pywebexec/static/css/style.css,sha256=sDBhZ-csW5THIKfTDsHqxCSg6rIJ91Oh15sjw_HjJo4,5702
|
6
6
|
pywebexec/static/css/xterm.css,sha256=gy8_LGA7Q61DUf8ElwFQzHqHMBQnbbEmpgZcbdgeSHI,5383
|
7
7
|
pywebexec/static/images/aborted.svg,sha256=_mP43hU5QdRLFZIknBgjx-dIXrHgQG23-QV27ApXK2A,381
|
8
8
|
pywebexec/static/images/copy.svg,sha256=d9OwtGh5GzzZHzYcDrLfNxZYLth1Q64x7bRyYxu4Px0,622
|
9
9
|
pywebexec/static/images/copy_ok.svg,sha256=mEqUVUhSq8xaJK2msQkxRawnz_KwlCZ-tok8QS6hJ3g,451
|
10
10
|
pywebexec/static/images/down-arrow.svg,sha256=4TclEmntMvKk_F_ADXgTpGtviYo826EDmmZiGE7HQBI,121
|
11
11
|
pywebexec/static/images/failed.svg,sha256=ADZ7IKrUyOXtqpivnz3VcH0-Wru-I5MOi3OJAkI3hxk,1439
|
12
|
-
pywebexec/static/images/favicon.svg,sha256
|
12
|
+
pywebexec/static/images/favicon.svg,sha256=9gSN5Oak1zTWhTCyutlupPBKUxcbdoVt7dvhk8xvEug,1224
|
13
|
+
pywebexec/static/images/popup.svg,sha256=0Bl9A_v5cBsMPn6FnOlVWlAQKgd2zqiWQbhjcL9BDzI,559
|
13
14
|
pywebexec/static/images/running.gif,sha256=iYuzQGkMxrakSIwt6gPieKCImGZoSAHmU5MUNZa7cpw,25696
|
14
15
|
pywebexec/static/images/success.svg,sha256=PJDcCSTevJh7rkfSFLtc7P0pbeh8PVQBS8DaOLQemmc,489
|
15
16
|
pywebexec/static/js/commands.js,sha256=8JDb3Q55EJOYf2Q9Uy6qEuqAnn1oGjM0RndgQ4aOjqo,7725
|
16
|
-
pywebexec/static/js/
|
17
|
+
pywebexec/static/js/popup.js,sha256=1AczXkJrqqjajT8ji4Rxz_xRyPSO8NJmIsx-ckmbNEw,4239
|
18
|
+
pywebexec/static/js/script.js,sha256=QAXrNqHrqrAF2MpgFagnMe59AIT57bAe7crzYYzKGB4,11972
|
17
19
|
pywebexec/static/js/xterm/LICENSE,sha256=EU1P4eXTull-_T9I80VuwnJXubB-zLzUl3xpEYj2T1M,1083
|
18
20
|
pywebexec/static/js/xterm/ansi_up.min.js,sha256=KNGV0vEr30hNqKQimTAvGVy-icD5A1JqMQTtvYtKR2Y,13203
|
19
21
|
pywebexec/static/js/xterm/xterm-addon-fit.js,sha256=Pprm9pZe4SadVXS5Bc8b9VnC9Ex4QlWwA0pxOH53Gck,1460
|
20
22
|
pywebexec/static/js/xterm/xterm.js,sha256=Bzka76jZwEhVt_LlS0e0qMw7ryGa1p5qfxFyeohphBo,283371
|
21
23
|
pywebexec/templates/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
22
24
|
pywebexec/templates/index.html,sha256=DYtT555wSNhnFtzzHhPMWJireynCJNnAuTytpoORQeE,2321
|
23
|
-
pywebexec
|
24
|
-
pywebexec-1.4.
|
25
|
-
pywebexec-1.4.
|
26
|
-
pywebexec-1.4.
|
27
|
-
pywebexec-1.4.
|
28
|
-
pywebexec-1.4.
|
25
|
+
pywebexec/templates/popup.html,sha256=PfhAi1LwS06MvjqJA45IN_eLxy49Tq2Q_qOPzX8JTrU,820
|
26
|
+
pywebexec-1.4.7.dist-info/LICENSE,sha256=gRJf0JPT_wsZJsUGlWPTS8Vypfl9vQ1qjp6sNbKykuA,1064
|
27
|
+
pywebexec-1.4.7.dist-info/METADATA,sha256=Jzlkrd79ANeEkb5ZI98Bc0GnBQUWlEYNRLanQSDeyKQ,7399
|
28
|
+
pywebexec-1.4.7.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
29
|
+
pywebexec-1.4.7.dist-info/entry_points.txt,sha256=l52GBkPCXRkmlHfEyoVauyfBdg8o-CAtC8qQpOIjJK0,55
|
30
|
+
pywebexec-1.4.7.dist-info/top_level.txt,sha256=vHoHyzngrfGdm_nM7Xn_5iLmaCrf10XO1EhldgNLEQ8,10
|
31
|
+
pywebexec-1.4.7.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|