iobroker.script-restore 0.0.10 → 0.0.12

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.
@@ -1,40 +1,40 @@
1
1
  {
2
- "localSection": "Local Backups",
3
- "localEnabled": "Enable local backups",
4
- "backupPath": "Backup path",
5
- "suggestPath": "Suggest path",
6
- "ftpSection": "FTP",
7
- "ftpEnabled": "Enable FTP",
2
+ "backupPath": "Ścieżka kopii zapasowej",
3
+ "ftpEnabled": "Włącz FTP",
8
4
  "ftpHost": "Host",
5
+ "ftpPassword": "Hasło",
6
+ "ftpPath": "Ścieżka",
9
7
  "ftpPort": "Port",
10
- "ftpSecure": "Use FTPS (TLS)",
11
- "ftpUser": "User",
12
- "ftpPassword": "Password",
13
- "ftpPath": "Path",
14
- "testConnection": "Test connection",
15
- "smbSection": "SMB (v2)",
16
- "smbEnabled": "Enable SMB",
17
- "smbInfo": "Only SMB2 is supported.",
18
- "smbHost": "Host / IP",
19
- "smbShare": "Share name",
20
- "smbPath": "Sub-path (optional)",
21
- "smbDomain": "Domain (optional)",
22
- "smbUser": "User",
23
- "smbPassword": "Password",
8
+ "ftpSection": "FTP",
9
+ "ftpSecure": "Użyj FTPS (TLS)",
10
+ "ftpUser": "Użytkownik",
11
+ "httpEnabled": "Włącz źródło HTTP/HTTPS",
12
+ "httpInfo": "Wprowadź bezpośredni adres URL do pliku kopii zapasowej .tar.gz w głównej karcie. Protokół (https://) jest dodawany automatycznie, jeśli zostanie pominięty.",
24
13
  "httpSection": "HTTP/HTTPS",
25
- "httpEnabled": "Enable HTTP/HTTPS source",
26
- "httpInfo": "Enter a direct URL to a .tar.gz backup file in the main tab. The protocol (https://) is added automatically if omitted.",
27
- "sftpSection": "SFTP",
28
- "sftpEnabled": "Enable SFTP",
14
+ "localEnabled": "Włącz lokalne kopie zapasowe",
15
+ "localSection": "Lokalne kopie zapasowe",
16
+ "sftpEnabled": "Włącz SFTP",
29
17
  "sftpHost": "Host / IP",
18
+ "sftpPassword": "Hasło",
19
+ "sftpPath": "Ścieżka",
30
20
  "sftpPort": "Port",
31
- "sftpUser": "User",
32
- "sftpPassword": "Password",
33
- "sftpPath": "Path",
21
+ "sftpSection": "SFTP",
22
+ "sftpUser": "Użytkownik",
23
+ "smbDomain": "Domena (opcjonalna)",
24
+ "smbEnabled": "Włącz SMB",
25
+ "smbHost": "Host / IP",
26
+ "smbInfo": "Obsługiwany jest tylko SMB2.",
27
+ "smbPassword": "Hasło",
28
+ "smbPath": "Podścieżka (opcjonalna)",
29
+ "smbSection": "SMB (v2)",
30
+ "smbShare": "Nazwa udziału",
31
+ "smbUser": "Użytkownik",
32
+ "suggestPath": "Zaproponuj ścieżkę",
33
+ "testConnection": "Testuj połączenie",
34
+ "webdavEnabled": "Włącz WebDAV",
35
+ "webdavPassword": "Hasło",
36
+ "webdavPath": "Ścieżka",
34
37
  "webdavSection": "WebDAV",
35
- "webdavEnabled": "Enable WebDAV",
36
- "webdavUrl": "Server URL",
37
- "webdavUser": "User",
38
- "webdavPassword": "Password",
39
- "webdavPath": "Path"
38
+ "webdavUrl": "Adres URL serwera",
39
+ "webdavUser": "Użytkownik"
40
40
  }
