pywebexec 2.3.3__py3-none-any.whl → 2.3.5__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 +2 -0
- pywebexec/static/css/form.css +49 -1
- pywebexec/static/css/style.css +2 -0
- pywebexec/static/js/schemaform.js +51 -5
- pywebexec/static/js/script.js +29 -15
- pywebexec/version.py +2 -2
- {pywebexec-2.3.3.dist-info → pywebexec-2.3.5.dist-info}/METADATA +1 -1
- {pywebexec-2.3.3.dist-info → pywebexec-2.3.5.dist-info}/RECORD +12 -12
- {pywebexec-2.3.3.dist-info → pywebexec-2.3.5.dist-info}/WHEEL +1 -1
- {pywebexec-2.3.3.dist-info → pywebexec-2.3.5.dist-info}/entry_points.txt +0 -0
- {pywebexec-2.3.3.dist-info → pywebexec-2.3.5.dist-info}/licenses/LICENSE +0 -0
- {pywebexec-2.3.3.dist-info → pywebexec-2.3.5.dist-info}/top_level.txt +0 -0
pywebexec/pywebexec.py
CHANGED
@@ -921,6 +921,8 @@ def run_dynamic_command(cmd):
|
|
921
921
|
if value:
|
922
922
|
params += f"{prefix} "
|
923
923
|
continue
|
924
|
+
if prefix and not value: # skip empty params with prefix
|
925
|
+
continue
|
924
926
|
if isinstance(value, dict) or convert_values.get(param, None) == "json":
|
925
927
|
value = shlex.quote(json.dumps(value, indent=2, sort_keys=False))
|
926
928
|
elif convert_values.get(param, None) == "quote":
|
pywebexec/static/css/form.css
CHANGED
@@ -123,6 +123,7 @@
|
|
123
123
|
margin-top: 0px;
|
124
124
|
margin-bottom: 1px;
|
125
125
|
padding: 0;
|
126
|
+
padding-right: 10px;
|
126
127
|
}
|
127
128
|
input[type="checkbox"] {
|
128
129
|
display: block;
|
@@ -148,6 +149,21 @@
|
|
148
149
|
.controls input[type="text"] {
|
149
150
|
width: 110px;;
|
150
151
|
}
|
152
|
+
|
153
|
+
.controls > div:not([id]) { /* for checkboxes */
|
154
|
+
scrollbar-width: thin;
|
155
|
+
scrollbar-gutter: stable;
|
156
|
+
overflow-y: auto;
|
157
|
+
max-height: 100px;
|
158
|
+
border: solid 1px #ccc;
|
159
|
+
border-radius: 5px;
|
160
|
+
padding: 5px 2px;
|
161
|
+
}
|
162
|
+
.controls > div.range {
|
163
|
+
overflow-y: hidden;
|
164
|
+
padding: 0px 5px;
|
165
|
+
}
|
166
|
+
|
151
167
|
input[type="number"] {
|
152
168
|
max-width: 120px;
|
153
169
|
text-align: right;
|
@@ -201,9 +217,13 @@
|
|
201
217
|
._jsonform-array-deletelast {
|
202
218
|
display: none;
|
203
219
|
}
|
204
|
-
._jsonform-array-buttons {
|
220
|
+
ul ~ ._jsonform-array-buttons {
|
205
221
|
display: block;
|
206
222
|
width: 100%;
|
223
|
+
}
|
224
|
+
._jsonform-array-buttons {
|
225
|
+
/* display: block; */
|
226
|
+
/* width: 100%; */
|
207
227
|
text-align: right;
|
208
228
|
}
|
209
229
|
i[title="Delete current"] {
|
@@ -237,6 +257,34 @@
|
|
237
257
|
background-color: #f2dede;
|
238
258
|
border-color: #ebccd1;
|
239
259
|
}
|
260
|
+
#reset-form:hover {
|
261
|
+
background-color: #e8e8e8;
|
262
|
+
border-color: #adadad;
|
263
|
+
}
|
264
|
+
#reset-form {
|
265
|
+
position: relative;
|
266
|
+
margin-bottom: 10px;
|
267
|
+
height: 24px;
|
268
|
+
top: 20px;
|
269
|
+
background-color: #f5f5f5;
|
270
|
+
border-color: #ccc;
|
271
|
+
height: 24px;
|
272
|
+
color: #333;
|
273
|
+
padding: 3px 13px;
|
274
|
+
}
|
275
|
+
fieldset {
|
276
|
+
border: 1px solid #ccc;
|
277
|
+
border-radius: 5px;
|
278
|
+
padding-top: 9px;
|
279
|
+
width: 100%;
|
280
|
+
label {
|
281
|
+
padding-right: 5px;
|
282
|
+
}
|
283
|
+
}
|
284
|
+
fieldset > div {
|
285
|
+
/* display: block ruby; */
|
286
|
+
padding-bottom: 5px;
|
287
|
+
}
|
240
288
|
}
|
241
289
|
|
242
290
|
.swagger-ui textarea {
|
pywebexec/static/css/style.css
CHANGED
@@ -53,7 +53,34 @@ function extractKeysAndPlaceholders(obj, formoptions, prefix = '') {
|
|
53
53
|
return result;
|
54
54
|
}
|
55
55
|
|
56
|
-
|
56
|
+
|
57
|
+
// Convert objects to JSON strings where schema type is object without properties
|
58
|
+
function convertObjectsToJsonStrings(obj, schema, prefix = '') {
|
59
|
+
// Helper function to get schema type and check for properties
|
60
|
+
function getSchemaTypeForKey(schema, keyPath) {
|
61
|
+
const keys = keyPath.split('.');
|
62
|
+
let current = schema.properties;
|
63
|
+
for (const key of keys) {
|
64
|
+
if (!current || !current[key]) return null;
|
65
|
+
current = current[key];
|
66
|
+
}
|
67
|
+
return current;
|
68
|
+
}
|
69
|
+
|
70
|
+
for (const key in obj) {
|
71
|
+
const keyPath = prefix ? `${prefix}.${key}` : key;
|
72
|
+
const schemaType = getSchemaTypeForKey(schema, keyPath);
|
73
|
+
|
74
|
+
if (schemaType && schemaType.type === 'object' && !schemaType.properties) {
|
75
|
+
if (typeof obj[key] === 'object' && obj[key] !== null) {
|
76
|
+
obj[key] = JSON.stringify(obj[key], null, 2);
|
77
|
+
}
|
78
|
+
} else if (typeof obj[key] === 'object' && obj[key] !== null) {
|
79
|
+
convertObjectsToJsonStrings(obj[key], schema, keyPath);
|
80
|
+
}
|
81
|
+
}
|
82
|
+
}
|
83
|
+
|
57
84
|
|
58
85
|
function convertTextareaToArray(values, formDesc, schema) {
|
59
86
|
// Helper function to get schema type for a key path
|
@@ -107,6 +134,7 @@ function validateSchemaForm(form, formDesc, schema, values, schemaName) {
|
|
107
134
|
err.style.display = 'none';
|
108
135
|
return true;
|
109
136
|
}
|
137
|
+
|
110
138
|
function createSchemaForm($form, schema, onSubmit, schemaName) {
|
111
139
|
if (schema && schema.schema_options) {
|
112
140
|
schema_options = schema.schema_options;
|
@@ -151,6 +179,7 @@ function createSchemaForm($form, schema, onSubmit, schemaName) {
|
|
151
179
|
}
|
152
180
|
}
|
153
181
|
}
|
182
|
+
convertObjectsToJsonStrings(value, schema);
|
154
183
|
} else {
|
155
184
|
value = {};
|
156
185
|
}
|
@@ -205,8 +234,27 @@ function createSchemaForm($form, schema, onSubmit, schemaName) {
|
|
205
234
|
}
|
206
235
|
}
|
207
236
|
formDesc.push({
|
208
|
-
type: '
|
209
|
-
|
237
|
+
type: 'actions',
|
238
|
+
items: [
|
239
|
+
{
|
240
|
+
type: 'submit',
|
241
|
+
title: 'Run',
|
242
|
+
id: 'run-form',
|
243
|
+
},
|
244
|
+
{
|
245
|
+
type: 'button',
|
246
|
+
title: 'Reset',
|
247
|
+
id: 'reset-form',
|
248
|
+
onClick: function (evt) {
|
249
|
+
console.log('reset');
|
250
|
+
evt.preventDefault();
|
251
|
+
evt.stopPropagation();
|
252
|
+
evt.stopImmediatePropagation();
|
253
|
+
schemaValues[schemaName] = {};
|
254
|
+
createSchemaForm($form, schema, onSubmit, schemaName);
|
255
|
+
},
|
256
|
+
},
|
257
|
+
],
|
210
258
|
});
|
211
259
|
} else {
|
212
260
|
if (schema_params_options && schema_params_options.batch_param) {
|
@@ -308,5 +356,3 @@ async function getPostParametersSchema() {
|
|
308
356
|
let schemaForm;
|
309
357
|
// let inputHandlers = [];
|
310
358
|
let schemaValues = JSON.parse(localStorage.getItem('schemaValues')) || {};
|
311
|
-
|
312
|
-
|
pywebexec/static/js/script.js
CHANGED
@@ -163,7 +163,7 @@ async function fetchCommands(hide=false) {
|
|
163
163
|
const commandRow = document.createElement('tr');
|
164
164
|
commandRow.className = `clickable-row ${command.command_id === currentCommandId ? 'currentcommand' : ''}`;
|
165
165
|
commandRow.onclick = () => viewOutput(command.command_id);
|
166
|
-
if (command.status === 'running') runningCommands.push(command.command.replace(
|
166
|
+
if (command.status === 'running') runningCommands.push(command.command.replace(/^\.[\\/]/, ''));
|
167
167
|
commandRow.innerHTML = `
|
168
168
|
<td class="monospace">
|
169
169
|
${navigator.clipboard == undefined ? `${command.command_id.slice(0, 8)}` : `<span class="copy_clip" onclick="copyToClipboard('${command.command_id}', this, event)">${command.command_id.slice(0, 8)}</span>`}
|
@@ -174,7 +174,7 @@ async function fetchCommands(hide=false) {
|
|
174
174
|
<td align="center">
|
175
175
|
${command.command.startsWith('term') ? '' : command.status === 'running' ? `<button class="stop" onclick="stopCommand('${command.command_id}', event)">Stop</button>` : `<button class="run" onclick="relaunchCommand('${command.command_id}', event)">Run</button>`}
|
176
176
|
</td>
|
177
|
-
<td title="${command.user == '-' ? '' : command.user}"><span class="command-line">${command.command.replace(
|
177
|
+
<td title="${command.user == '-' ? '' : command.user}"><span class="command-line">${command.command.replace(/^\.[\\/]/, '')}</span></td>
|
178
178
|
<td class="monospace outcol">
|
179
179
|
<button class="popup-button" onclick="openPopup('${command.command_id}', event)"></button>
|
180
180
|
${command.last_output_line || ''}
|
@@ -204,6 +204,7 @@ function extractHtml(text) {
|
|
204
204
|
async function fetchOutput(url) {
|
205
205
|
if (isPaused) return;
|
206
206
|
try {
|
207
|
+
document.getElementById('output').classList.remove('outputhtml');
|
207
208
|
const response = await fetch(url);
|
208
209
|
if (!response.ok) return;
|
209
210
|
const data = await response.json();
|
@@ -221,12 +222,21 @@ async function fetchOutput(url) {
|
|
221
222
|
fullOutput = fullOutput.slice(-maxSize);
|
222
223
|
|
223
224
|
if (data.status != 'running') {
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
225
|
+
if (data.status === 'success') {
|
226
|
+
const htmlContent = extractHtml(fullOutput);
|
227
|
+
if (htmlContent) {
|
228
|
+
document.getElementById('output').innerHTML = htmlContent;
|
229
|
+
document.getElementById('output').classList.add('outputhtml');
|
230
|
+
} else {
|
231
|
+
if (slider.value == 1000)
|
232
|
+
terminal.write(data.output);
|
233
|
+
else {
|
234
|
+
percentage = Math.round((outputLength * 1000)/fullOutput.length);
|
235
|
+
slider.value = percentage;
|
236
|
+
outputPercentage.innerText = `${Math.floor(percentage/10)}%`;
|
237
|
+
}
|
238
|
+
}
|
228
239
|
} else {
|
229
|
-
document.getElementById('output').classList.remove('outputhtml');
|
230
240
|
if (slider.value == 1000)
|
231
241
|
terminal.write(data.output);
|
232
242
|
else {
|
@@ -284,7 +294,7 @@ async function viewOutput(command_id) {
|
|
284
294
|
if (data.command.endsWith('/run-para')) {
|
285
295
|
command = `${data.params.join(' ').replace(/^.* -- run .\//, 'batch ')}`;
|
286
296
|
} else {
|
287
|
-
command = `${data.command.replace(
|
297
|
+
command = `${data.command.replace(/^\.[\\/]/, '')} ${data.params.join(' ')}`;
|
288
298
|
}
|
289
299
|
setCommandStatus(data.status)
|
290
300
|
commandInfo.innerHTML = command;
|
@@ -303,14 +313,18 @@ async function viewOutput(command_id) {
|
|
303
313
|
const outputResponse = await fetch(nextOutputLink);
|
304
314
|
const outputData = await outputResponse.json();
|
305
315
|
const output = outputData.output;
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
316
|
+
document.getElementById('output').classList.remove('outputhtml');
|
317
|
+
document.getElementById('output').innerHTML = '';
|
318
|
+
document.getElementById('output').appendChild(terminal.element);
|
319
|
+
if (data.status === 'success') {
|
320
|
+
const htmlContent = extractHtml(output);
|
321
|
+
if (htmlContent) {
|
322
|
+
document.getElementById('output').innerHTML = htmlContent;
|
323
|
+
document.getElementById('output').classList.add('outputhtml');
|
324
|
+
} else {
|
325
|
+
terminal.write(output);
|
326
|
+
}
|
310
327
|
} else {
|
311
|
-
document.getElementById('output').classList.remove('outputhtml');
|
312
|
-
document.getElementById('output').innerHTML = '';
|
313
|
-
document.getElementById('output').appendChild(terminal.element);
|
314
328
|
terminal.write(output);
|
315
329
|
}
|
316
330
|
toggleButton.style.display = 'none';
|
pywebexec/version.py
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
pywebexec/__init__.py,sha256=197fHJy0UDBwTTpGCGortZRr-w2kTaD7MxqdbVmTEi0,61
|
2
2
|
pywebexec/host_ip.py,sha256=oiCMlo2o3AkkgXDarUSx8T3FWXKI0vk1-EPnx5FGBd8,1332
|
3
|
-
pywebexec/pywebexec.py,sha256=
|
3
|
+
pywebexec/pywebexec.py,sha256=1M5CtxKr5YkEMBhuVSrwnMNcVRuf7iQf-uxF4Lf0ouQ,48375
|
4
4
|
pywebexec/swagger.yaml,sha256=I_oLpp7Hqel8SDEEykvpmCT-Gv3ytGlziq9bvQOrtZY,7598
|
5
|
-
pywebexec/version.py,sha256=
|
6
|
-
pywebexec/static/css/form.css,sha256=
|
5
|
+
pywebexec/version.py,sha256=yuw-MeUgld_ZQvHY-ySzAKeJ1b7eRT6gVg14nwqZJYY,511
|
6
|
+
pywebexec/static/css/form.css,sha256=vfB0wEHETHWR3vyjkjm3M84CV3vh82yUxAsN8I3UwKg,6757
|
7
7
|
pywebexec/static/css/markdown.css,sha256=br4-iK9wigTs54N2KHtjgZ4KLH0THVSvJo-XZAdMHiE,1970
|
8
|
-
pywebexec/static/css/style.css,sha256=
|
8
|
+
pywebexec/static/css/style.css,sha256=9P46lB-YLCYWRKIG58h_6Goj49ImAMxcWibh_uyrmDo,10308
|
9
9
|
pywebexec/static/css/swagger-ui.css,sha256=xhXN8fnUaIACGHuPIEIr9-qmyYr6Zx0k2wv4Qy7Bg1Y,154985
|
10
10
|
pywebexec/static/css/swagger-ui.css.map,sha256=dJy-xBn_htK4BNupTMIl33ddse7BXsrCdDJWlTJodnw,258842
|
11
11
|
pywebexec/static/css/xterm.css,sha256=uo5phWaUiJgcz0DAzv46uoByLLbJLeetYosL1xf68rY,5559
|
@@ -35,8 +35,8 @@ pywebexec/static/images/success.svg,sha256=NVwezvVMplt46ElW798vqGfrL21Mw_DWHUp_q
|
|
35
35
|
pywebexec/static/images/swagger-ui.svg,sha256=FR0yeOVwe4zCYKZAjCGcT_m0Mf25NexIVaSXifIkoU0,2117
|
36
36
|
pywebexec/static/js/executables.js,sha256=cTgCFHr_F9bFCirtfG_uR32vOY3vNUr4Ih3Wglj5lFc,11988
|
37
37
|
pywebexec/static/js/popup.js,sha256=IaKmk2U2hEn-Nv6krf_PPW6LaG8NcpCkJKb7lUX0qZo,11457
|
38
|
-
pywebexec/static/js/schemaform.js,sha256=
|
39
|
-
pywebexec/static/js/script.js,sha256=
|
38
|
+
pywebexec/static/js/schemaform.js,sha256=57FeWNWJT1zW9sG3ujZEOG7vLoiHif5ROQZori2QNMg,11131
|
39
|
+
pywebexec/static/js/script.js,sha256=TI3TSylgBxh_a6QvYWlg4CyJ6LMPxnhFl8WRtRDGD0Y,20810
|
40
40
|
pywebexec/static/js/swagger-form.js,sha256=CLcSHMhk5P4-_2MIRBoJLgEnIj_9keDDSzUugXHZjio,4565
|
41
41
|
pywebexec/static/js/js-yaml/LICENSE,sha256=oHvCRGi5ZUznalR9R6LbKC0HcztxXbTHOpi9Y5YflVA,1084
|
42
42
|
pywebexec/static/js/js-yaml/js-yaml.min.js,sha256=Rdw90D3AegZwWiwpibjH9wkBPwS9U4bjJ51ORH8H69c,39430
|
@@ -67,9 +67,9 @@ pywebexec/templates/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSu
|
|
67
67
|
pywebexec/templates/index.html,sha256=w18O2plH_yS8bqlPsu5hwFFmCj9H2hWLSV8B6ADcSwU,3900
|
68
68
|
pywebexec/templates/popup.html,sha256=3kpMccKD_OLLhJ4Y9KRw6Ny8wQWjVaRrUfV9y5-bDiQ,1580
|
69
69
|
pywebexec/templates/swagger_ui.html,sha256=MAPr-z96VERAecDvX37V8q2Nxph-O0fNDBul1x2w9SI,1147
|
70
|
-
pywebexec-2.3.
|
71
|
-
pywebexec-2.3.
|
72
|
-
pywebexec-2.3.
|
73
|
-
pywebexec-2.3.
|
74
|
-
pywebexec-2.3.
|
75
|
-
pywebexec-2.3.
|
70
|
+
pywebexec-2.3.5.dist-info/licenses/LICENSE,sha256=gRJf0JPT_wsZJsUGlWPTS8Vypfl9vQ1qjp6sNbKykuA,1064
|
71
|
+
pywebexec-2.3.5.dist-info/METADATA,sha256=ip0nBVVxyEqlIrNJwuV0BCWPKYpjZcRAAZRCOan5tuk,13015
|
72
|
+
pywebexec-2.3.5.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
|
73
|
+
pywebexec-2.3.5.dist-info/entry_points.txt,sha256=l52GBkPCXRkmlHfEyoVauyfBdg8o-CAtC8qQpOIjJK0,55
|
74
|
+
pywebexec-2.3.5.dist-info/top_level.txt,sha256=vHoHyzngrfGdm_nM7Xn_5iLmaCrf10XO1EhldgNLEQ8,10
|
75
|
+
pywebexec-2.3.5.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|