From: Moritz Warning Date: Tue, 16 Jun 2020 20:02:05 +0000 (+0200) Subject: move web content to www folder X-Git-Tag: v2.2.1~3 X-Git-Url: http://git.openwrt.org/?a=commitdiff_plain;h=3b1cae8d238031087e7a2d545c45dc6f2077ac9a;p=web%2Ffirmware-selector-openwrt-org.git move web content to www folder This makes a better separation of actual content and meta data (readme, license, etc.) much better. --- diff --git a/README.md b/README.md index 48224a9..b071fd6 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,18 @@ # Yet Another Firmware Selector A simple OpenWrt firmware selector using autocompletion. Uses plain -HTML/CSS/JavaScript. Checkout the [Demo](https://mwarning.github.io/yet_another_firmware_selector/). +HTML/CSS/JavaScript. Checkout the [Demo](https://mwarning.github.io/yet-another-firmware-selector/www/). ![image](misc/screenshot.png) ## Run -* Download repository and change directory +* Checkput the repository and change to the project directory * Start webserver (e.g. `python3 -m http.server`) -* Go to `http://localhost:8000` in your web browser +* Go to `http://localhost:8000/www/` in your web browser -Configure with [config.js](config.js). +Configure with [config.js](www/config.js). ## Attended Sysupgrade Support diff --git a/config.js b/config.js deleted file mode 100644 index 6048dd6..0000000 --- a/config.js +++ /dev/null @@ -1,15 +0,0 @@ -var config = { - // Default language, see i18n.js - language: 'en', - // Show help text for images - showHelp: true, - // Image overview file or path to the ASU API - versions: { - 'SNAPSHOT': 'misc/snapshot/overview.json', - '19.07.1': 'misc/19.07.1/overview.json', - '18.06.7': 'misc/18.06.7/overview.json' - }, - // Build custom images - // See https://github.com/aparcar/asu - //asu_url: 'https://chef.libremesh.org' -}; diff --git a/i18n.js b/i18n.js deleted file mode 100644 index 56333bc..0000000 --- a/i18n.js +++ /dev/null @@ -1,240 +0,0 @@ - -var translations = { - 'ca': { - 'tr-load': 'Descarregueu el microprogramari OpenWrt per al vostre dispositiu!', - 'tr-title': 'Selector de microprogramari OpenWrt', - 'tr-message': 'Feu servir el formulari de sota per seleccionar i descarregar el microprogramari per al vostre dispositiu!', - 'tr-version-build': 'Compilació', - 'tr-custom-build': 'Compilació personalitzada', - 'tr-customize': 'Personalitzar', - 'tr-request-build': 'Demanar la compilació', - 'tr-model': 'Model:', - 'tr-target': 'Plataforma:', - 'tr-version': 'Versió:', - 'tr-date': 'Data:', - 'tr-downloads': 'Descàrregues', - 'tr-custom-downloads': 'Descàrregues personalitzades', - 'tr-factory-help': 'Les imatges Factory són per instal·lar OpenWrt als dispositius per primera vegada. Usualment, això es fa a través de la interfície web del microprogramari original.', - 'tr-sysupgrade-help': 'Les imatges Sysupgrade són per instal·lar-les als dispositius que ja tenen OpenWrt. La imatge es pot instal·lar a través de la interfície web o del terminal.', - 'tr-kernel-help': 'El nucli de Linux en una imatge separada.', - 'tr-rootfs-help': 'El sistema de fitxers arrel en una imatge separada.', - 'tr-sdcard-help': 'Una imatge feta per escriure-la a una targeta SD.', - 'tr-tftp-help': 'Les imatges TFTP images es fan servir per instal·lar-les a un dispositiu mitjançant el mètode TFTP del carregador d\'arrencada.', - 'tr-other-help': 'Un altre tipus d\'imatge.', - 'tr-build-successful': 'La compilació ha tingut èxit', - 'tr-build-failed': 'La compilació ha fallat', - 'tr-request-image': 'Demanar la imatge', - 'tr-check-again': 'Proveu de nou d\'aquí 5 segons...' - }, - 'en': { - 'tr-load': 'Download OpenWrt firmware for your device!', - 'tr-title': 'OpenWrt Firmware Selector', - 'tr-message': 'Please use the input below to download firmware for your device!', - 'tr-version-build': 'Build', - 'tr-custom-build': 'Custom Build', - 'tr-customize': 'Customize', - 'tr-request-build': 'Request Build', - 'tr-model': 'Model:', - 'tr-target': 'Platform:', - 'tr-version': 'Version:', - 'tr-date': 'Date:', - 'tr-downloads': 'Downloads', - 'tr-custom-downloads': 'Custom Downloads', - 'tr-factory-help': 'Factory images are for flashing routers with OpenWrt for the first time. Usually via the web interface of the original firmware.', - 'tr-sysupgrade-help': 'Sysupgrade images are for flashing routers that already run OpenWrt. The image can be applied using the web interface or the terminal.', - 'tr-kernel-help': 'Linux kernel as a separate image.', - 'tr-rootfs-help': 'Root file system as a separate image.', - 'tr-sdcard-help': 'Image that is meant to be flashed onto a SD-Card.', - 'tr-tftp-help': 'TFTP images are used to flash a device via the TFTP method of the bootloader.', - 'tr-other-help': 'Other image type.', - 'tr-build-successful': 'Build successful', - 'tr-build-failed': 'Build failed', - 'tr-request-image': 'Request image', - 'tr-check-again': 'Check again in 5 seconds...' - }, - 'es': { - 'tr-load': 'Descargue el firmware OpenWrt para su dispositivo!', - 'tr-title': 'Selector de firmware OpenWrt', - 'tr-message': 'Utilice la entrada a continuación para descargar el firmware de su dispositivo!', - 'tr-version-build': 'Compilar', - 'tr-custom-build': 'Compilación personalizada', - 'tr-customize': 'Personalizar', - 'tr-request-build': 'Solicitar compilación', - 'tr-model': 'Modelo:', - 'tr-target': 'Plataforma:', - 'tr-version': 'Versión:', - 'tr-date': 'Fecha:', - 'tr-downloads': 'Descargas', - 'tr-custom-downloads': 'Descargas personalizadas', - 'tr-factory-help': 'Las imágenes de fábrica son para enrutadores intermitentes con OpenWrt por primera vez. Generalmente a través de la interfaz web del firmware original.', - 'tr-sysupgrade-help': 'Las imágenes de Sysupgrade son para enrutadores intermitentes que ya ejecutan OpenWrt. La imagen se puede aplicar utilizando la interfaz web o el terminal.', - 'tr-kernel-help': 'Kernel de Linux como una imagen separada.', - 'tr-rootfs-help': 'Sistema de archivos raíz como una imagen separada.', - 'tr-sdcard-help': 'Imagen que debe ser mostrada en una tarjeta SD.', - 'tr-tftp-help': 'Las imágenes TFTP se utilizan para flashear un dispositivo mediante el método TFTP del gestor de arranque.', - 'tr-other-help': 'Otro tipo de imagen.', - 'tr-build-successful': 'Compilación exitosa', - 'tr-build-failed': 'Compilación fallida', - 'tr-request-image': 'Solicitar imagen', - 'tr-check-again': 'Verifique nuevamente en 5 segundos...' - }, - 'no': { - 'tr-load': 'Last ned OpenWrt fastvare for din enhet!', - 'tr-title': 'OpenWrt fastvare utvelger', - 'tr-message': 'Bruk feltene nedenfor for å laste ned fastvare til enheten din!', - 'tr-version-build': 'Sammensetning', - 'tr-custom-build': 'Tilpasset sammensetning', - 'tr-customize': 'Tilpasse', - 'tr-request-build': 'Be om sammensetning', - 'tr-model': 'Modell:', - 'tr-target': 'Platform:', - 'tr-version': 'Versjon:', - 'tr-date': 'Dato:', - 'tr-downloads': 'Nedlastninger', - 'tr-custom-downloads': 'Tilpassede nedlastninger', - 'tr-factory-help': 'Factory avbildningen er for å laste rutere med OpenWrt første gang. Vanligvis via webgrensesnittet til den originale fastvaren.', - 'tr-sysupgrade-help': 'Sysupgrade avbildningen er for rutere som allerede benytter OpenWrt. Avbildningen innstaleres gjennom webgrensesnittet eller terminalen.', - 'tr-kernel-help': 'Linux kjernen som en egen avbildning.', - 'tr-rootfs-help': 'Rotfilsystem som en egen avbildning.', - 'tr-sdcard-help': 'Avbildning som er ment for et SD-kort.', - 'tr-tftp-help': 'TFTP avbildninger er for å laste enheter via TFTP metoden i oppstartsprosedyren.', - 'tr-other-help': 'Andre avbildningstyper.', - 'tr-build-successful': 'Vellykket sammensetning', - 'tr-build-failed': 'Sammensetningen feilet', - 'tr-request-image': 'Be om avbildning', - 'tr-check-again': 'Sjekk pånytt om 5 sekunder...' - }, - 'de': { - 'tr-load': 'Lade die OpenWrt Firmware für dein Gerät!', - 'tr-title': 'OpenWrt Firmware Selector', - 'tr-message': 'Bitte benutze die Eingabe um die passende Firmware zu finden!', - 'tr-version-build': 'Release Build', - 'tr-custom-build': 'Custom Build', - 'tr-customize': 'Customize', - 'tr-request-build': 'Request Build', - 'tr-model': 'Model:', - 'tr-target': 'Target', - 'tr-version': 'Version:', - 'tr-date': 'Datum:', - 'tr-downloads': 'Downloads', - 'tr-custom-downloads': 'Custom Downloads', - 'tr-factory-help': 'Factory Abbilder werden über die Weboberfläche der originalen Firmware eingespielt.', - 'tr-sysupgrade-help': 'Sysupgrade Abbilder werden für Geräte verwendet, die bereits OpenWrt laufen haben. Es ist möglich, existierende Einstellungen beizubehalten.', - 'tr-kernel-help': 'Linux Kernel als separates Abbild.', - 'tr-rootfs-help': 'Das Root Dateisystem als separates Abbild.', - 'tr-sdcard-help': 'Image für SD Speicherkarten.', - 'tr-tftp-help': 'TFTP Dateien können verwendet werden, um ein Gerät über die TFTP Method des Bootloader zu flashen.', - 'tr-other-help': 'Sonstiger Imagetyp.', - 'tr-build-successful': 'Build erfolgreich', - 'tr-build-failed': 'Build fehlgeschlagen', - 'tr-request-image': 'Frage nach image', - 'tr-check-again': 'Nochmal nachfragen in 5 Sekunden...' - }, - 'fr': { - 'tr-load': 'Télécharger le firmware OpenWrt de votre périphérique !', - 'tr-title': 'Sélecteur de Firmware', - 'tr-message': 'Utiliser les entrées ci-dessous pour télécharger le firmware de votre périphérique !', - 'tr-version-build': 'Build', - 'tr-custom-build': 'Build Personnalisé', - 'tr-customize': 'Personnalisation', - 'tr-request-build': 'Requête de Build', - 'tr-model': 'Modèle:', - 'tr-target': 'Platform:', - 'tr-version': 'Version:', - 'tr-date': 'Date:', - 'tr-downloads': 'Téléchargements', - 'tr-custom-downloads': 'Téléchargements Personnalusés', - 'tr-factory-help': 'Les images Factory sont prévues pour flasher les routers avec OpenWrt pour la première fois. Habituellement à partir de l\'interface web du firmware d\'origine.', - 'tr-sysupgrade-help': 'Les images Sysupgrade sont prévues pour flasher les routers fonctionnant déjà avec OpenWrt. L\'image peut être installée à travers l\'interface web ou par le terminal.', - 'tr-kernel-help': 'Linux kernel comme image séparée.', - 'tr-rootfs-help': 'Root file system comme image séparée.', - 'tr-sdcard-help': 'Image prévue pour être flashée sur une carte SD.', - 'tr-tftp-help': 'TFTP images prévues pour flasher le périphérique via le démarrage par méthode TFTP.', - 'tr-other-help': 'Autre type d\'image.', - 'tr-build-successful': 'Succès du Build', - 'tr-build-failed': 'Échec du Build', - 'tr-request-image': 'Demade d\'image', - 'tr-check-again': 'Essayer à nouveau dans 5 secondes...' - }, - 'it': { - 'tr-load': 'Scarica il firmware OpenWrt per il tuo dispositivo!', - 'tr-title': 'OpenWrt Firmware Selector', - 'tr-message': 'Usa la casella sottostante per scaricare il firmware per il tuo dispositivo!', - 'tr-version-build': 'Build', - 'tr-custom-build': 'Custom Build', - 'tr-customize': 'Personalizza', - 'tr-request-build': 'Richiedi Build', - 'tr-model': 'Modell:', - 'tr-target': 'Platform:', - 'tr-version': 'Version:', - 'tr-date': 'Data:', - 'tr-downloads': 'Downloads', - 'tr-custom-downloads': 'Download Personalizzati', - 'tr-factory-help': 'Factory Image sono usate per installare OpenWrt su router per la prima volta. Di solito l\'immagine può essere applicata via l\'interfaccia web del firmware originale.', - 'tr-sysupgrade-help': 'Sysupgrade Image sono usate per flashare router in cui OpenWrt è già installato. L\'immagine può essere applicata via interfaccia web o terminale.', - 'tr-kernel-help': 'Linux kernel come immagine separata.', - 'tr-rootfs-help': 'Root file system come immagine separata.', - 'tr-sdcard-help': 'Immagine da flashare su scheda SD-Card separata.', - 'tr-tftp-help': 'Immagini TFTP images sono usate per flashare un dispositivo con il metodo TFTP del bootloader.', - 'tr-other-help': 'Other image type.', - 'tr-build-successful': 'Build compilata con successo', - 'tr-build-failed': 'Build fallita', - 'tr-request-image': 'Richiedi immagine', - 'tr-check-again': 'Prova di nuovo in 5 secondi...' - }, - 'pl': { - 'tr-load': 'Pobieranie oprogramowania OpenWrt!', - 'tr-title': 'OpenWrt Firmware Selector', - 'tr-message': 'Użyj pola poniżej żeby znaleźć obraz dla swojego urządzenia!', - 'tr-version-build': 'Informacje o obrazie', - 'tr-custom-build': 'Informacje o zmodyfikowanym obrazie', - 'tr-customize': 'Modyfikacja', - 'tr-request-build': 'Żądanie budowy obrazu', - 'tr-model': 'Model:', - 'tr-target': 'Platforma:', - 'tr-version': 'Wersja:', - 'tr-date': 'Data:', - 'tr-downloads': 'Obrazy do pobrania', - 'tr-custom-downloads': 'Zmodyfikowane obrazy do pobrania', - 'tr-factory-help': 'Obraz factory używany jest do pierwszej instalacji OpenWrt. Zwykle można go użyć wykorzystując interfejs graficzny oryginalnego oprogramowania.', - 'tr-sysupgrade-help': 'Obraz sysuprade używany jest do aktualizacji routerów z zainstalowanym już OpenWrt. Obraz można użyć przez GUI lub konsolę.', - 'tr-kernel-help': 'Osobny obraz z kernelem linuksowym.', - 'tr-rootfs-help': 'Osobny obraz z system plików.', - 'tr-sdcard-help': 'Obraz do wgrania na kartę SD.', - 'tr-tftp-help': 'Obraz TFTP służący do aktualizacji urządzenia z wykorzystaniem TFTP i bootloadera.', - 'tr-other-help': 'Inny typ obrazu.', - 'tr-build-successful': 'Budowanie zakończone pomyślnie', - 'tr-build-failed': 'Błąd budowania', - 'tr-request-image': 'Żądanie obrazu', - 'tr-check-again': 'Sprawdź ponownie za 5 sekund...' - }, - 'tr': { - 'tr-load': 'Cihazınız için OpenWrt yazılımını indirin!', - 'tr-title': 'OpenWrt Yazılım Seçicisi', - 'tr-message': 'Cihazınız için yazılımı indirmek için lütfen aşağıdaki girişi kullanın!', - 'tr-version-build': 'Sürüm', - 'tr-custom-build': 'Özel Sürüm', - 'tr-customize': 'Özelleştir', - 'tr-request-build': 'Sürüm Oluştur', - 'tr-model': 'Model:', - 'tr-target': 'Platform:', - 'tr-version': 'Versiyon:', - 'tr-date': 'Tarih:', - 'tr-downloads': 'İndirmeler', - 'tr-custom-downloads': 'Özel İndirmeler', - 'tr-factory-help': 'Fabrika imajları, ilk kez OpenWrt yüklenen cihazlar içindir. Genellikle orijinal ürün yazılımının web arayüzü üzerinden yüklenir.', - 'tr-sysupgrade-help': 'Sysupgrade imajları, zaten OpenWrt kurulu cihazlar içindir. İmaj, web arayüzü veya terminal kullanılarak yüklenebilir.', - 'tr-kernel-help': 'Linux kernel ayrı bir imaj olarak.', - 'tr-rootfs-help': 'Kök Dosya Sistemi ayrı bir imaj olarak.', - 'tr-sdcard-help': 'SD-Kart \'a kurulması planlanan imaj', - 'tr-tftp-help': 'TFTP imajları, Bootloader \'ın TFTP yöntemi ile bir cihaza kurulması için kullanılır.', - 'tr-other-help': 'Diğer imaj türü.', - 'tr-build-successful': 'Oluşturma başarılı', - 'tr-build-failed': 'Oluşturma başarısız', - 'tr-request-image': 'Imaj oluştur', - 'tr-check-again': '5 saniye icinde tekrar dene...' - } -}; - -// Complement translations based on other translations -//translations['en'] = Object.assign({}, translations['de'], translations['en']); diff --git a/index.css b/index.css deleted file mode 100644 index e0e1885..0000000 --- a/index.css +++ /dev/null @@ -1,231 +0,0 @@ - -body { - font-family: "Arial", sans-serif; - margin: 0px; -} - -#buildstatus a { - color: inherit; -} - -#models-autocomplete { - width: 20em; - display: inline-block; -} - -.autocomplete { - position: relative; -} - -.autocomplete > input { - border: 1px solid transparent; - background-color: #f1f1f1; - padding: 10px; - width: 100%; - border-radius: 4px; -} - -.autocomplete-items { - position: absolute; - border: 1px solid #d4d4d4; - border-bottom: none; - border-top: none; - z-index: 99; - /*position the autocomplete items to be the same width as the container:*/ - top: 100%; - left: 0; - right: 0; -} - -.autocomplete-items div { - padding: 10px; - cursor: pointer; - background-color: #fff; - border-bottom: 1px solid #d4d4d4; -} - -/*when hovering an item:*/ -.autocomplete-items div:hover { - background-color: #e9e9e9; -} - -/*when navigating through the items using the arrow keys:*/ -.autocomplete-active { - background-color: DodgerBlue !important; - color: #ffffff; -} - -header { - font-weight: 500; - width: 100%; - z-index: 1100; - box-shadow: 0px 2px 4px -1px rgba(0,0,0,0.2),0px 4px 5px 0px rgba(0,0,0,0.14),0px 1px 10px 0px rgba(0,0,0,0.12); - background-color: #00A3E1; -} - -h6 { - margin: 0; - font-size: 1.25rem; - font-weight: 500; - line-height: 1.6; - letter-spacing: 0.0075em; -} - -header > div { - padding-left: 24px; - padding-right: 24px; - min-height: 64px; - - display: flex; - position: relative; - align-items: center; - color: #fff; -} - -.container { - max-width: 1280px; - padding-left: 32px; - padding-right: 32px; - width: 100%; - box-sizing: border-box; - margin-top: 30px; - margin-right: auto; - margin-left: auto; - margin-bottom: 100px; -} - -.container > div { - padding: 10px 20px; - text-align: left; - box-shadow: 0px 1px 3px 0px rgba(0,0,0,0.2),0px 1px 1px 0px rgba(0,0,0,0.14),0px 2px 1px -1px rgba(0,0,0,0.12); - border-radius: 4px; - color: rgba(0, 0, 0, 0.87); - transition: box-shadow 300ms cubic-bezier(0.4, 0, 0.2, 1) 0ms; - background-color: #fff; -} - -#versions { - border: 1px solid transparent; - background-color: #f1f1f1; - padding: 10px; - width: 10em; - border-radius: 4px; -} - -#language-selection { - color: #fff; - background-color: #1084b2; - box-shadow: 0px 1px 5px 0px rgba(0,0,0,0.2),0px 2px 2px 0px rgba(0,0,0,0.14),0px 3px 1px -2px - rgba(0,0,0,0.12); - padding: 6px 16px; - border-radius: 4px; - border: 0; - - /* hide arrow */ - -webkit-appearance: none; - -moz-appearance: none; - text-indent: 1px; - text-overflow: ''; -} - -.download-link { - text-decoration: none; - border-radius: 4px; - padding: 12px 16px; - margin: 5px; - font-size: 16px; - cursor: pointer; - letter-spacing: 0.05em; - display: inline-flex; - align-items: center; - box-shadow: 0px 1px 5px 0px rgba(0,0,0,0.2),0px 2px 2px 0px rgba(0,0,0,0.14),0px 3px 1px -2px rgba(0,0,0,0.12); - color: #fff; - background-color: #00A3E1; -} - -.download-link:hover { - background-color: #038fc6 -} - -.download-link :first-child { - width: 30px; - margin-right: 15px; - margin-top: -2px; - content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.64 5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96zM17 13l-5 5-5-5h3V9h4v4h3z' fill='%23fff'%3E%3C/path%3E%3Cpath d='M0 0h24v24H0z' fill='none'/%3E%3C/svg%3E"); -} - -#images .column { - width: 5em; - display: inline-block; - line-height: 1.5; -} - -#images { - display: none; -} - -#images > div { - padding-top: 20px; -} - -#image-model { - font-weight: bold; -} - -#custom { - display: none; -} - -#custom textarea { - width: 500px; - height: 120px; - font-size: 16px; - display: block; -} - -#custom a :first-child { - width: 30px; - margin-right: 10px; - margin-top: 0px; - font-size: 36px; -} - -#custom a { - text-decoration: none; - border-radius: 4px; - padding: 2px 10px; - margin: 5px; - font-size: 16px; - cursor: pointer; - letter-spacing: 0.05em; - display: inline-flex; - align-items: center; - box-shadow: 0px 1px 5px 0px rgba(0,0,0,0.2),0px 2px 2px 0px rgba(0,0,0,0.14),0px 3px 1px -2px rgba(0,0,0,0.12); - color: #fff; - background-color: #00A3E1; -} - -.download-help { - display: none; -} - -#buildspinner { - float: left; - height: 40px; - padding-right: 12px; - display: none; -} - -#buildstatus { - padding: 10px 0; - display: none; -} - -#footer { - font-size: 0.8em; - text-align: right; -} - -#footer a { - text-decoration: none; -} diff --git a/index.html b/index.html deleted file mode 100644 index 2260f81..0000000 --- a/index.html +++ /dev/null @@ -1,96 +0,0 @@ - - - - - - OpenWrt Firmware Selector - - - - - - - -
-
- - Logo -
- - -
-
- -
-
-