@@ -1,40 +1,40 @@
1
1
  {
2
- "localSection": "Local Backups",
3
- "localEnabled": "Enable local backups",
4
- "backupPath": "Backup path",
5
- "suggestPath": "Suggest path",
6
- "ftpSection": "FTP",
7
- "ftpEnabled": "Enable FTP",
2
+ "backupPath": "Caminho da cópia de segurança",
3
+ "ftpEnabled": "Ativar FTP",
8
4
  "ftpHost": "Host",
9
- "ftpPort": "Port",
10
- "ftpSecure": "Use FTPS (TLS)",
11
- "ftpUser": "User",
12
- "ftpPassword": "Password",
13
- "ftpPath": "Path",
14
- "testConnection": "Test connection",
15
- "smbSection": "SMB (v2)",
16
- "smbEnabled": "Enable SMB",
17
- "smbInfo": "Only SMB2 is supported.",
18
- "smbHost": "Host / IP",
19
- "smbShare": "Share name",
20
- "smbPath": "Sub-path (optional)",
21
- "smbDomain": "Domain (optional)",
22
- "smbUser": "User",
23
- "smbPassword": "Password",
5
+ "ftpPassword": "Palavra-passe",
6
+ "ftpPath": "Caminho",
7
+ "ftpPort": "Porta",
8
+ "ftpSection": "FTP",
9
+ "ftpSecure": "Usar FTPS (TLS)",
10
+ "ftpUser": "Utilizador",
11
+ "httpEnabled": "Ativar fonte HTTP/HTTPS",
12
+ "httpInfo": "Introduza um URL direto para um ficheiro de cópia de segurança .tar.gz no separador principal. O protocolo (https://) é adicionado automaticamente se omitido.",
24
13
  "httpSection": "HTTP/HTTPS",
25
- "httpEnabled": "Enable HTTP/HTTPS source",
26
- "httpInfo": "Enter a direct URL to a .tar.gz backup file in the main tab. The protocol (https://) is added automatically if omitted.",
27
- "sftpSection": "SFTP",
28
- "sftpEnabled": "Enable SFTP",
14
+ "localEnabled": "Ativar cópias de segurança locais",
15
+ "localSection": "Cópias de segurança locais",
16
+ "sftpEnabled": "Ativar SFTP",
29
17
  "sftpHost": "Host / IP",
30
- "sftpPort": "Port",
31
- "sftpUser": "User",
32
- "sftpPassword": "Password",
33
- "sftpPath": "Path",
18
+ "sftpPassword": "Palavra-passe",
19
+ "sftpPath": "Caminho",
20
+ "sftpPort": "Porta",
21
+ "sftpSection": "SFTP",
22
+ "sftpUser": "Utilizador",
23
+ "smbDomain": "Domínio (opcional)",
24
+ "smbEnabled": "Ativar SMB",
25
+ "smbHost": "Host / IP",
26
+ "smbInfo": "Apenas SMB2 é suportado.",
27
+ "smbPassword": "Palavra-passe",
28
+ "smbPath": "Sub-caminho (opcional)",
29
+ "smbSection": "SMB (v2)",
30
+ "smbShare": "Nome da partilha",
31
+ "smbUser": "Utilizador",
32
+ "suggestPath": "Sugerir caminho",
33
+ "testConnection": "Testar ligação",
34
+ "webdavEnabled": "Ativar WebDAV",
35
+ "webdavPassword": "Palavra-passe",
36
+ "webdavPath": "Caminho",
34
37
  "webdavSection": "WebDAV",
35
- "webdavEnabled": "Enable WebDAV",
36
- "webdavUrl": "Server URL",
37
- "webdavUser": "User",
38
- "webdavPassword": "Password",
39
- "webdavPath": "Path"
38
+ "webdavUrl": "URL do servidor",
39
+ "webdavUser": "Utilizador"
40
40
  }
