pywebexec 2.4.4__py3-none-any.whl → 2.4.6__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/static/js/exceljs.min.js +45 -0
- pywebexec/static/js/tablefilter.js +148 -42
- pywebexec/templates/index.html +1 -2
- pywebexec/version.py +2 -2
- {pywebexec-2.4.4.dist-info → pywebexec-2.4.6.dist-info}/METADATA +1 -1
- {pywebexec-2.4.4.dist-info → pywebexec-2.4.6.dist-info}/RECORD +10 -9
- {pywebexec-2.4.4.dist-info → pywebexec-2.4.6.dist-info}/WHEEL +0 -0
- {pywebexec-2.4.4.dist-info → pywebexec-2.4.6.dist-info}/entry_points.txt +0 -0
- {pywebexec-2.4.4.dist-info → pywebexec-2.4.6.dist-info}/licenses/LICENSE +0 -0
- {pywebexec-2.4.4.dist-info → pywebexec-2.4.6.dist-info}/top_level.txt +0 -0
@@ -26,6 +26,7 @@ function initTableFilters(table) {
|
|
26
26
|
// Add row counter
|
27
27
|
const rowCount = document.createElement('span');
|
28
28
|
rowCount.className = 'row-count system-font';
|
29
|
+
rowCount.title = 'Export to Excel';
|
29
30
|
rowCount.onclick = () => exportToExcel(table);
|
30
31
|
contentSpan.appendChild(rowCount);
|
31
32
|
}
|
@@ -144,49 +145,154 @@ function applyFilters(table) {
|
|
144
145
|
}
|
145
146
|
}
|
146
147
|
|
148
|
+
function processHtmlContent(element) {
|
149
|
+
function processLi(li, level = 0) {
|
150
|
+
const indent = ' '.repeat(level);
|
151
|
+
const items = [];
|
152
|
+
|
153
|
+
// Extraire le texte direct (avant sous-liste)
|
154
|
+
const textContent = Array.from(li.childNodes)
|
155
|
+
.filter(node => node.nodeType === Node.TEXT_NODE)
|
156
|
+
.map(node => node.textContent.trim())
|
157
|
+
.join(' ')
|
158
|
+
.replace(/\s+/g, ' ')
|
159
|
+
.trim();
|
160
|
+
|
161
|
+
if (textContent) {
|
162
|
+
items.push(indent + '• ' + textContent);
|
163
|
+
}
|
164
|
+
|
165
|
+
// Traiter récursivement les sous-listes
|
166
|
+
const subLists = li.querySelectorAll(':scope > ul > li');
|
167
|
+
if (subLists.length) {
|
168
|
+
for (const subLi of subLists) {
|
169
|
+
items.push(...processLi(subLi, level + 1));
|
170
|
+
}
|
171
|
+
}
|
172
|
+
|
173
|
+
return items;
|
174
|
+
}
|
175
|
+
|
176
|
+
const list = element.querySelector('ul');
|
177
|
+
if (list) {
|
178
|
+
const items = Array.from(list.children)
|
179
|
+
.filter(el => el.tagName === 'LI')
|
180
|
+
.map(li => processLi(li))
|
181
|
+
.flat();
|
182
|
+
return items.join('\n');
|
183
|
+
}
|
184
|
+
const text = element.textContent.replace(/\s+/g, ' ').trim();
|
185
|
+
// Return object with type info if it's a number
|
186
|
+
if (/^\d+$/.test(text)) {
|
187
|
+
return { value: parseInt(text, 10), type: 'integer' };
|
188
|
+
}
|
189
|
+
return text;
|
190
|
+
}
|
191
|
+
|
147
192
|
function exportToExcel(table) {
|
148
|
-
|
149
|
-
const
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
193
|
+
const workbook = new ExcelJS.Workbook();
|
194
|
+
const worksheet = workbook.addWorksheet('Sheet1', {
|
195
|
+
views: [{ state: 'frozen', xSplit: 0, ySplit: 1 }]
|
196
|
+
});
|
197
|
+
|
198
|
+
// Get headers and data
|
199
|
+
const headers = Array.from(table.querySelectorAll('thead th'))
|
200
|
+
.filter((_, i) => i !== 4 || table !== commandsTable)
|
201
|
+
.map(th => th.querySelector('.th-content')?.textContent.replace(/[].*/, '').replace(/[^\w\s]/g, '').trim() || '');
|
202
|
+
|
203
|
+
// Get data rows with type information
|
204
|
+
const rows = Array.from(table.querySelectorAll('tbody tr'))
|
205
|
+
.filter(row => row.style.display !== 'none')
|
206
|
+
.map(row =>
|
207
|
+
Array.from(row.cells)
|
208
|
+
.filter((_, i) => i !== 4 || table !== commandsTable)
|
209
|
+
.map(cell => {
|
210
|
+
const content = processHtmlContent(cell);
|
211
|
+
if (content && typeof content === 'object' && content.type === 'integer') {
|
212
|
+
return content.value; // Numbers will be handled as numbers by ExcelJS
|
213
|
+
}
|
214
|
+
return (typeof content === 'string' ? content : content.toString())
|
215
|
+
})
|
216
|
+
);
|
217
|
+
|
218
|
+
// Calculate optimal column widths based on content
|
219
|
+
const columnWidths = headers.map((header, colIndex) => {
|
220
|
+
// Start with header width
|
221
|
+
let maxWidth = header.length;
|
222
|
+
|
223
|
+
// Check width needed for each row's cell in this column
|
224
|
+
rows.forEach(row => {
|
225
|
+
const cellContent = row[colIndex];
|
226
|
+
if (cellContent === null || cellContent === undefined) return;
|
227
|
+
|
228
|
+
// Convert numbers to string for width calculation
|
229
|
+
const contentStr = cellContent.toString();
|
230
|
+
// Get the longest line in multiline content
|
231
|
+
const lines = contentStr.split('\n');
|
232
|
+
const longestLine = Math.max(...lines.map(line => line.length));
|
233
|
+
maxWidth = Math.max(maxWidth, longestLine);
|
234
|
+
});
|
235
|
+
|
236
|
+
// Add some padding and ensure minimum/maximum widths
|
237
|
+
return { width: Math.min(Math.max(maxWidth + 2, 10), 100) };
|
238
|
+
});
|
239
|
+
|
240
|
+
// Define columns with calculated widths
|
241
|
+
worksheet.columns = headers.map((header, index) => ({
|
242
|
+
header: header,
|
243
|
+
key: header,
|
244
|
+
width: columnWidths[index].width
|
245
|
+
}));
|
246
|
+
|
247
|
+
// Add data rows
|
248
|
+
rows.forEach(rowData => {
|
249
|
+
const row = worksheet.addRow(rowData);
|
250
|
+
row.alignment = { vertical: 'top', wrapText: true };
|
251
|
+
|
252
|
+
// Set row height based on content, handling both strings and numbers
|
253
|
+
// const maxLines = Math.max(...rowData.map(cell => {
|
254
|
+
// if (cell === null || cell === undefined) return 1;
|
255
|
+
// const str = cell.toString();
|
256
|
+
// return (str.match(/\n/g) || []).length + 1;
|
257
|
+
// }));
|
258
|
+
// row.height = Math.max(20, maxLines * 15);
|
259
|
+
});
|
260
|
+
|
261
|
+
// Style header row
|
262
|
+
const headerRow = worksheet.getRow(1);
|
263
|
+
headerRow.font = { bold: true };
|
264
|
+
headerRow.alignment = { vertical: 'middle', horizontal: 'left' };
|
265
|
+
// headerRow.height = 20;
|
266
|
+
|
267
|
+
// Add table after all rows are defined
|
268
|
+
worksheet.addTable({
|
269
|
+
name: 'DataTable',
|
270
|
+
ref: 'A1',
|
271
|
+
headerRow: true,
|
272
|
+
totalsRow: false,
|
273
|
+
style: {
|
274
|
+
theme: 'TableStyleMedium2',
|
275
|
+
showRowStripes: true,
|
276
|
+
},
|
277
|
+
columns: headers.map(h => ({
|
278
|
+
name: h,
|
279
|
+
filterButton: true
|
280
|
+
})),
|
281
|
+
rows: rows
|
282
|
+
});
|
283
|
+
|
284
|
+
// Save file
|
285
|
+
workbook.xlsx.writeBuffer().then(buffer => {
|
286
|
+
const blob = new Blob([buffer], {
|
287
|
+
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
|
288
|
+
});
|
289
|
+
const url = window.URL.createObjectURL(blob);
|
290
|
+
const a = document.createElement('a');
|
291
|
+
a.href = url;
|
292
|
+
a.download = 'export_' + new Date().toISOString().slice(0,10) + '.xlsx';
|
293
|
+
a.click();
|
294
|
+
window.URL.revokeObjectURL(url);
|
295
|
+
});
|
190
296
|
}
|
191
297
|
|
192
298
|
let commandsTable = document.querySelector('#commandsTable');
|
pywebexec/templates/index.html
CHANGED
@@ -68,6 +68,7 @@
|
|
68
68
|
<script src="/static/js/xterm/addon-unicode-graphemes.js"></script>
|
69
69
|
<script src="/static/js/xterm/addon-fit.js"></script>
|
70
70
|
<script src="/static/js/marked/marked.min.js"></script>
|
71
|
+
<script src="/static/js/exceljs.min.js"></script>
|
71
72
|
<script type="text/javascript" src="/static/jsonform/deps/jquery.min.js"></script>
|
72
73
|
<script type="text/javascript" src="/static/jsonform/deps/underscore.js"></script>
|
73
74
|
<script type="text/javascript" src="/static/jsonform/deps/jsv.js"></script>
|
@@ -76,7 +77,5 @@
|
|
76
77
|
<script type="text/javascript" src="/static/js/executables.js"></script>
|
77
78
|
<script type="text/javascript" src="/static/js/schemaform.js"></script>
|
78
79
|
<script type="text/javascript" src="/static/js/tablefilter.js"></script>
|
79
|
-
|
80
|
-
|
81
80
|
</body>
|
82
81
|
</html>
|
pywebexec/version.py
CHANGED
@@ -2,7 +2,7 @@ pywebexec/__init__.py,sha256=197fHJy0UDBwTTpGCGortZRr-w2kTaD7MxqdbVmTEi0,61
|
|
2
2
|
pywebexec/host_ip.py,sha256=oiCMlo2o3AkkgXDarUSx8T3FWXKI0vk1-EPnx5FGBd8,1332
|
3
3
|
pywebexec/pywebexec.py,sha256=NT4f7Xd4qMkAgjgwguqKKbUkOTCqT7ArRYlsW57Pfwg,48477
|
4
4
|
pywebexec/swagger.yaml,sha256=I_oLpp7Hqel8SDEEykvpmCT-Gv3ytGlziq9bvQOrtZY,7598
|
5
|
-
pywebexec/version.py,sha256=
|
5
|
+
pywebexec/version.py,sha256=A7m3JGqv6GgWxdlAhxGqiDnKOY6QWqyUQuVpQYGKv-s,511
|
6
6
|
pywebexec/static/css/form.css,sha256=2JUhraeL46JaiNoD_MSKA2JdouHkXaamhd77DnCqG8k,7291
|
7
7
|
pywebexec/static/css/markdown.css,sha256=br4-iK9wigTs54N2KHtjgZ4KLH0THVSvJo-XZAdMHiE,1970
|
8
8
|
pywebexec/static/css/style.css,sha256=TX60M-mzIPTGVDmaypRCOcyxc8A7dOjx-p1_bpJ6t9M,11772
|
@@ -33,12 +33,13 @@ pywebexec/static/images/resume.svg,sha256=99LP1Ya2JXakRCO9kW8JMuT_4a_CannF65Eiuw
|
|
33
33
|
pywebexec/static/images/running.svg,sha256=fBCYwYb2O9K4N3waC2nURP25NRwZlqR4PbDZy6JQMww,610
|
34
34
|
pywebexec/static/images/success.svg,sha256=NVwezvVMplt46ElW798vqGfrL21Mw_DWHUp_qiD_FU8,489
|
35
35
|
pywebexec/static/images/swagger-ui.svg,sha256=FR0yeOVwe4zCYKZAjCGcT_m0Mf25NexIVaSXifIkoU0,2117
|
36
|
+
pywebexec/static/js/exceljs.min.js,sha256=fknaaFiOJQ27i7oZDSyqirN4fMAoS9odiy-AXE33Qsk,947702
|
36
37
|
pywebexec/static/js/executables.js,sha256=cTgCFHr_F9bFCirtfG_uR32vOY3vNUr4Ih3Wglj5lFc,11988
|
37
38
|
pywebexec/static/js/popup.js,sha256=IaKmk2U2hEn-Nv6krf_PPW6LaG8NcpCkJKb7lUX0qZo,11457
|
38
39
|
pywebexec/static/js/schemaform.js,sha256=2AIjwdjSDTE2ide8UMmQt4tS-7-JKqidKdopq9mNzvo,12458
|
39
40
|
pywebexec/static/js/script.js,sha256=SpNmskHKJHza0Au7QWrb17EKqiMPbMz5CDmaLt_i3M4,21548
|
40
41
|
pywebexec/static/js/swagger-form.js,sha256=CLcSHMhk5P4-_2MIRBoJLgEnIj_9keDDSzUugXHZjio,4565
|
41
|
-
pywebexec/static/js/tablefilter.js,sha256=
|
42
|
+
pywebexec/static/js/tablefilter.js,sha256=PH_OQ2NpaXr1WryM2p4EQVIvxtSLPm4IHDVAK0N6OU8,11093
|
42
43
|
pywebexec/static/js/js-yaml/LICENSE,sha256=oHvCRGi5ZUznalR9R6LbKC0HcztxXbTHOpi9Y5YflVA,1084
|
43
44
|
pywebexec/static/js/js-yaml/js-yaml.min.js,sha256=Rdw90D3AegZwWiwpibjH9wkBPwS9U4bjJ51ORH8H69c,39430
|
44
45
|
pywebexec/static/js/marked/LICENSE.md,sha256=jjo_gvWaYJWPVsoI9EVkfDKkcz3HymwsRvbriYRxq5w,2942
|
@@ -65,12 +66,12 @@ pywebexec/static/jsonform/deps/underscore.js,sha256=SzKOQsVYGX1bmddyfPzGC6yXY_rW
|
|
65
66
|
pywebexec/static/jsonform/deps/img/glyphicons-halflings.png,sha256=hpJM0AbbMLnU8UGOBs172D7vK-dooQ8n0s_ybml3zO0,13826
|
66
67
|
pywebexec/static/jsonform/lib/jsonform.js,sha256=U-BvOgq5gCvSUo36qSAK7Y91RPKOq7vZShkIYpzwlkk,138525
|
67
68
|
pywebexec/templates/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
68
|
-
pywebexec/templates/index.html,sha256=
|
69
|
+
pywebexec/templates/index.html,sha256=Hen-UXHenn3To-7gsHU3kO15hi2Mj--OpUVPb5DyHNk,4026
|
69
70
|
pywebexec/templates/popup.html,sha256=3kpMccKD_OLLhJ4Y9KRw6Ny8wQWjVaRrUfV9y5-bDiQ,1580
|
70
71
|
pywebexec/templates/swagger_ui.html,sha256=MAPr-z96VERAecDvX37V8q2Nxph-O0fNDBul1x2w9SI,1147
|
71
|
-
pywebexec-2.4.
|
72
|
-
pywebexec-2.4.
|
73
|
-
pywebexec-2.4.
|
74
|
-
pywebexec-2.4.
|
75
|
-
pywebexec-2.4.
|
76
|
-
pywebexec-2.4.
|
72
|
+
pywebexec-2.4.6.dist-info/licenses/LICENSE,sha256=gRJf0JPT_wsZJsUGlWPTS8Vypfl9vQ1qjp6sNbKykuA,1064
|
73
|
+
pywebexec-2.4.6.dist-info/METADATA,sha256=ZIbjKPlU2sVW1LQVZcpDnZTiltCx8_trixeXyucDXoY,13015
|
74
|
+
pywebexec-2.4.6.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
|
75
|
+
pywebexec-2.4.6.dist-info/entry_points.txt,sha256=l52GBkPCXRkmlHfEyoVauyfBdg8o-CAtC8qQpOIjJK0,55
|
76
|
+
pywebexec-2.4.6.dist-info/top_level.txt,sha256=vHoHyzngrfGdm_nM7Xn_5iLmaCrf10XO1EhldgNLEQ8,10
|
77
|
+
pywebexec-2.4.6.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|