Download OpenWrt firmware for your device!

-

Please use the input below to download firmware for your device!

-
- - -
- -
- -
-
- -
- Logo -
-
- -
-
-

Customize

-
- -
- - Request Build - -
- -
-

Release Build

-
Model:
-
Target:
-
Version: ()
-
Date:
-
- - - -
- Factory images are for flashing routers with OpenWrt for the first time using the web interface of the original firmware. - Sysupgrade images are for flashing routers that already run OpenWrt. The image can be applied using the web interface or the console. - Linux kernel as a separate image. - Root file system as a separate image. - Image that is meant to be flashed on an SD-Card. - Image that can be applied using the TFTP meachnism of the bootloader - Image of unknown purpose. -
-
- - -
-
- - - diff --git a/index.js b/index.js deleted file mode 100644 index 7562da4..0000000 --- a/index.js +++ /dev/null @@ -1,451 +0,0 @@ - -var current_model = {}; - -function $(id) { - return document.getElementById(id); -} - -function show(id) { - $(id).style.display = 'block'; -} - -function hide(id) { - $(id).style.display = 'none'; -} - -function split(str) { - return str.match(/[^\s,]+/g) || []; -} - -function get_model_titles(titles) { - return titles.map(e => { - if (e.title) { - return e.title; - } else { - return ((e.vendor || '') + ' ' + (e.model || '') + ' ' + (e.variant || '')).trim(); - } - }).join(' / '); -} - -function build_asu_request() { - if (!current_model || !current_model.id) { - alert('bad profile'); - return; - } - - function showStatus(message, url) { - show('buildstatus'); - var tr = message.startsWith('tr-') ? message : ''; - if (url) { - $('buildstatus').innerHTML = '' + message + ''; - } else { - $('buildstatus').innerHTML = ''; - } - translate(); - } - - // hide image view - updateImages(); - - show('buildspinner'); - showStatus('tr-request-image'); - - var request_data = { - 'target': current_model.target, - 'profile': current_model.id, - 'packages': split($('packages').value), - 'version': $('versions').value - } - - fetch(config.asu_url + '/api/build', { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify(request_data) - }) - .then(response => { - switch (response.status) { - case 200: - hide('buildspinner'); - showStatus('tr-build-successful'); - - response.json() - .then(mobj => { - var download_url = config.asu_url + '/store/' + mobj.bin_dir; - showStatus('tr-build-successful', download_url + '/buildlog.txt'); - updateImages( - mobj.version_number, - mobj.version_code, - mobj.build_at, - get_model_titles(mobj.titles), - download_url, mobj, true - ); - }); - break; - case 202: - showStatus('tr-check-again'); - setTimeout(_ => { build_asu_request() }, 5000); - break; - case 400: // bad request - case 422: // bad package - case 500: // build failed - hide('buildspinner'); - response.json() - .then(mobj => { - var message = mobj['message'] || 'tr-build-failed'; - var url = mobj.buildlog ? (config.asu_url + '/store/' + mobj.bin_dir + '/buildlog.txt') : undefined; - showStatus(message, url); - }) - break; - } - }) - .catch(err => { - hide('buildspinner'); - showStatus(err); - }) -} - -function setupSelectList(select, items, onselection) { - for (var i = 0; i < items.length; i += 1) { - var option = document.createElement('OPTION'); - option.innerHTML = items[i]; - select.appendChild(option); - } - - select.addEventListener('change', e => { - onselection(items[select.selectedIndex]); - }); - - if (select.selectedIndex >= 0) { - onselection(items[select.selectedIndex]); - } -} - -// Change the translation of the entire document -function translate() { - var mapping = translations[config.language]; - for (var tr in mapping) { - Array.from(document.getElementsByClassName(tr)) - .forEach(e => { e.innerText = mapping[tr]; }) - } -} - -function setupAutocompleteList(input, items, as_list, onbegin, onend) { - var currentFocus = -1; - - // sort numbers and other characters separately - var collator = new Intl.Collator(undefined, {numeric: true, sensitivity: 'base'}); - - items.sort(collator.compare); - - input.oninput = function(e) { - onbegin(); - - var offset = 0; - var value = this.value; - var value_list = []; - - if (as_list) { - // automcomplete last text item - offset = this.value.lastIndexOf(' ') + 1; - value = this.value.substr(offset); - value_list = split(this.value.substr(0, offset)); - } - - // close any already open lists of autocompleted values - closeAllLists(); - - if (!value) { - return false; - } - - // create a DIV element that will contain the items (values): - var list = document.createElement('DIV'); - list.setAttribute('id', this.id + '-autocomplete-list'); - list.setAttribute('class', 'autocomplete-items'); - // append the DIV element as a child of the autocomplete container: - this.parentNode.appendChild(list); - - var c = 0; - for (var i = 0; i < items.length; i += 1) { - var item = items[i]; - - // match - var j = item.toUpperCase().indexOf(value.toUpperCase()); - if (j < 0) { - continue; - } - - // do not offer a duplicate item - if (as_list && value_list.indexOf(item) != -1) { - continue; - } - - c += 1; - if (c >= 15) { - var div = document.createElement('DIV'); - div.innerHTML = '...'; - list.appendChild(div); - break; - } else { - var div = document.createElement('DIV'); - // make the matching letters bold: - div.innerHTML = item.substr(0, j) - + '' + item.substr(j, value.length) + '' - + item.substr(j + value.length) - + ''; - - div.addEventListener('click', function(e) { - // include selected value - var selected = this.getElementsByTagName('input')[0].value; - if (as_list) { - input.value = value_list.join(' ') + ' ' + selected; - } else { - input.value = selected; - } - // close the list of autocompleted values, - closeAllLists(); - onend(input); - }); - - list.appendChild(div); - } - } - }; - - input.onkeydown = function(e) { - var x = document.getElementById(this.id + '-autocomplete-list'); - if (x) x = x.getElementsByTagName('div'); - if (e.keyCode == 40) { - // key down - currentFocus += 1; - // and and make the current item more visible: - setActive(x); - } else if (e.keyCode == 38) { - // key up - currentFocus -= 1; - // and and make the current item more visible: - setActive(x); - } else if (e.keyCode == 13) { - // If the ENTER key is pressed, prevent the form from being submitted, - e.preventDefault(); - if (currentFocus > -1) { - // and simulate a click on the 'active' item: - if (x) x[currentFocus].click(); - } - } - }; - - input.onfocus = function() { - onend(input); - } - - // focus lost - input.onblur = function() { - onend(input); - } - - function setActive(x) { - // a function to classify an item as 'active': - if (!x) return false; - // start by removing the 'active' class on all items: - for (var i = 0; i < x.length; i++) { - x[i].classList.remove('autocomplete-active'); - } - if (currentFocus >= x.length) currentFocus = 0; - if (currentFocus < 0) currentFocus = (x.length - 1); - // add class 'autocomplete-active': - x[currentFocus].classList.add('autocomplete-active'); - } - - function closeAllLists(elmnt) { - // close all autocomplete lists in the document, - // except the one passed as an argument: - var x = document.getElementsByClassName('autocomplete-items'); - for (var i = 0; i < x.length; i++) { - if (elmnt != x[i] && elmnt != input) { - x[i].parentNode.removeChild(x[i]); - } - } - } - - // execute a function when someone clicks in the document: - document.addEventListener('click', e => { - closeAllLists(e.target); - }); -} - -// for attended sysupgrade -function updatePackageList(version, target) { - // set available packages - fetch(config.asu_url + '/' + config.versions[version] + '/' + target + '/index.json') - .then(response => response.json()) - .then(all_packages => { - setupAutocompleteList($('packages'), all_packages, true, _ => {}, textarea => { - textarea.value = split(textarea.value) - // make list unique, ignore minus - .filter((value, index, self) => { - var i = self.indexOf(value.replace(/^\-/, '')); - return (i === index) || (i < 0); - }) - // limit to available packages, ignore minus - .filter((value, index) => all_packages.indexOf(value.replace(/^\-/, '')) !== -1) - .join(' '); - }); - }); -} - -function updateImages(version, code, date, model, url, mobj, is_custom) { - // add download button for image - function addLink(type, file) { - var a = document.createElement('A'); - a.classList.add('download-link'); - a.href = url - .replace('{target}', mobj.target) - .replace('{version}', version) - + '/' + file; - var span = document.createElement('SPAN'); - span.appendChild(document.createTextNode('')); - a.appendChild(span); - a.appendChild(document.createTextNode(type.toUpperCase())); - - if (config.showHelp) { - a.onmouseover = function() { - // hide all help texts - Array.from(document.getElementsByClassName('download-help')) - .forEach(e => e.style.display = 'none'); - var lc = type.toLowerCase(); - if (lc.includes('sysupgrade')) { - show('sysupgrade-help'); - } else if (lc.includes('factory') || lc == 'trx' || lc == 'chk') { - show('factory-help'); - } else if (lc.includes('kernel') || lc.includes('zimage') || lc.includes('uimage')) { - show('kernel-help'); - } else if (lc.includes('root')) { - show('rootfs-help'); - } else if (lc.includes('sdcard')) { - show('sdcard-help'); - } else if (lc.includes('tftp')) { - show('tftp-help'); - } else { - show('other-help'); - } - }; - } - - $('download-links').appendChild(a); - } - - function switchClass(id, from_class, to_class) { - $(id).classList.remove(from_class); - $(id).classList.add(to_class); - } - - // remove all download links - Array.from(document.getElementsByClassName('download-link')) - .forEach(e => e.remove()); - - // hide all help texts - Array.from(document.getElementsByClassName('download-help')) - .forEach(e => e.style.display = 'none'); - - if (version && code && date && model && url && mobj) { - var target = mobj.target; - var images = mobj.images; - - // change between "version" and "custom" title - if (is_custom) { - switchClass('images-title', 'tr-version-build', 'tr-custom-build'); - switchClass('downloads-title', 'tr-version-downloads', 'tr-custom-downloads'); - } else { - switchClass('images-title', 'tr-custom-build', 'tr-version-build'); - switchClass('downloads-title', 'tr-custom-downloads', 'tr-version-downloads'); - } - // update title translation - translate(); - - // fill out build info - $('image-model').innerText = model; - $('image-target').innerText = target; - $('image-version').innerText = version; - $('image-code').innerText = code; - $('image-date').innerText = date; - - images.sort((a, b) => a.name.localeCompare(b.name)); - - for (var i in images) { - addLink(images[i].type, images[i].name); - } - - if (config.asu_url) { - updatePackageList(version, target); - } - - show('images'); - } else { - hide('images'); - } -} - -function init() { - var build_date = "unknown" - setupSelectList($('versions'), Object.keys(config.versions), version => { - var url = config.versions[version]; - if (config.asu_url) { - url = config.asu_url + '/' + url + '/profiles.json'; - } - fetch(url) - .then(obj => { - build_date = obj.headers.get('last-modified'); - return obj.json(); - }) - .then(obj => { - // handle native openwrt json format - if ('profiles' in obj) { - obj['models'] = {} - for (const [key, value] of Object.entries(obj['profiles'])) { - obj['models'][get_model_titles(value.titles)] = value - obj['models'][get_model_titles(value.titles)]['id'] = key - } - } - return obj - }) - .then(obj => { - setupAutocompleteList($('models'), Object.keys(obj['models']), false, updateImages, models => { - var model = models.value; - if (model in obj['models']) { - var url = obj.url || 'unknown'; - var code = obj.version_code || 'unknown'; - var mobj = obj['models'][model]; - updateImages(version, code, build_date, model, url, mobj, false); - current_model = mobj; - } else { - updateImages(); - current_model = {}; - } - }); - - // trigger model update when selected version changes - $('models').onfocus(); - }); - }); - - if (config.asu_url) { - show('custom'); - } - - // hide fields - updateImages(); - - var user_lang = (navigator.language || navigator.userLanguage).split('-')[0]; - if (user_lang in translations) { - config.language = user_lang; - $('language-selection').value = user_lang; - } - - translate(); - - $('language-selection').onclick = function() { - config.language = this.children[this.selectedIndex].value; - translate(); - } -} diff --git a/logo.png b/logo.png deleted file mode 100644 index 8500f9b..0000000 Binary files a/logo.png and /dev/null differ diff --git a/spinner.gif b/spinner.gif deleted file mode 100644 index 7154314..0000000 Binary files a/spinner.gif and /dev/null differ diff --git a/www/config.js b/www/config.js new file mode 100644 index 0000000..78adfb0 --- /dev/null +++ b/www/config.js @@ -0,0 +1,15 @@ +var config = { + // Default language, see i18n.js + language: 'en', + // Show help text for images + showHelp: true, + // Image overview file or path to the ASU API + versions: { + 'SNAPSHOT': '../misc/snapshot/overview.json', + '19.07.1': '../misc/19.07.1/overview.json', + '18.06.7': '../misc/18.06.7/overview.json' + }, + // Build custom images + // See https://github.com/aparcar/asu + //asu_url: 'https://chef.libremesh.org' +}; diff --git a/www/i18n.js b/www/i18n.js new file mode 100644 index 0000000..56333bc --- /dev/null +++ b/www/i18n.js @@ -0,0 +1,240 @@ + +var translations = { + 'ca': { + 'tr-load': 'Descarregueu el microprogramari OpenWrt per al vostre dispositiu!', + 'tr-title': 'Selector de microprogramari OpenWrt', + 'tr-message': 'Feu servir el formulari de sota per seleccionar i descarregar el microprogramari per al vostre dispositiu!', + 'tr-version-build': 'Compilació', + 'tr-custom-build': 'Compilació personalitzada', + 'tr-customize': 'Personalitzar', + 'tr-request-build': 'Demanar la compilació', + 'tr-model': 'Model:', + 'tr-target': 'Plataforma:', + 'tr-version': 'Versió:', + 'tr-date': 'Data:', + 'tr-downloads': 'Descàrregues', + 'tr-custom-downloads': 'Descàrregues personalitzades', + 'tr-factory-help': 'Les imatges Factory són per instal·lar OpenWrt als dispositius per primera vegada. Usualment, això es fa a través de la interfície web del microprogramari original.', + 'tr-sysupgrade-help': 'Les imatges Sysupgrade són per instal·lar-les als dispositius que ja tenen OpenWrt. La imatge es pot instal·lar a través de la interfície web o del terminal.', + 'tr-kernel-help': 'El nucli de Linux en una imatge separada.', + 'tr-rootfs-help': 'El sistema de fitxers arrel en una imatge separada.', + 'tr-sdcard-help': 'Una imatge feta per escriure-la a una targeta SD.', + 'tr-tftp-help': 'Les imatges TFTP images es fan servir per instal·lar-les a un dispositiu mitjançant el mètode TFTP del carregador d\'arrencada.', + 'tr-other-help': 'Un altre tipus d\'imatge.', + 'tr-build-successful': 'La compilació ha tingut èxit', + 'tr-build-failed': 'La compilació ha fallat', + 'tr-request-image': 'Demanar la imatge', + 'tr-check-again': 'Proveu de nou d\'aquí 5 segons...' + }, + 'en': { + 'tr-load': 'Download OpenWrt firmware for your device!', + 'tr-title': 'OpenWrt Firmware Selector', + 'tr-message': 'Please use the input below to download firmware for your device!', + 'tr-version-build': 'Build', + 'tr-custom-build': 'Custom Build', + 'tr-customize': 'Customize', + 'tr-request-build': 'Request Build', + 'tr-model': 'Model:', + 'tr-target': 'Platform:', + 'tr-version': 'Version:', + 'tr-date': 'Date:', + 'tr-downloads': 'Downloads', + 'tr-custom-downloads': 'Custom Downloads', + 'tr-factory-help': 'Factory images are for flashing routers with OpenWrt for the first time. Usually via the web interface of the original firmware.', + 'tr-sysupgrade-help': 'Sysupgrade images are for flashing routers that already run OpenWrt. The image can be applied using the web interface or the terminal.', + 'tr-kernel-help': 'Linux kernel as a separate image.', + 'tr-rootfs-help': 'Root file system as a separate image.', + 'tr-sdcard-help': 'Image that is meant to be flashed onto a SD-Card.', + 'tr-tftp-help': 'TFTP images are used to flash a device via the TFTP method of the bootloader.', + 'tr-other-help': 'Other image type.', + 'tr-build-successful': 'Build successful', + 'tr-build-failed': 'Build failed', + 'tr-request-image': 'Request image', + 'tr-check-again': 'Check again in 5 seconds...' + }, + 'es': { + 'tr-load': 'Descargue el firmware OpenWrt para su dispositivo!', + 'tr-title': 'Selector de firmware OpenWrt', + 'tr-message': 'Utilice la entrada a continuación para descargar el firmware de su dispositivo!', + 'tr-version-build': 'Compilar', + 'tr-custom-build': 'Compilación personalizada', + 'tr-customize': 'Personalizar', + 'tr-request-build': 'Solicitar compilación', + 'tr-model': 'Modelo:', + 'tr-target': 'Plataforma:', + 'tr-version': 'Versión:', + 'tr-date': 'Fecha:', + 'tr-downloads': 'Descargas', + 'tr-custom-downloads': 'Descargas personalizadas', + 'tr-factory-help': 'Las imágenes de fábrica son para enrutadores intermitentes con OpenWrt por primera vez. Generalmente a través de la interfaz web del firmware original.', + 'tr-sysupgrade-help': 'Las imágenes de Sysupgrade son para enrutadores intermitentes que ya ejecutan OpenWrt. La imagen se puede aplicar utilizando la interfaz web o el terminal.', + 'tr-kernel-help': 'Kernel de Linux como una imagen separada.', + 'tr-rootfs-help': 'Sistema de archivos raíz como una imagen separada.', + 'tr-sdcard-help': 'Imagen que debe ser mostrada en una tarjeta SD.', + 'tr-tftp-help': 'Las imágenes TFTP se utilizan para flashear un dispositivo mediante el método TFTP del gestor de arranque.', + 'tr-other-help': 'Otro tipo de imagen.', + 'tr-build-successful': 'Compilación exitosa', + 'tr-build-failed': 'Compilación fallida', + 'tr-request-image': 'Solicitar imagen', + 'tr-check-again': 'Verifique nuevamente en 5 segundos...' + }, + 'no': { + 'tr-load': 'Last ned OpenWrt fastvare for din enhet!', + 'tr-title': 'OpenWrt fastvare utvelger', + 'tr-message': 'Bruk feltene nedenfor for å laste ned fastvare til enheten din!', + 'tr-version-build': 'Sammensetning', + 'tr-custom-build': 'Tilpasset sammensetning', + 'tr-customize': 'Tilpasse', + 'tr-request-build': 'Be om sammensetning', + 'tr-model': 'Modell:', + 'tr-target': 'Platform:', + 'tr-version': 'Versjon:', + 'tr-date': 'Dato:', + 'tr-downloads': 'Nedlastninger', + 'tr-custom-downloads': 'Tilpassede nedlastninger', + 'tr-factory-help': 'Factory avbildningen er for å laste rutere med OpenWrt første gang. Vanligvis via webgrensesnittet til den originale fastvaren.', + 'tr-sysupgrade-help': 'Sysupgrade avbildningen er for rutere som allerede benytter OpenWrt. Avbildningen innstaleres gjennom webgrensesnittet eller terminalen.', + 'tr-kernel-help': 'Linux kjernen som en egen avbildning.', + 'tr-rootfs-help': 'Rotfilsystem som en egen avbildning.', + 'tr-sdcard-help': 'Avbildning som er ment for et SD-kort.', + 'tr-tftp-help': 'TFTP avbildninger er for å laste enheter via TFTP metoden i oppstartsprosedyren.', + 'tr-other-help': 'Andre avbildningstyper.', + 'tr-build-successful': 'Vellykket sammensetning', + 'tr-build-failed': 'Sammensetningen feilet', + 'tr-request-image': 'Be om avbildning', + 'tr-check-again': 'Sjekk pånytt om 5 sekunder...' + }, + 'de': { + 'tr-load': 'Lade die OpenWrt Firmware für dein Gerät!', + 'tr-title': 'OpenWrt Firmware Selector', + 'tr-message': 'Bitte benutze die Eingabe um die passende Firmware zu finden!', + 'tr-version-build': 'Release Build', + 'tr-custom-build': 'Custom Build', + 'tr-customize': 'Customize', + 'tr-request-build': 'Request Build', + 'tr-model': 'Model:', + 'tr-target': 'Target', + 'tr-version': 'Version:', + 'tr-date': 'Datum:', + 'tr-downloads': 'Downloads', + 'tr-custom-downloads': 'Custom Downloads', + 'tr-factory-help': 'Factory Abbilder werden über die Weboberfläche der originalen Firmware eingespielt.', + 'tr-sysupgrade-help': 'Sysupgrade Abbilder werden für Geräte verwendet, die bereits OpenWrt laufen haben. Es ist möglich, existierende Einstellungen beizubehalten.', + 'tr-kernel-help': 'Linux Kernel als separates Abbild.', + 'tr-rootfs-help': 'Das Root Dateisystem als separates Abbild.', + 'tr-sdcard-help': 'Image für SD Speicherkarten.', + 'tr-tftp-help': 'TFTP Dateien können verwendet werden, um ein Gerät über die TFTP Method des Bootloader zu flashen.', + 'tr-other-help': 'Sonstiger Imagetyp.', + 'tr-build-successful': 'Build erfolgreich', + 'tr-build-failed': 'Build fehlgeschlagen', + 'tr-request-image': 'Frage nach image', + 'tr-check-again': 'Nochmal nachfragen in 5 Sekunden...' + }, + 'fr': { + 'tr-load': 'Télécharger le firmware OpenWrt de votre périphérique !', + 'tr-title': 'Sélecteur de Firmware', + 'tr-message': 'Utiliser les entrées ci-dessous pour télécharger le firmware de votre périphérique !', + 'tr-version-build': 'Build', + 'tr-custom-build': 'Build Personnalisé', + 'tr-customize': 'Personnalisation', + 'tr-request-build': 'Requête de Build', + 'tr-model': 'Modèle:', + 'tr-target': 'Platform:', + 'tr-version': 'Version:', + 'tr-date': 'Date:', + 'tr-downloads': 'Téléchargements', + 'tr-custom-downloads': 'Téléchargements Personnalusés', + 'tr-factory-help': 'Les images Factory sont prévues pour flasher les routers avec OpenWrt pour la première fois. Habituellement à partir de l\'interface web du firmware d\'origine.', + 'tr-sysupgrade-help': 'Les images Sysupgrade sont prévues pour flasher les routers fonctionnant déjà avec OpenWrt. L\'image peut être installée à travers l\'interface web ou par le terminal.', + 'tr-kernel-help': 'Linux kernel comme image séparée.', + 'tr-rootfs-help': 'Root file system comme image séparée.', + 'tr-sdcard-help': 'Image prévue pour être flashée sur une carte SD.', + 'tr-tftp-help': 'TFTP images prévues pour flasher le périphérique via le démarrage par méthode TFTP.', + 'tr-other-help': 'Autre type d\'image.', + 'tr-build-successful': 'Succès du Build', + 'tr-build-failed': 'Échec du Build', + 'tr-request-image': 'Demade d\'image', + 'tr-check-again': 'Essayer à nouveau dans 5 secondes...' + }, + 'it': { + 'tr-load': 'Scarica il firmware OpenWrt per il tuo dispositivo!', + 'tr-title': 'OpenWrt Firmware Selector', + 'tr-message': 'Usa la casella sottostante per scaricare il firmware per il tuo dispositivo!', + 'tr-version-build': 'Build', + 'tr-custom-build': 'Custom Build', + 'tr-customize': 'Personalizza', + 'tr-request-build': 'Richiedi Build', + 'tr-model': 'Modell:', + 'tr-target': 'Platform:', + 'tr-version': 'Version:', + 'tr-date': 'Data:', + 'tr-downloads': 'Downloads', + 'tr-custom-downloads': 'Download Personalizzati', + 'tr-factory-help': 'Factory Image sono usate per installare OpenWrt su router per la prima volta. Di solito l\'immagine può essere applicata via l\'interfaccia web del firmware originale.', + 'tr-sysupgrade-help': 'Sysupgrade Image sono usate per flashare router in cui OpenWrt è già installato. L\'immagine può essere applicata via interfaccia web o terminale.', + 'tr-kernel-help': 'Linux kernel come immagine separata.', + 'tr-rootfs-help': 'Root file system come immagine separata.', + 'tr-sdcard-help': 'Immagine da flashare su scheda SD-Card separata.', + 'tr-tftp-help': 'Immagini TFTP images sono usate per flashare un dispositivo con il metodo TFTP del bootloader.', + 'tr-other-help': 'Other image type.', + 'tr-build-successful': 'Build compilata con successo', + 'tr-build-failed': 'Build fallita', + 'tr-request-image': 'Richiedi immagine', + 'tr-check-again': 'Prova di nuovo in 5 secondi...' + }, + 'pl': { + 'tr-load': 'Pobieranie oprogramowania OpenWrt!', + 'tr-title': 'OpenWrt Firmware Selector', + 'tr-message': 'Użyj pola poniżej żeby znaleźć obraz dla swojego urządzenia!', + 'tr-version-build': 'Informacje o obrazie', + 'tr-custom-build': 'Informacje o zmodyfikowanym obrazie', + 'tr-customize': 'Modyfikacja', + 'tr-request-build': 'Żądanie budowy obrazu', + 'tr-model': 'Model:', + 'tr-target': 'Platforma:', + 'tr-version': 'Wersja:', + 'tr-date': 'Data:', + 'tr-downloads': 'Obrazy do pobrania', + 'tr-custom-downloads': 'Zmodyfikowane obrazy do pobrania', + 'tr-factory-help': 'Obraz factory używany jest do pierwszej instalacji OpenWrt. Zwykle można go użyć wykorzystując interfejs graficzny oryginalnego oprogramowania.', + 'tr-sysupgrade-help': 'Obraz sysuprade używany jest do aktualizacji routerów z zainstalowanym już OpenWrt. Obraz można użyć przez GUI lub konsolę.', + 'tr-kernel-help': 'Osobny obraz z kernelem linuksowym.', + 'tr-rootfs-help': 'Osobny obraz z system plików.', + 'tr-sdcard-help': 'Obraz do wgrania na kartę SD.', + 'tr-tftp-help': 'Obraz TFTP służący do aktualizacji urządzenia z wykorzystaniem TFTP i bootloadera.', + 'tr-other-help': 'Inny typ obrazu.', + 'tr-build-successful': 'Budowanie zakończone pomyślnie', + 'tr-build-failed': 'Błąd budowania', + 'tr-request-image': 'Żądanie obrazu', + 'tr-check-again': 'Sprawdź ponownie za 5 sekund...' + }, + 'tr': { + 'tr-load': 'Cihazınız için OpenWrt yazılımını indirin!', + 'tr-title': 'OpenWrt Yazılım Seçicisi', + 'tr-message': 'Cihazınız için yazılımı indirmek için lütfen aşağıdaki girişi kullanın!', + 'tr-version-build': 'Sürüm', + 'tr-custom-build': 'Özel Sürüm', + 'tr-customize': 'Özelleştir', + 'tr-request-build': 'Sürüm Oluştur', + 'tr-model': 'Model:', + 'tr-target': 'Platform:', + 'tr-version': 'Versiyon:', + 'tr-date': 'Tarih:', + 'tr-downloads': 'İndirmeler', + 'tr-custom-downloads': 'Özel İndirmeler', + 'tr-factory-help': 'Fabrika imajları, ilk kez OpenWrt yüklenen cihazlar içindir. Genellikle orijinal ürün yazılımının web arayüzü üzerinden yüklenir.', + 'tr-sysupgrade-help': 'Sysupgrade imajları, zaten OpenWrt kurulu cihazlar içindir. İmaj, web arayüzü veya terminal kullanılarak yüklenebilir.', + 'tr-kernel-help': 'Linux kernel ayrı bir imaj olarak.', + 'tr-rootfs-help': 'Kök Dosya Sistemi ayrı bir imaj olarak.', + 'tr-sdcard-help': 'SD-Kart \'a kurulması planlanan imaj', + 'tr-tftp-help': 'TFTP imajları, Bootloader \'ın TFTP yöntemi ile bir cihaza kurulması için kullanılır.', + 'tr-other-help': 'Diğer imaj türü.', + 'tr-build-successful': 'Oluşturma başarılı', + 'tr-build-failed': 'Oluşturma başarısız', + 'tr-request-image': 'Imaj oluştur', + 'tr-check-again': '5 saniye icinde tekrar dene...' + } +}; + +// Complement translations based on other translations +//translations['en'] = Object.assign({}, translations['de'], translations['en']); diff --git a/www/index.css b/www/index.css new file mode 100644 index 0000000..e0e1885 --- /dev/null +++ b/www/index.css @@ -0,0 +1,231 @@ + +body { + font-family: "Arial", sans-serif; + margin: 0px; +} + +#buildstatus a { + color: inherit; +} + +#models-autocomplete { + width: 20em; + display: inline-block; +} + +.autocomplete { + position: relative; +} + +.autocomplete > input { + border: 1px solid transparent; + background-color: #f1f1f1; + padding: 10px; + width: 100%; + border-radius: 4px; +} + +.autocomplete-items { + position: absolute; + border: 1px solid #d4d4d4; + border-bottom: none; + border-top: none; + z-index: 99; + /*position the autocomplete items to be the same width as the container:*/ + top: 100%; + left: 0; + right: 0; +} + +.autocomplete-items div { + padding: 10px; + cursor: pointer; + background-color: #fff; + border-bottom: 1px solid #d4d4d4; +} + +/*when hovering an item:*/ +.autocomplete-items div:hover { + background-color: #e9e9e9; +} + +/*when navigating through the items using the arrow keys:*/ +.autocomplete-active { + background-color: DodgerBlue !important; + color: #ffffff; +} + +header { + font-weight: 500; + width: 100%; + z-index: 1100; + box-shadow: 0px 2px 4px -1px rgba(0,0,0,0.2),0px 4px 5px 0px rgba(0,0,0,0.14),0px 1px 10px 0px rgba(0,0,0,0.12); + background-color: #00A3E1; +} + +h6 { + margin: 0; + font-size: 1.25rem; + font-weight: 500; + line-height: 1.6; + letter-spacing: 0.0075em; +} + +header > div { + padding-left: 24px; + padding-right: 24px; + min-height: 64px; + + display: flex; + position: relative; + align-items: center; + color: #fff; +} + +.container { + max-width: 1280px; + padding-left: 32px; + padding-right: 32px; + width: 100%; + box-sizing: border-box; + margin-top: 30px; + margin-right: auto; + margin-left: auto; + margin-bottom: 100px; +} + +.container > div { + padding: 10px 20px; + text-align: left; + box-shadow: 0px 1px 3px 0px rgba(0,0,0,0.2),0px 1px 1px 0px rgba(0,0,0,0.14),0px 2px 1px -1px rgba(0,0,0,0.12); + border-radius: 4px; + color: rgba(0, 0, 0, 0.87); + transition: box-shadow 300ms cubic-bezier(0.4, 0, 0.2, 1) 0ms; + background-color: #fff; +} + +#versions { + border: 1px solid transparent; + background-color: #f1f1f1; + padding: 10px; + width: 10em; + border-radius: 4px; +} + +#language-selection { + color: #fff; + background-color: #1084b2; + box-shadow: 0px 1px 5px 0px rgba(0,0,0,0.2),0px 2px 2px 0px rgba(0,0,0,0.14),0px 3px 1px -2px + rgba(0,0,0,0.12); + padding: 6px 16px; + border-radius: 4px; + border: 0; + + /* hide arrow */ + -webkit-appearance: none; + -moz-appearance: none; + text-indent: 1px; + text-overflow: ''; +} + +.download-link { + text-decoration: none; + border-radius: 4px; + padding: 12px 16px; + margin: 5px; + font-size: 16px; + cursor: pointer; + letter-spacing: 0.05em; + display: inline-flex; + align-items: center; + box-shadow: 0px 1px 5px 0px rgba(0,0,0,0.2),0px 2px 2px 0px rgba(0,0,0,0.14),0px 3px 1px -2px rgba(0,0,0,0.12); + color: #fff; + background-color: #00A3E1; +} + +.download-link:hover { + background-color: #038fc6 +} + +.download-link :first-child { + width: 30px; + margin-right: 15px; + margin-top: -2px; + content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.64 5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96zM17 13l-5 5-5-5h3V9h4v4h3z' fill='%23fff'%3E%3C/path%3E%3Cpath d='M0 0h24v24H0z' fill='none'/%3E%3C/svg%3E"); +} + +#images .column { + width: 5em; + display: inline-block; + line-height: 1.5; +} + +#images { + display: none; +} + +#images > div { + padding-top: 20px; +} + +#image-model { + font-weight: bold; +} + +#custom { + display: none; +} + +#custom textarea { + width: 500px; + height: 120px; + font-size: 16px; + display: block; +} + +#custom a :first-child { + width: 30px; + margin-right: 10px; + margin-top: 0px; + font-size: 36px; +} + +#custom a { + text-decoration: none; + border-radius: 4px; + padding: 2px 10px; + margin: 5px; + font-size: 16px; + cursor: pointer; + letter-spacing: 0.05em; + display: inline-flex; + align-items: center; + box-shadow: 0px 1px 5px 0px rgba(0,0,0,0.2),0px 2px 2px 0px rgba(0,0,0,0.14),0px 3px 1px -2px rgba(0,0,0,0.12); + color: #fff; + background-color: #00A3E1; +} + +.download-help { + display: none; +} + +#buildspinner { + float: left; + height: 40px; + padding-right: 12px; + display: none; +} + +#buildstatus { + padding: 10px 0; + display: none; +} + +#footer { + font-size: 0.8em; + text-align: right; +} + +#footer a { + text-decoration: none; +} diff --git a/www/index.html b/www/index.html new file mode 100644 index 0000000..2260f81 --- /dev/null +++ b/www/index.html @@ -0,0 +1,96 @@ + + + + + + OpenWrt Firmware Selector + + + + + + + +
+
+ + Logo +
+ + +
+
+ +
+
+

Download OpenWrt firmware for your device!

+

Please use the input below to download firmware for your device!

+
+ + +
+ +
+ +
+
+ +
+ Logo +
+
+ +
+
+

Customize

+
+ +
+ + Request Build + +
+ +
+

Release Build

+
Model:
+
Target:
+
Version: ()
+
Date:
+
+ + + +
+ Factory images are for flashing routers with OpenWrt for the first time using the web interface of the original firmware. + Sysupgrade images are for flashing routers that already run OpenWrt. The image can be applied using the web interface or the console. + Linux kernel as a separate image. + Root file system as a separate image. + Image that is meant to be flashed on an SD-Card. + Image that can be applied using the TFTP meachnism of the bootloader + Image of unknown purpose. +
+
+ + +
+
+ + + diff --git a/www/index.js b/www/index.js new file mode 100644 index 0000000..7562da4 --- /dev/null +++ b/www/index.js @@ -0,0 +1,451 @@ + +var current_model = {}; + +function $(id) { + return document.getElementById(id); +} + +function show(id) { + $(id).style.display = 'block'; +} + +function hide(id) { + $(id).style.display = 'none'; +} + +function split(str) { + return str.match(/[^\s,]+/g) || []; +} + +function get_model_titles(titles) { + return titles.map(e => { + if (e.title) { + return e.title; + } else { + return ((e.vendor || '') + ' ' + (e.model || '') + ' ' + (e.variant || '')).trim(); + } + }).join(' / '); +} + +function build_asu_request() { + if (!current_model || !current_model.id) { + alert('bad profile'); + return; + } + + function showStatus(message, url) { + show('buildstatus'); + var tr = message.startsWith('tr-') ? message : ''; + if (url) { + $('buildstatus').innerHTML = '' + message + ''; + } else { + $('buildstatus').innerHTML = ''; + } + translate(); + } + + // hide image view + updateImages(); + + show('buildspinner'); + showStatus('tr-request-image'); + + var request_data = { + 'target': current_model.target, + 'profile': current_model.id, + 'packages': split($('packages').value), + 'version': $('versions').value + } + + fetch(config.asu_url + '/api/build', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(request_data) + }) + .then(response => { + switch (response.status) { + case 200: + hide('buildspinner'); + showStatus('tr-build-successful'); + + response.json() + .then(mobj => { + var download_url = config.asu_url + '/store/' + mobj.bin_dir; + showStatus('tr-build-successful', download_url + '/buildlog.txt'); + updateImages( + mobj.version_number, + mobj.version_code, + mobj.build_at, + get_model_titles(mobj.titles), + download_url, mobj, true + ); + }); + break; + case 202: + showStatus('tr-check-again'); + setTimeout(_ => { build_asu_request() }, 5000); + break; + case 400: // bad request + case 422: // bad package + case 500: // build failed + hide('buildspinner'); + response.json() + .then(mobj => { + var message = mobj['message'] || 'tr-build-failed'; + var url = mobj.buildlog ? (config.asu_url + '/store/' + mobj.bin_dir + '/buildlog.txt') : undefined; + showStatus(message, url); + }) + break; + } + }) + .catch(err => { + hide('buildspinner'); + showStatus(err); + }) +} + +function setupSelectList(select, items, onselection) { + for (var i = 0; i < items.length; i += 1) { + var option = document.createElement('OPTION'); + option.innerHTML = items[i]; + select.appendChild(option); + } + + select.addEventListener('change', e => { + onselection(items[select.selectedIndex]); + }); + + if (select.selectedIndex >= 0) { + onselection(items[select.selectedIndex]); + } +} + +// Change the translation of the entire document +function translate() { + var mapping = translations[config.language]; + for (var tr in mapping) { + Array.from(document.getElementsByClassName(tr)) + .forEach(e => { e.innerText = mapping[tr]; }) + } +} + +function setupAutocompleteList(input, items, as_list, onbegin, onend) { + var currentFocus = -1; + + // sort numbers and other characters separately + var collator = new Intl.Collator(undefined, {numeric: true, sensitivity: 'base'}); + + items.sort(collator.compare); + + input.oninput = function(e) { + onbegin(); + + var offset = 0; + var value = this.value; + var value_list = []; + + if (as_list) { + // automcomplete last text item + offset = this.value.lastIndexOf(' ') + 1; + value = this.value.substr(offset); + value_list = split(this.value.substr(0, offset)); + } + + // close any already open lists of autocompleted values + closeAllLists(); + + if (!value) { + return false; + } + + // create a DIV element that will contain the items (values): + var list = document.createElement('DIV'); + list.setAttribute('id', this.id + '-autocomplete-list'); + list.setAttribute('class', 'autocomplete-items'); + // append the DIV element as a child of the autocomplete container: + this.parentNode.appendChild(list); + + var c = 0; + for (var i = 0; i < items.length; i += 1) { + var item = items[i]; + + // match + var j = item.toUpperCase().indexOf(value.toUpperCase()); + if (j < 0) { + continue; + } + + // do not offer a duplicate item + if (as_list && value_list.indexOf(item) != -1) { + continue; + } + + c += 1; + if (c >= 15) { + var div = document.createElement('DIV'); + div.innerHTML = '...'; + list.appendChild(div); + break; + } else { + var div = document.createElement('DIV'); + // make the matching letters bold: + div.innerHTML = item.substr(0, j) + + '' + item.substr(j, value.length) + '' + + item.substr(j + value.length) + + ''; + + div.addEventListener('click', function(e) { + // include selected value + var selected = this.getElementsByTagName('input')[0].value; + if (as_list) { + input.value = value_list.join(' ') + ' ' + selected; + } else { + input.value = selected; + } + // close the list of autocompleted values, + closeAllLists(); + onend(input); + }); + + list.appendChild(div); + } + } + }; + + input.onkeydown = function(e) { + var x = document.getElementById(this.id + '-autocomplete-list'); + if (x) x = x.getElementsByTagName('div'); + if (e.keyCode == 40) { + // key down + currentFocus += 1; + // and and make the current item more visible: + setActive(x); + } else if (e.keyCode == 38) { + // key up + currentFocus -= 1; + // and and make the current item more visible: + setActive(x); + } else if (e.keyCode == 13) { + // If the ENTER key is pressed, prevent the form from being submitted, + e.preventDefault(); + if (currentFocus > -1) { + // and simulate a click on the 'active' item: + if (x) x[currentFocus].click(); + } + } + }; + + input.onfocus = function() { + onend(input); + } + + // focus lost + input.onblur = function() { + onend(input); + } + + function setActive(x) { + // a function to classify an item as 'active': + if (!x) return false; + // start by removing the 'active' class on all items: + for (var i = 0; i < x.length; i++) { + x[i].classList.remove('autocomplete-active'); + } + if (currentFocus >= x.length) currentFocus = 0; + if (currentFocus < 0) currentFocus = (x.length - 1); + // add class 'autocomplete-active': + x[currentFocus].classList.add('autocomplete-active'); + } + + function closeAllLists(elmnt) { + // close all autocomplete lists in the document, + // except the one passed as an argument: + var x = document.getElementsByClassName('autocomplete-items'); + for (var i = 0; i < x.length; i++) { + if (elmnt != x[i] && elmnt != input) { + x[i].parentNode.removeChild(x[i]); + } + } + } + + // execute a function when someone clicks in the document: + document.addEventListener('click', e => { + closeAllLists(e.target); + }); +} + +// for attended sysupgrade +function updatePackageList(version, target) { + // set available packages + fetch(config.asu_url + '/' + config.versions[version] + '/' + target + '/index.json') + .then(response => response.json()) + .then(all_packages => { + setupAutocompleteList($('packages'), all_packages, true, _ => {}, textarea => { + textarea.value = split(textarea.value) + // make list unique, ignore minus + .filter((value, index, self) => { + var i = self.indexOf(value.replace(/^\-/, '')); + return (i === index) || (i < 0); + }) + // limit to available packages, ignore minus + .filter((value, index) => all_packages.indexOf(value.replace(/^\-/, '')) !== -1) + .join(' '); + }); + }); +} + +function updateImages(version, code, date, model, url, mobj, is_custom) { + // add download button for image + function addLink(type, file) { + var a = document.createElement('A'); + a.classList.add('download-link'); + a.href = url + .replace('{target}', mobj.target) + .replace('{version}', version) + + '/' + file; + var span = document.createElement('SPAN'); + span.appendChild(document.createTextNode('')); + a.appendChild(span); + a.appendChild(document.createTextNode(type.toUpperCase())); + + if (config.showHelp) { + a.onmouseover = function() { + // hide all help texts + Array.from(document.getElementsByClassName('download-help')) + .forEach(e => e.style.display = 'none'); + var lc = type.toLowerCase(); + if (lc.includes('sysupgrade')) { + show('sysupgrade-help'); + } else if (lc.includes('factory') || lc == 'trx' || lc == 'chk') { + show('factory-help'); + } else if (lc.includes('kernel') || lc.includes('zimage') || lc.includes('uimage')) { + show('kernel-help'); + } else if (lc.includes('root')) { + show('rootfs-help'); + } else if (lc.includes('sdcard')) { + show('sdcard-help'); + } else if (lc.includes('tftp')) { + show('tftp-help'); + } else { + show('other-help'); + } + }; + } + + $('download-links').appendChild(a); + } + + function switchClass(id, from_class, to_class) { + $(id).classList.remove(from_class); + $(id).classList.add(to_class); + } + + // remove all download links + Array.from(document.getElementsByClassName('download-link')) + .forEach(e => e.remove()); + + // hide all help texts + Array.from(document.getElementsByClassName('download-help')) + .forEach(e => e.style.display = 'none'); + + if (version && code && date && model && url && mobj) { + var target = mobj.target; + var images = mobj.images; + + // change between "version" and "custom" title + if (is_custom) { + switchClass('images-title', 'tr-version-build', 'tr-custom-build'); + switchClass('downloads-title', 'tr-version-downloads', 'tr-custom-downloads'); + } else { + switchClass('images-title', 'tr-custom-build', 'tr-version-build'); + switchClass('downloads-title', 'tr-custom-downloads', 'tr-version-downloads'); + } + // update title translation + translate(); + + // fill out build info + $('image-model').innerText = model; + $('image-target').innerText = target; + $('image-version').innerText = version; + $('image-code').innerText = code; + $('image-date').innerText = date; + + images.sort((a, b) => a.name.localeCompare(b.name)); + + for (var i in images) { + addLink(images[i].type, images[i].name); + } + + if (config.asu_url) { + updatePackageList(version, target); + } + + show('images'); + } else { + hide('images'); + } +} + +function init() { + var build_date = "unknown" + setupSelectList($('versions'), Object.keys(config.versions), version => { + var url = config.versions[version]; + if (config.asu_url) { + url = config.asu_url + '/' + url + '/profiles.json'; + } + fetch(url) + .then(obj => { + build_date = obj.headers.get('last-modified'); + return obj.json(); + }) + .then(obj => { + // handle native openwrt json format + if ('profiles' in obj) { + obj['models'] = {} + for (const [key, value] of Object.entries(obj['profiles'])) { + obj['models'][get_model_titles(value.titles)] = value + obj['models'][get_model_titles(value.titles)]['id'] = key + } + } + return obj + }) + .then(obj => { + setupAutocompleteList($('models'), Object.keys(obj['models']), false, updateImages, models => { + var model = models.value; + if (model in obj['models']) { + var url = obj.url || 'unknown'; + var code = obj.version_code || 'unknown'; + var mobj = obj['models'][model]; + updateImages(version, code, build_date, model, url, mobj, false); + current_model = mobj; + } else { + updateImages(); + current_model = {}; + } + }); + + // trigger model update when selected version changes + $('models').onfocus(); + }); + }); + + if (config.asu_url) { + show('custom'); + } + + // hide fields + updateImages(); + + var user_lang = (navigator.language || navigator.userLanguage).split('-')[0]; + if (user_lang in translations) { + config.language = user_lang; + $('language-selection').value = user_lang; + } + + translate(); + + $('language-selection').onclick = function() { + config.language = this.children[this.selectedIndex].value; + translate(); + } +} diff --git a/www/logo.png b/www/logo.png new file mode 100644 index 0000000..8500f9b Binary files /dev/null and b/www/logo.png differ diff --git a/www/spinner.gif b/www/spinner.gif new file mode 100644 index 0000000..7154314 Binary files /dev/null and b/www/spinner.gif differ