@@ -1,40 +1,40 @@
1
1
  {
2
- "localSection": "Local Backups",
3
- "localEnabled": "Enable local backups",
4
- "backupPath": "Backup path",
5
- "suggestPath": "Suggest path",
2
+ "backupPath": "Путь к резервным копиям",
3
+ "ftpEnabled": "Включить FTP",
4
+ "ftpHost": "Хост",
5
+ "ftpPassword": "Пароль",
6
+ "ftpPath": "Путь",
7
+ "ftpPort": "Порт",
6
8
  "ftpSection": "FTP",
7
- "ftpEnabled": "Enable FTP",
8
- "ftpHost": "Host",
9
- "ftpPort": "Port",
10
- "ftpSecure": "Use FTPS (TLS)",
11
- "ftpUser": "User",
12
- "ftpPassword": "Password",
13
- "ftpPath": "Path",
14
- "testConnection": "Test connection",
15
- "smbSection": "SMB (v2)",
16
- "smbEnabled": "Enable SMB",
17
- "smbInfo": "Only SMB2 is supported.",
18
- "smbHost": "Host / IP",
19
- "smbShare": "Share name",
20
- "smbPath": "Sub-path (optional)",
21
- "smbDomain": "Domain (optional)",
22
- "smbUser": "User",
23
- "smbPassword": "Password",
9
+ "ftpSecure": "Использовать FTPS (TLS)",
10
+ "ftpUser": "Пользователь",
11
+ "httpEnabled": "Включить источник HTTP/HTTPS",
12
+ "httpInfo": "Введите прямой URL к файлу резервной копии .tar.gz на главной вкладке. Протокол (https://) добавляется автоматически, если не указан.",
24
13
  "httpSection": "HTTP/HTTPS",
25
- "httpEnabled": "Enable HTTP/HTTPS source",
26
- "httpInfo": "Enter a direct URL to a .tar.gz backup file in the main tab. The protocol (https://) is added automatically if omitted.",
14
+ "localEnabled": "Включить локальные резервные копии",
15
+ "localSection": "Локальные резервные копии",
16
+ "sftpEnabled": "Включить SFTP",
17
+ "sftpHost": "Хост / IP",
18
+ "sftpPassword": "Пароль",
19
+ "sftpPath": "Путь",
20
+ "sftpPort": "Порт",
27
21
  "sftpSection": "SFTP",
28
- "sftpEnabled": "Enable SFTP",
29
- "sftpHost": "Host / IP",
30
- "sftpPort": "Port",
31
- "sftpUser": "User",
32
- "sftpPassword": "Password",
33
- "sftpPath": "Path",
22
+ "sftpUser": "Пользователь",
23
+ "smbDomain": "Домен (необязательно)",
24
+ "smbEnabled": "Включить SMB",
25
+ "smbHost": "Хост / IP",
26
+ "smbInfo": "Поддерживается только SMB2.",
27
+ "smbPassword": "Пароль",
28
+ "smbPath": "Подпуть (необязательно)",
29
+ "smbSection": "SMB (v2)",
30
+ "smbShare": "Имя общего ресурса",
31
+ "smbUser": "Пользователь",
32
+ "suggestPath": "Предложить путь",
33
+ "testConnection": "Проверить соединение",
34
+ "webdavEnabled": "Включить WebDAV",
35
+ "webdavPassword": "Пароль",
36
+ "webdavPath": "Путь",
34
37
  "webdavSection": "WebDAV",
35
- "webdavEnabled": "Enable WebDAV",
36
- "webdavUrl": "Server URL",
37
- "webdavUser": "User",
38
- "webdavPassword": "Password",
39
- "webdavPath": "Path"
38
+ "webdavUrl": "URL сервера",
39
+ "webdavUser": "Пользователь"
40
40
  }
