iobroker.staticsfilefolder 0.0.3 → 0.0.5

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.
package/io-package.json CHANGED
@@ -1,8 +1,14 @@
1
1
  {
2
2
  "common": {
3
3
  "name": "staticsfilefolder",
4
- "version": "0.0.3",
4
+ "version": "0.0.5",
5
5
  "news": {
6
+ "0.0.5": {
7
+ "en": "Added print, download, and file-navigation controls inside the file viewer modal."
8
+ },
9
+ "0.0.4": {
10
+ "en": "Defined latest_file_url and latest_file_path states in instanceObjects so they are created automatically upon installation."
11
+ },
6
12
  "0.0.3": {
7
13
  "en": "Fixed UI theme button visibility in dark mode and resolved PDF opening issue."
8
14
  },
@@ -95,5 +101,32 @@
95
101
  "webInstance": "*"
96
102
  },
97
103
  "objects": [],
98
- "instanceObjects": []
104
+ "instanceObjects": [
105
+ {
106
+ "_id": "latest_file_url",
107
+ "type": "state",
108
+ "common": {
109
+ "name": "Latest File URL",
110
+ "type": "string",
111
+ "role": "url",
112
+ "read": true,
113
+ "write": false,
114
+ "def": ""
115
+ },
116
+ "native": {}
117
+ },
118
+ {
119
+ "_id": "latest_file_path",
120
+ "type": "state",
121
+ "common": {
122
+ "name": "Latest File Path",
123
+ "type": "string",
124
+ "role": "value",
125
+ "read": true,
126
+ "write": false,
127
+ "def": ""
128
+ },
129
+ "native": {}
130
+ }
131
+ ]
99
132
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iobroker.staticsfilefolder",
3
- "version": "0.0.3",
3
+ "version": "0.0.5",
4
4
  "description": "Static Files Folder",
5
5
  "author": {
6
6
  "name": "gokturk413",
package/www/app.js CHANGED
@@ -23,6 +23,15 @@ const sortSelect = document.getElementById('sort-select');
23
23
  const viewerModal = document.getElementById('viewer-modal');
24
24
  const closeModal = document.getElementById('close-modal');
25
25
  const viewerBody = document.getElementById('viewer-body');
26
+ const modalTitle = document.getElementById('modal-title');
27
+ const modalBtnPrev = document.getElementById('modal-btn-prev');
28
+ const modalBtnNext = document.getElementById('modal-btn-next');
29
+ const modalBtnPrint = document.getElementById('modal-btn-print');
30
+ const modalBtnDownload = document.getElementById('modal-btn-download');
31
+
32
+ // Modal Navigation State
33
+ let currentOpenItem = null;
34
+ let currentFilesList = [];
26
35
 
27
36
  // Setup PDF.js worker
28
37
  if (window.pdfjsLib) {
@@ -59,9 +68,16 @@ document.addEventListener('DOMContentLoaded', () => {
59
68
  typeFilter.addEventListener('change', renderItems);
60
69
  sortSelect.addEventListener('change', renderItems);
61
70
 
71
+ // Modal Toolbar Event Listeners
72
+ modalBtnPrev.addEventListener('click', navigateModalPrev);
73
+ modalBtnNext.addEventListener('click', navigateModalNext);
74
+ modalBtnPrint.addEventListener('click', printModalContent);
75
+ modalBtnDownload.addEventListener('click', downloadCurrentFile);
76
+
62
77
  closeModal.addEventListener('click', () => {
63
78
  viewerModal.style.display = 'none';
64
79
  viewerBody.innerHTML = ''; // clear memory
80
+ currentOpenItem = null;
65
81
  });
66
82
  });
67
83
 
@@ -181,6 +197,8 @@ function renderItems() {
181
197
  emptyStateEl.style.display = 'none';
182
198
  }
183
199
 
200
+ currentFilesList = filtered.filter(item => !item.isDirectory);
201
+
184
202
  const today = new Date().setHours(0,0,0,0);
185
203
 
186
204
  filtered.forEach(item => {
@@ -223,19 +241,110 @@ function handleItemClick(item) {
223
241
  const newPath = currentPath ? `${currentPath}/${item.name}` : item.name;
224
242
  navigateTo(newPath);
225
243
  } else {
226
- const filePath = currentPath ? `${currentPath}/${item.name}` : item.name;
244
+ openFile(item);
245
+ }
246
+ }
247
+
248
+ function openFile(item) {
249
+ currentOpenItem = item;
250
+ modalTitle.textContent = item.name;
251
+
252
+ // Find index of current file in currentFilesList
253
+ const index = currentFilesList.findIndex(f => f.name === item.name);
254
+ modalBtnPrev.disabled = index <= 0;
255
+ modalBtnNext.disabled = index === -1 || index >= currentFilesList.length - 1;
256
+
257
+ const filePath = currentPath ? `${currentPath}/${item.name}` : item.name;
258
+ const fileUrl = `${FILE_URL}/${encodeURIComponent(filePath)}`;
259
+
260
+ if (item.ext === '.pdf') {
261
+ openPdf(fileUrl);
262
+ } else if (item.ext === '.xlsx' || item.ext === '.csv') {
263
+ openExcel(fileUrl);
264
+ } else if (item.ext === '.docx') {
265
+ openWord(fileUrl);
266
+ } else {
267
+ // Unhandled file type, just open in new tab
268
+ window.open(fileUrl, '_blank');
269
+ viewerModal.style.display = 'none';
270
+ currentOpenItem = null;
271
+ }
272
+ }
273
+
274
+ function navigateModalPrev() {
275
+ if (!currentOpenItem) return;
276
+ const index = currentFilesList.findIndex(f => f.name === currentOpenItem.name);
277
+ if (index > 0) {
278
+ openFile(currentFilesList[index - 1]);
279
+ }
280
+ }
281
+
282
+ function navigateModalNext() {
283
+ if (!currentOpenItem) return;
284
+ const index = currentFilesList.findIndex(f => f.name === currentOpenItem.name);
285
+ if (index !== -1 && index < currentFilesList.length - 1) {
286
+ openFile(currentFilesList[index + 1]);
287
+ }
288
+ }
289
+
290
+ function printModalContent() {
291
+ if (!currentOpenItem) return;
292
+
293
+ const canvases = viewerBody.querySelectorAll('canvas');
294
+ let contentHtml = '';
295
+
296
+ if (canvases.length > 0) {
297
+ // PDF (which is rendered in canvases)
298
+ canvases.forEach(canvas => {
299
+ const dataUrl = canvas.toDataURL();
300
+ contentHtml += `<img src="${dataUrl}" style="max-width: 100%; margin-bottom: 20px; display: block;" />`;
301
+ });
302
+ } else {
303
+ // Excel table or Word document HTML
304
+ contentHtml = viewerBody.innerHTML;
305
+ }
306
+
307
+ const printWindow = window.open('', '_blank');
308
+ printWindow.document.write(`
309
+ <html>
310
+ <head>
311
+ <title>${currentOpenItem.name}</title>
312
+ <style>
313
+ body { margin: 20px; font-family: sans-serif; background: white; color: black; }
314
+ img, table { max-width: 100%; page-break-inside: avoid; }
315
+ table { border-collapse: collapse; width: 100%; margin-top: 10px; }
316
+ table th, table td { border: 1px solid #ddd; padding: 8px; text-align: left; }
317
+ table th { background-color: #f2f2f2; }
318
+ </style>
319
+ </head>
320
+ <body>
321
+ <h2>${currentOpenItem.name}</h2>
322
+ <hr />
323
+ ${contentHtml}
324
+ <script>
325
+ window.onload = function() {
326
+ setTimeout(() => {
327
+ window.print();
328
+ window.close();
329
+ }, 500);
330
+ };
331
+ <\/script>
332
+ </body>
333
+ </html>
334
+ `);
335
+ printWindow.document.close();
336
+ }
337
+
338
+ function downloadCurrentFile() {
339
+ if (currentOpenItem) {
340
+ const filePath = currentPath ? `${currentPath}/${currentOpenItem.name}` : currentOpenItem.name;
227
341
  const fileUrl = `${FILE_URL}/${encodeURIComponent(filePath)}`;
228
-
229
- if (item.ext === '.pdf') {
230
- openPdf(fileUrl);
231
- } else if (item.ext === '.xlsx' || item.ext === '.csv') {
232
- openExcel(fileUrl);
233
- } else if (item.ext === '.docx') {
234
- openWord(fileUrl);
235
- } else {
236
- // Unhandled file type, just open in new tab
237
- window.open(fileUrl, '_blank');
238
- }
342
+ const a = document.createElement('a');
343
+ a.href = fileUrl;
344
+ a.download = currentOpenItem.name;
345
+ document.body.appendChild(a);
346
+ a.click();
347
+ document.body.removeChild(a);
239
348
  }
240
349
  }
241
350
 
package/www/index.html CHANGED
@@ -60,7 +60,16 @@
60
60
  <!-- Viewer Modal -->
61
61
  <div id="viewer-modal" class="modal">
62
62
  <div class="modal-content">
63
- <span id="close-modal" class="close-button">&times;</span>
63
+ <header class="modal-header">
64
+ <div class="modal-title" id="modal-title">Fayl Baxışı</div>
65
+ <div class="modal-toolbar">
66
+ <button id="modal-btn-prev" class="nav-btn" title="Əvvəlki">&larr; Geri</button>
67
+ <button id="modal-btn-next" class="nav-btn" title="Növbəti">İrəli &rarr;</button>
68
+ <button id="modal-btn-print" class="nav-btn" title="Çap et / PDF olaraq saxla">🖨️ Çap / PDF</button>
69
+ <button id="modal-btn-download" class="nav-btn" title="Faylı Yüklə / Export">📥 Yüklə</button>
70
+ <span id="close-modal" class="close-button">&times;</span>
71
+ </div>
72
+ </header>
64
73
  <div id="viewer-body">
65
74
  <!-- Viewer content (Canvas for PDF, Table for Excel, HTML for Word) -->
66
75
  </div>
package/www/style.css CHANGED
@@ -218,11 +218,9 @@ body {
218
218
 
219
219
  .close-button {
220
220
  color: var(--text-muted);
221
- align-self: flex-end;
222
221
  font-size: 28px;
223
222
  font-weight: bold;
224
223
  cursor: pointer;
225
- margin-bottom: 10px;
226
224
  }
227
225
 
228
226
  .close-button:hover,
@@ -264,3 +262,37 @@ table.sheetjs-table th, table.sheetjs-table td {
264
262
  table.sheetjs-table th {
265
263
  background-color: var(--hover-color);
266
264
  }
265
+
266
+ /* Modal Header and Toolbar Styles */
267
+ .modal-header {
268
+ display: flex;
269
+ justify-content: space-between;
270
+ align-items: center;
271
+ padding-bottom: 15px;
272
+ border-bottom: 1px solid var(--border-color);
273
+ margin-bottom: 15px;
274
+ }
275
+
276
+ .modal-title {
277
+ font-size: 1.25rem;
278
+ font-weight: 600;
279
+ color: var(--text-color);
280
+ white-space: nowrap;
281
+ overflow: hidden;
282
+ text-overflow: ellipsis;
283
+ max-width: 40%;
284
+ }
285
+
286
+ .modal-toolbar {
287
+ display: flex;
288
+ align-items: center;
289
+ gap: 8px;
290
+ }
291
+
292
+ .modal-toolbar .close-button {
293
+ font-size: 32px;
294
+ line-height: 1;
295
+ margin-bottom: 0;
296
+ margin-left: 15px;
297
+ align-self: center;
298
+ }