@@ -1,40 +1,40 @@
1
1
  {
2
- "localSection": "Local Backups",
3
- "localEnabled": "Enable local backups",
4
- "backupPath": "Backup path",
5
- "suggestPath": "Suggest path",
2
+ "backupPath": "Шлях до резервних копій",
3
+ "ftpEnabled": "Увімкнути FTP",
4
+ "ftpHost": "Хост",
5
+ "ftpPassword": "Пароль",
6
+ "ftpPath": "Шлях",
7
+ "ftpPort": "Порт",
6
8
  "ftpSection": "FTP",
7
- "ftpEnabled": "Enable FTP",
8
- "ftpHost": "Host",
9
- "ftpPort": "Port",
10
- "ftpSecure": "Use FTPS (TLS)",
11
- "ftpUser": "User",
12
- "ftpPassword": "Password",
13
- "ftpPath": "Path",
14
- "testConnection": "Test connection",
15
- "smbSection": "SMB (v2)",
16
- "smbEnabled": "Enable SMB",
17
- "smbInfo": "Only SMB2 is supported.",
18
- "smbHost": "Host / IP",
19
- "smbShare": "Share name",
20
- "smbPath": "Sub-path (optional)",
21
- "smbDomain": "Domain (optional)",
22
- "smbUser": "User",
23
- "smbPassword": "Password",
9
+ "ftpSecure": "Використовувати FTPS (TLS)",
10
+ "ftpUser": "Користувач",
11
+ "httpEnabled": "Увімкнути джерело HTTP/HTTPS",
12
+ "httpInfo": "Введіть пряме посилання на файл резервної копії .tar.gz у головній вкладці. Протокол (https://) додається автоматично, якщо не вказано.",
24
13
  "httpSection": "HTTP/HTTPS",
25
- "httpEnabled": "Enable HTTP/HTTPS source",
26
- "httpInfo": "Enter a direct URL to a .tar.gz backup file in the main tab. The protocol (https://) is added automatically if omitted.",
14
+ "localEnabled": "Увімкнути локальні резервні копії",
15
+ "localSection": "Локальні резервні копії",
16
+ "sftpEnabled": "Увімкнути SFTP",
17
+ "sftpHost": "Хост / IP",
18
+ "sftpPassword": "Пароль",
19
+ "sftpPath": "Шлях",
20
+ "sftpPort": "Порт",
27
21
  "sftpSection": "SFTP",
28
- "sftpEnabled": "Enable SFTP",
29
- "sftpHost": "Host / IP",
30
- "sftpPort": "Port",
31
- "sftpUser": "User",
32
- "sftpPassword": "Password",
33
- "sftpPath": "Path",
22
+ "sftpUser": "Користувач",
23
+ "smbDomain": "Домен (необов'язково)",
24
+ "smbEnabled": "Увімкнути SMB",
25
+ "smbHost": "Хост / IP",
26
+ "smbInfo": "Підтримується лише SMB2.",
27
+ "smbPassword": "Пароль",
28
+ "smbPath": "Підшлях (необов'язково)",
29
+ "smbSection": "SMB (v2)",
30
+ "smbShare": "Ім'я спільного ресурсу",
31
+ "smbUser": "Користувач",
32
+ "suggestPath": "Запропонувати шлях",
33
+ "testConnection": "Перевірити з'єднання",
34
+ "webdavEnabled": "Увімкнути WebDAV",
35
+ "webdavPassword": "Пароль",
36
+ "webdavPath": "Шлях",
34
37
  "webdavSection": "WebDAV",
35
- "webdavEnabled": "Enable WebDAV",
36
- "webdavUrl": "Server URL",
37
- "webdavUser": "User",
38
- "webdavPassword": "Password",
39
- "webdavPath": "Path"
38
+ "webdavUrl": "URL сервера",
39
+ "webdavUser": "Користувач"
40
40
  }
@@ -1,40 +1,40 @@
1
1
  {
2
- "localSection": "Local Backups",
3
- "localEnabled": "Enable local backups",
4
- "backupPath": "Backup path",
5
- "suggestPath": "Suggest path",
2
+ "backupPath": "备份路径",
3
+ "ftpEnabled": "启用 FTP",
4
+ "ftpHost": "主机",
5
+ "ftpPassword": "密码",
6
+ "ftpPath": "路径",
7
+ "ftpPort": "端口",
6
8
  "ftpSection": "FTP",
7
- "ftpEnabled": "Enable FTP",
8
- "ftpHost": "Host",
9
- "ftpPort": "Port",
10
- "ftpSecure": "Use FTPS (TLS)",
11
- "ftpUser": "User",
12
- "ftpPassword": "Password",
13
- "ftpPath": "Path",
14
- "testConnection": "Test connection",
15
- "smbSection": "SMB (v2)",
16
- "smbEnabled": "Enable SMB",
17
- "smbInfo": "Only SMB2 is supported.",
18
- "smbHost": "Host / IP",
19
- "smbShare": "Share name",
20
- "smbPath": "Sub-path (optional)",
21
- "smbDomain": "Domain (optional)",
22
- "smbUser": "User",
23
- "smbPassword": "Password",
9
+ "ftpSecure": "使用 FTPS (TLS)",
10
+ "ftpUser": "用户",
11
+ "httpEnabled": "启用 HTTP/HTTPS 来源",
12
+ "httpInfo": "在主标签页中输入 .tar.gz 备份文件的直接 URL。如果省略协议 (https://),将自动添加。",
24
13
  "httpSection": "HTTP/HTTPS",
25
- "httpEnabled": "Enable HTTP/HTTPS source",
26
- "httpInfo": "Enter a direct URL to a .tar.gz backup file in the main tab. The protocol (https://) is added automatically if omitted.",
14
+ "localEnabled": "启用本地备份",
15
+ "localSection": "本地备份",
16
+ "sftpEnabled": "启用 SFTP",
17
+ "sftpHost": "主机 / IP",
18
+ "sftpPassword": "密码",
19
+ "sftpPath": "路径",
20
+ "sftpPort": "端口",
27
21
  "sftpSection": "SFTP",
28
- "sftpEnabled": "Enable SFTP",
29
- "sftpHost": "Host / IP",
30
- "sftpPort": "Port",
31
- "sftpUser": "User",
32
- "sftpPassword": "Password",
33
- "sftpPath": "Path",
22
+ "sftpUser": "用户",
23
+ "smbDomain": "域名(可选)",
24
+ "smbEnabled": "启用 SMB",
25
+ "smbHost": "主机 / IP",
26
+ "smbInfo": "仅支持 SMB2。",
27
+ "smbPassword": "密码",
28
+ "smbPath": "子路径(可选)",
29
+ "smbSection": "SMB (v2)",
30
+ "smbShare": "共享名称",
31
+ "smbUser": "用户",
32
+ "suggestPath": "建议路径",
33
+ "testConnection": "测试连接",
34
+ "webdavEnabled": "启用 WebDAV",
35
+ "webdavPassword": "密码",
36
+ "webdavPath": "路径",
34
37
  "webdavSection": "WebDAV",
35
- "webdavEnabled": "Enable WebDAV",
36
- "webdavUrl": "Server URL",
37
- "webdavUser": "User",
38
- "webdavPassword": "Password",
39
- "webdavPath": "Path"
38
+ "webdavUrl": "服务器 URL",
39
+ "webdavUser": "用户"
40
40
  }
package/admin/tab_m.html CHANGED
@@ -297,6 +297,66 @@
297
297
  body.dark .progress-inner { background: rgba(26,26,46,0.95); }
298
298
  body.dark #loaderText { color: #c0c0d0; }
299
299
 
300
+ /* Type Filter Bar */
301
+ .type-filter-bar {
302
+ display: flex; gap: 4px; padding: 5px 8px;
303
+ border-bottom: 1px solid var(--border); flex-shrink: 0; flex-wrap: wrap;
304
+ }
305
+ .btn-type {
306
+ background: transparent; border: 1px solid #ced4da; border-radius: 3px;
307
+ padding: 2px 8px; cursor: pointer; font-size: 0.8rem; color: #495057;
308
+ transition: 0.15s; font-family: var(--font-main);
309
+ }
310
+ .btn-type:hover { background: #f0f0f0; }
311
+ .btn-type.active { background: #e9ecef; border-color: #999; font-weight: 600; }
312
+ .btn-type .type-badge { margin: 0; pointer-events: none; }
313
+ .restore-suffix-input {
314
+ width: 70px; padding: 2px 6px; border: 1px solid #555;
315
+ background: #1e1e1e; color: #d4d4d4; border-radius: 3px; font-size: 0.85rem;
316
+ font-family: var(--font-main);
317
+ }
318
+ body.dark .type-filter-bar { border-bottom-color: #3a3a5c; }
319
+ body.dark .btn-type { color: #c0c0d0; border-color: #4a4a6a; }
320
+ body.dark .btn-type:hover { background: #3a3a5c; }
321
+ body.dark .btn-type.active { background: #3a3a5c; border-color: #7070a0; }
322
+
323
+ /* Restore Modal */
324
+ .restore-modal-overlay {
325
+ display: none; position: fixed; inset: 0;
326
+ background: rgba(0,0,0,0.5); z-index: 10000;
327
+ align-items: center; justify-content: center;
328
+ }
329
+ .restore-modal-overlay.open { display: flex; }
330
+ .restore-modal {
331
+ background: white; border-radius: 8px; padding: 24px;
332
+ min-width: 360px; max-width: 520px; width: 90%;
333
+ box-shadow: 0 8px 32px rgba(0,0,0,0.25); font-family: var(--font-main);
334
+ }
335
+ .restore-modal h3 { margin: 0 0 16px; font-size: 1.1rem; color: #111; }
336
+ .restore-modal-meta { background: #f8f9fa; border-radius: 4px; padding: 10px 12px; margin-bottom: 16px; font-size: 0.85rem; }
337
+ .restore-modal-meta div { color: #555; margin-bottom: 4px; }
338
+ .restore-modal-meta div:last-child { margin-bottom: 0; }
339
+ .restore-modal-meta strong { color: #111; }
340
+ .restore-modal label { display: block; font-size: 0.85rem; color: #555; margin-bottom: 6px; }
341
+ .restore-modal input[type=text] {
342
+ width: 100%; padding: 8px 10px; border: 1px solid #ced4da; border-radius: 4px;
343
+ font-size: 0.95rem; font-family: var(--font-main); box-sizing: border-box;
344
+ }
345
+ .restore-modal input[type=text]:focus { outline: none; border-color: var(--primary); }
346
+ .restore-modal-preview {
347
+ margin-top: 10px; font-size: 0.8rem; color: #6c757d;
348
+ font-family: 'Consolas', monospace; word-break: break-all;
349
+ }
350
+ .restore-modal-footer { display: flex; gap: 8px; justify-content: flex-end; margin-top: 20px; }
351
+ body.dark .restore-modal { background: #252537; }
352
+ body.dark .restore-modal h3 { color: #e0e0e0; }
353
+ body.dark .restore-modal-meta { background: #1a1a2e; }
354
+ body.dark .restore-modal-meta div { color: #aaa; }
355
+ body.dark .restore-modal-meta strong { color: #e0e0e0; }
356
+ body.dark .restore-modal label { color: #aaa; }
357
+ body.dark .restore-modal input[type=text] { background: #1a1a2e; border-color: #4a4a6a; color: #e0e0e0; }
358
+ body.dark .restore-modal-preview { color: #7a7aaa; }
359
+
300
360
  /* Responsive */
301
361
  @media (max-width: 768px) {
302
362
  .toolbar { padding: 6px 8px; }
@@ -316,6 +376,26 @@
316
376
  <div id="loaderText">Lade Backup...</div>
317
377
  </div>
318
378
 
379
+ <!-- Restore Modal -->
380
+ <div class="restore-modal-overlay" id="restoreModalOverlay" onclick="closeRestoreModal(event)">
381
+ <div class="restore-modal" onclick="event.stopPropagation()">
382
+ <h3>In ioBroker laden</h3>
383
+ <div class="restore-modal-meta">
384
+ <div>Skript: <strong id="rmScriptName"></strong></div>
385
+ <div>Pfad: <strong id="rmScriptPath"></strong></div>
386
+ <div>Typ: <strong id="rmScriptType"></strong></div>
387
+ </div>
388
+ <label for="rmSuffix">Suffix (wird an den Skriptnamen angehängt)</label>
389
+ <input type="text" id="rmSuffix" value="_rcvr" oninput="updateRestorePreview()">
390
+ <div class="restore-modal-preview" id="rmPreview"></div>
391
+ <div class="restore-modal-footer">
392
+ <span id="rmMsg" style="flex:1;font-size:0.85rem;align-self:center;"></span>
393
+ <button class="btn btn-outline" onclick="closeRestoreModal()">Abbrechen</button>
394
+ <button class="btn btn-outline-success" id="rmConfirmBtn" onclick="confirmRestoreScript()">Laden</button>
395
+ </div>
396
+ </div>
397
+ </div>
398
+
319
399
  <div class="toolbar">
320
400
  <div class="toolbar-left">
321
401
  <label class="file-input-label">
@@ -367,6 +447,13 @@
367
447
  <input type="text" id="q" placeholder="Suche in Namen, Ordner &amp; Code...">
368
448
  <button class="btn-icon" id="expandToggleBtn" onclick="toggleExpandAll()" title="Alle Ordner aufklappen">📂</button>
369
449
  </div>
450
+ <div class="type-filter-bar">
451
+ <button class="btn-type active" onclick="setTypeFilter(this, '')">Alle</button>
452
+ <button class="btn-type" onclick="setTypeFilter(this, 'JS')"><span class="type-badge badge-JS">JS</span></button>
453
+ <button class="btn-type" onclick="setTypeFilter(this, 'TypeScript')"><span class="type-badge badge-TypeScript">TS</span></button>
454
+ <button class="btn-type" onclick="setTypeFilter(this, 'Blockly')"><span class="type-badge badge-Blockly">Blockly</span></button>
455
+ <button class="btn-type" onclick="setTypeFilter(this, 'Rules')"><span class="type-badge badge-Rules">Rules</span></button>
456
+ </div>
370
457
  <div id="list" class="script-list"></div>
371
458
  </div>
372
459
 
@@ -376,7 +463,8 @@
376
463
  <div class="action-bar" id="actionBar">
377
464
  <div class="action-bar-inner">
378
465
  <div class="btn-group" id="viewSwitcher"></div>
379
- <div style="display:flex;gap:6px;">
466
+ <div style="display:flex;gap:8px;align-items:center;flex-wrap:wrap;">
467
+ <button onclick="openRestoreModal()" class="btn btn-outline-success" id="restoreBtn">In ioBroker laden</button>
380
468
  <button onclick="copyCode(this)" class="btn btn-outline-light">Code Kopieren</button>
381
469
  <button onclick="downloadActive()" class="btn btn-primary" id="dlBtn">Download</button>
382
470
  </div>
@@ -578,6 +666,7 @@
578
666
  let cur = { index: -1 };
579
667
  const openFolders = new Set();
580
668
  let isAllExpanded = false;
669
+ let activeTypeFilter = '';
581
670
 
582
671
  function escapeHTML(str) {
583
672
  if (!str) return '';
@@ -1023,13 +1112,15 @@
1023
1112
  const toggleBtn = document.getElementById('expandToggleBtn');
1024
1113
  const tree = buildTree(scriptsData);
1025
1114
 
1026
- if (q) {
1115
+ if (q || activeTypeFilter) {
1027
1116
  toggleBtn.style.display = 'none';
1028
1117
  const filter = (node, path) => {
1029
1118
  if (!node.isDir) {
1030
- return node.script.name.toLowerCase().includes(q) ||
1119
+ const typeOk = !activeTypeFilter || node.script.type === activeTypeFilter;
1120
+ const qOk = !q || node.script.name.toLowerCase().includes(q) ||
1031
1121
  node.script.path.toLowerCase().includes(q) ||
1032
1122
  (node.script.source && node.script.source.toLowerCase().includes(q));
1123
+ return typeOk && qOk;
1033
1124
  }
1034
1125
  let has = false;
1035
1126
  for (const k in node.children) {
@@ -1144,6 +1235,69 @@
1144
1235
  }
1145
1236
 
1146
1237
  document.getElementById('q').addEventListener('keyup', renderList);
1238
+
1239
+ // === Type Filter ===
1240
+ function setTypeFilter(btn, type) {
1241
+ activeTypeFilter = type;
1242
+ document.querySelectorAll('.btn-type').forEach(b => b.classList.remove('active'));
1243
+ btn.classList.add('active');
1244
+ renderList();
1245
+ }
1246
+
1247
+ // === Restore Modal ===
1248
+ function openRestoreModal() {
1249
+ if (cur.index < 0) return;
1250
+ const s = scriptsData[cur.index];
1251
+ document.getElementById('rmScriptName').textContent = s.name;
1252
+ document.getElementById('rmScriptPath').textContent = s.path;
1253
+ document.getElementById('rmScriptType').textContent = s.type;
1254
+ document.getElementById('rmSuffix').value = '_rcvr';
1255
+ document.getElementById('rmMsg').textContent = '';
1256
+ document.getElementById('rmMsg').style.color = '';
1257
+ document.getElementById('rmConfirmBtn').disabled = false;
1258
+ updateRestorePreview();
1259
+ document.getElementById('restoreModalOverlay').classList.add('open');
1260
+ setTimeout(() => document.getElementById('rmSuffix').focus(), 50);
1261
+ }
1262
+
1263
+ function closeRestoreModal(e) {
1264
+ if (e && e.target !== document.getElementById('restoreModalOverlay')) return;
1265
+ document.getElementById('restoreModalOverlay').classList.remove('open');
1266
+ }
1267
+
1268
+ function updateRestorePreview() {
1269
+ if (cur.index < 0) return;
1270
+ const s = scriptsData[cur.index];
1271
+ const suffix = document.getElementById('rmSuffix').value.trim();
1272
+ const parts = s.path.split('.');
1273
+ parts[parts.length - 1] = parts[parts.length - 1] + suffix;
1274
+ document.getElementById('rmPreview').textContent = '→ script.js.' + parts.join('.');
1275
+ }
1276
+
1277
+ function confirmRestoreScript() {
1278
+ if (cur.index < 0) return;
1279
+ const s = scriptsData[cur.index];
1280
+ const suffix = document.getElementById('rmSuffix').value.trim() || '_rcvr';
1281
+ const msgEl = document.getElementById('rmMsg');
1282
+ const confirmBtn = document.getElementById('rmConfirmBtn');
1283
+ msgEl.style.color = '#aaa';
1284
+ msgEl.textContent = '⏳ Laden...';
1285
+ confirmBtn.disabled = true;
1286
+ sendTo('restoreScript', { path: s.path, name: s.name, type: s.type, source: s.source, suffix }, function(result) {
1287
+ confirmBtn.disabled = false;
1288
+ if (result && result.error) {
1289
+ msgEl.style.color = '#dc3545';
1290
+ msgEl.textContent = '✗ ' + result.error;
1291
+ } else if (result && result.success) {
1292
+ msgEl.style.color = '#198754';
1293
+ msgEl.textContent = '✓ Geladen!';
1294
+ setTimeout(() => document.getElementById('restoreModalOverlay').classList.remove('open'), 1200);
1295
+ } else {
1296
+ msgEl.style.color = '#dc3545';
1297
+ msgEl.textContent = '✗ Unbekannter Fehler';
1298
+ }
1299
+ });
1300
+ }
1147
1301
  </script>
1148
1302
  </body>
1149
1303
  </html>