introduce breadcrumbs in the web config
This commit is contained in:
		| @@ -151,4 +151,8 @@ h1 { | ||||
|  | ||||
| .scheduler-static-time-inputs > select { | ||||
|     flex: 1 0 auto; | ||||
| } | ||||
|  | ||||
| .breadcrumb { | ||||
|     margin-top: .5rem; | ||||
| } | ||||
| @@ -10,6 +10,7 @@ | ||||
| </HEAD><BODY> | ||||
|     ${header} | ||||
|     <div class="container"> | ||||
|         ${breadcrumb} | ||||
|         <h1>OpenWebRX Feature Report</h1> | ||||
|         <table class="features table"> | ||||
|             <tr> | ||||
| @@ -19,5 +20,6 @@ | ||||
|                 <th>Available</th> | ||||
|             </tr> | ||||
|         </table> | ||||
|         ${breadcrumb} | ||||
|     </div> | ||||
| </BODY></HTML> | ||||
| @@ -13,8 +13,7 @@ $(function(){ | ||||
|             }); | ||||
|             $table.append( | ||||
|                 '<tr>' + | ||||
|                     '<td colspan=2>' + name + '</td>' + | ||||
|                     '<td>' + converter.makeHtml(details.description) + '</td>' + | ||||
|                     '<td colspan=3>' + name + '</td>' + | ||||
|                     '<td>' + (details.available ? 'YES' : 'NO') + '</td>' + | ||||
|                 '</tr>' + | ||||
|                 requirements.join("") | ||||
|   | ||||
| @@ -11,6 +11,7 @@ | ||||
| <body> | ||||
| ${header} | ||||
| <div class="container"> | ||||
|     ${breadcrumb} | ||||
|     <div class="row"> | ||||
|         <h1 class="col-12">Bookmarks</h1> | ||||
|     </div> | ||||
| @@ -24,6 +25,7 @@ ${header} | ||||
|             <button type="button" class="btn btn-primary bookmark-add">Add a new bookmark</button> | ||||
|         </div> | ||||
|     </div> | ||||
|     ${breadcrumb} | ||||
| </div> | ||||
| <div class="modal" id="deleteModal" tabindex="-1" role="dialog"> | ||||
|     <div class="modal-dialog" role="document"> | ||||
|   | ||||
| @@ -11,10 +11,12 @@ | ||||
| <body> | ||||
| ${header} | ||||
| <div class="container"> | ||||
|     ${breadcrumb} | ||||
|     <div class="row"> | ||||
|         <h1 class="col-12">${title}</h1> | ||||
|     </div> | ||||
|     ${content} | ||||
|     ${breadcrumb} | ||||
| </div> | ||||
| ${modal} | ||||
| </body> | ||||
							
								
								
									
										42
									
								
								owrx/breadcrumb.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								owrx/breadcrumb.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,42 @@ | ||||
| from typing import List | ||||
| from abc import ABC, abstractmethod | ||||
|  | ||||
|  | ||||
| class BreadcrumbItem(object): | ||||
|     def __init__(self, title, href): | ||||
|         self.title = title | ||||
|         self.href = href | ||||
|  | ||||
|     def render(self, documentRoot): | ||||
|         return '<li class="breadcrumb-item"><a href="{documentRoot}{href}">{title}</a></li>'.format( | ||||
|             documentRoot=documentRoot, href=self.href, title=self.title | ||||
|         ) | ||||
|  | ||||
|  | ||||
| class Breadcrumb(object): | ||||
|     def __init__(self, breadcrumbs: List[BreadcrumbItem]): | ||||
|         self.items = breadcrumbs | ||||
|  | ||||
|     def render(self, documentRoot): | ||||
|         return """ | ||||
|             <ol class="breadcrumb"> | ||||
|                 {crumbs} | ||||
|             </ol> | ||||
|         """.format( | ||||
|             crumbs="".join(item.render(documentRoot) for item in self.items) | ||||
|         ) | ||||
|  | ||||
|     def append(self, crumb: BreadcrumbItem): | ||||
|         self.items.append(crumb) | ||||
|         return self | ||||
|  | ||||
|  | ||||
| class BreadcrumbMixin(ABC): | ||||
|     def template_variables(self): | ||||
|         variables = super().template_variables() | ||||
|         variables["breadcrumb"] = self.get_breadcrumb().render(self.get_document_root()) | ||||
|         return variables | ||||
|  | ||||
|     @abstractmethod | ||||
|     def get_breadcrumb(self) -> Breadcrumb: | ||||
|         pass | ||||
							
								
								
									
										11
									
								
								owrx/controllers/feature.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								owrx/controllers/feature.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| from owrx.controllers.template import WebpageController | ||||
| from owrx.breadcrumb import Breadcrumb, BreadcrumbItem, BreadcrumbMixin | ||||
| from owrx.controllers.settings import SettingsBreadcrumb | ||||
|  | ||||
|  | ||||
| class FeatureController(BreadcrumbMixin, WebpageController): | ||||
|     def get_breadcrumb(self) -> Breadcrumb: | ||||
|         return SettingsBreadcrumb().append(BreadcrumbItem("Feature report", "features")) | ||||
|  | ||||
|     def indexAction(self): | ||||
|         self.serve_template("features.html", **self.template_variables()) | ||||
| @@ -2,6 +2,7 @@ from owrx.config import Config | ||||
| from owrx.controllers.admin import AuthorizationMixin | ||||
| from owrx.controllers.template import WebpageController | ||||
| from owrx.form.error import FormError | ||||
| from owrx.breadcrumb import Breadcrumb, BreadcrumbItem, BreadcrumbMixin | ||||
| from abc import ABCMeta, abstractmethod | ||||
| from urllib.parse import parse_qs | ||||
|  | ||||
| @@ -50,7 +51,7 @@ class SettingsController(AuthorizationMixin, WebpageController): | ||||
|         self.serve_template("settings.html", **self.template_variables()) | ||||
|  | ||||
|  | ||||
| class SettingsFormController(AuthorizationMixin, WebpageController, metaclass=ABCMeta): | ||||
| class SettingsFormController(AuthorizationMixin, BreadcrumbMixin, WebpageController, metaclass=ABCMeta): | ||||
|     def __init__(self, handler, request, options): | ||||
|         super().__init__(handler, request, options) | ||||
|         self.errors = {} | ||||
| @@ -144,3 +145,9 @@ class SettingsFormController(AuthorizationMixin, WebpageController, metaclass=AB | ||||
|  | ||||
|     def buildModal(self): | ||||
|         return "" | ||||
|  | ||||
|  | ||||
| class SettingsBreadcrumb(Breadcrumb): | ||||
|     def __init__(self): | ||||
|         super().__init__([]) | ||||
|         self.append(BreadcrumbItem("Settings", "settings")) | ||||
|   | ||||
| @@ -1,11 +1,16 @@ | ||||
| from owrx.controllers.settings import SettingsFormController, Section | ||||
| from owrx.form import CheckboxInput, ServicesCheckboxInput | ||||
| from owrx.breadcrumb import Breadcrumb, BreadcrumbItem | ||||
| from owrx.controllers.settings import SettingsBreadcrumb | ||||
|  | ||||
|  | ||||
| class BackgroundDecodingController(SettingsFormController): | ||||
|     def getTitle(self): | ||||
|         return "Background decoding" | ||||
|  | ||||
|     def get_breadcrumb(self) -> Breadcrumb: | ||||
|         return SettingsBreadcrumb().append(BreadcrumbItem("Background decoding", "settings/backgrounddecoding")) | ||||
|  | ||||
|     def getSections(self): | ||||
|         return [ | ||||
|             Section( | ||||
|   | ||||
| @@ -1,7 +1,9 @@ | ||||
| from owrx.controllers.template import WebpageController | ||||
| from owrx.controllers.admin import AuthorizationMixin | ||||
| from owrx.controllers.settings import SettingsBreadcrumb | ||||
| from owrx.bookmarks import Bookmark, Bookmarks | ||||
| from owrx.modes import Modes | ||||
| from owrx.breadcrumb import Breadcrumb, BreadcrumbItem, BreadcrumbMixin | ||||
| import json | ||||
| import math | ||||
|  | ||||
| @@ -10,7 +12,10 @@ import logging | ||||
| logger = logging.getLogger(__name__) | ||||
|  | ||||
|  | ||||
| class BookmarksController(AuthorizationMixin, WebpageController): | ||||
| class BookmarksController(AuthorizationMixin, BreadcrumbMixin, WebpageController): | ||||
|     def get_breadcrumb(self) -> Breadcrumb: | ||||
|         return SettingsBreadcrumb().append(BreadcrumbItem("Bookmark editor", "settings/bookmarks")) | ||||
|  | ||||
|     def template_variables(self): | ||||
|         variables = super().template_variables() | ||||
|         variables["bookmarks"] = self.render_table() | ||||
|   | ||||
| @@ -1,14 +1,18 @@ | ||||
| from owrx.controllers.settings import SettingsFormController, Section | ||||
| from owrx.controllers.settings import SettingsFormController, Section, SettingsBreadcrumb | ||||
| from owrx.form import CheckboxInput, NumberInput, DropdownInput, Js8ProfileCheckboxInput, MultiCheckboxInput, Option | ||||
| from owrx.form.wfm import WfmTauValues | ||||
| from owrx.form.wsjt import Q65ModeMatrix, WsjtDecodingDepthsInput | ||||
| from owrx.wsjt import Fst4Profile, Fst4wProfile | ||||
| from owrx.breadcrumb import Breadcrumb, BreadcrumbItem | ||||
|  | ||||
|  | ||||
| class DecodingSettingsController(SettingsFormController): | ||||
|     def getTitle(self): | ||||
|         return "Demodulation and decoding" | ||||
|  | ||||
|     def get_breadcrumb(self) -> Breadcrumb: | ||||
|         return SettingsBreadcrumb().append(BreadcrumbItem("Demodulation and decoding", "settings/decoding")) | ||||
|  | ||||
|     def getSections(self): | ||||
|         return [ | ||||
|             Section( | ||||
|   | ||||
| @@ -14,6 +14,8 @@ from owrx.form.receiverid import ReceiverKeysConverter | ||||
| from owrx.form.gfx import AvatarInput, TopPhotoInput | ||||
| from owrx.form.device import WaterfallLevelsInput, WaterfallAutoLevelsInput | ||||
| from owrx.waterfall import WaterfallOptions | ||||
| from owrx.breadcrumb import Breadcrumb, BreadcrumbItem | ||||
| from owrx.controllers.settings import SettingsBreadcrumb | ||||
| import shutil | ||||
| import os | ||||
| from glob import glob | ||||
| @@ -27,6 +29,9 @@ class GeneralSettingsController(SettingsFormController): | ||||
|     def getTitle(self): | ||||
|         return "General Settings" | ||||
|  | ||||
|     def get_breadcrumb(self) -> Breadcrumb: | ||||
|         return SettingsBreadcrumb().append(BreadcrumbItem("General Settings", "settings/general")) | ||||
|  | ||||
|     def getSections(self): | ||||
|         return [ | ||||
|             Section( | ||||
|   | ||||
| @@ -1,12 +1,16 @@ | ||||
| from owrx.controllers.settings import SettingsFormController, Section | ||||
| from owrx.controllers.settings import SettingsFormController, Section, SettingsBreadcrumb | ||||
| from owrx.form.converter import OptionalConverter | ||||
| from owrx.form.aprs import AprsBeaconSymbols, AprsAntennaDirections | ||||
| from owrx.form import TextInput, CheckboxInput, DropdownInput, NumberInput | ||||
| from owrx.breadcrumb import Breadcrumb, BreadcrumbItem | ||||
|  | ||||
|  | ||||
| class ReportingController(SettingsFormController): | ||||
|     def getTitle(self): | ||||
|         return "Spotting and Reporting" | ||||
|         return "Spotting and reporting" | ||||
|  | ||||
|     def get_breadcrumb(self) -> Breadcrumb: | ||||
|         return SettingsBreadcrumb().append(BreadcrumbItem("Spotting and reporting", "settings/reporting")) | ||||
|  | ||||
|     def getSections(self): | ||||
|         return [ | ||||
|   | ||||
| @@ -4,16 +4,23 @@ from owrx.controllers.settings import SettingsFormController | ||||
| from owrx.source import SdrDeviceDescription, SdrDeviceDescriptionMissing, SdrClientClass | ||||
| from owrx.config import Config | ||||
| from owrx.connection import OpenWebRxReceiverClient | ||||
| from owrx.controllers.settings import Section | ||||
| from owrx.controllers.settings import Section, SettingsBreadcrumb | ||||
| from urllib.parse import quote, unquote | ||||
| from owrx.sdr import SdrService | ||||
| from owrx.form import TextInput, DropdownInput, Option | ||||
| from owrx.form.validator import RequiredValidator | ||||
| from owrx.property import PropertyLayer, PropertyStack | ||||
| from owrx.breadcrumb import BreadcrumbMixin, Breadcrumb, BreadcrumbItem | ||||
| from abc import ABCMeta, abstractmethod | ||||
|  | ||||
|  | ||||
| class SdrDeviceListController(AuthorizationMixin, WebpageController): | ||||
| class SdrDeviceBreadcrumb(SettingsBreadcrumb): | ||||
|     def __init__(self): | ||||
|         super().__init__() | ||||
|         self.append(BreadcrumbItem("SDR device settings", "settings/sdr")) | ||||
|  | ||||
|  | ||||
| class SdrDeviceListController(AuthorizationMixin, BreadcrumbMixin, WebpageController): | ||||
|     def template_variables(self): | ||||
|         variables = super().template_variables() | ||||
|         variables["content"] = self.render_devices() | ||||
| @@ -21,6 +28,9 @@ class SdrDeviceListController(AuthorizationMixin, WebpageController): | ||||
|         variables["modal"] = "" | ||||
|         return variables | ||||
|  | ||||
|     def get_breadcrumb(self): | ||||
|         return SdrDeviceBreadcrumb() | ||||
|  | ||||
|     def render_devices(self): | ||||
|         def render_device(device_id, config): | ||||
|             sources = SdrService.getAllSources() | ||||
| @@ -213,6 +223,11 @@ class SdrFormControllerWithModal(SdrFormController, metaclass=ABCMeta): | ||||
|  | ||||
|  | ||||
| class SdrDeviceController(SdrFormControllerWithModal): | ||||
|     def get_breadcrumb(self) -> Breadcrumb: | ||||
|         return SdrDeviceBreadcrumb().append( | ||||
|             BreadcrumbItem(self.device["name"], "settings/sdr/{}".format(self.device_id)) | ||||
|         ) | ||||
|  | ||||
|     def getData(self): | ||||
|         return self.device | ||||
|  | ||||
| @@ -271,6 +286,9 @@ class NewSdrDeviceController(SettingsFormController): | ||||
|         self.stack.addLayer(0, id_layer) | ||||
|         self.stack.addLayer(1, self.data_layer) | ||||
|  | ||||
|     def get_breadcrumb(self) -> Breadcrumb: | ||||
|         return SdrDeviceBreadcrumb().append(BreadcrumbItem("New device", "settings/sdr/newsdr")) | ||||
|  | ||||
|     def getSections(self): | ||||
|         return [ | ||||
|             Section( | ||||
| @@ -313,6 +331,17 @@ class SdrProfileController(SdrFormControllerWithModal): | ||||
|         super().__init__(handler, request, options) | ||||
|         self.profile_id, self.profile = self._get_profile() | ||||
|  | ||||
|     def get_breadcrumb(self) -> Breadcrumb: | ||||
|         return ( | ||||
|             SdrDeviceBreadcrumb() | ||||
|             .append(BreadcrumbItem(self.device["name"], "settings/sdr/{}".format(self.device_id))) | ||||
|             .append( | ||||
|                 BreadcrumbItem( | ||||
|                     self.profile["name"], "settings/sdr/{}/profile/{}".format(self.device_id, self.profile_id) | ||||
|                 ) | ||||
|             ) | ||||
|         ) | ||||
|  | ||||
|     def getData(self): | ||||
|         return self.profile | ||||
|  | ||||
| @@ -378,6 +407,13 @@ class NewProfileController(SdrProfileController): | ||||
|         self.stack.addLayer(1, id_layer) | ||||
|         super().__init__(handler, request, options) | ||||
|  | ||||
|     def get_breadcrumb(self) -> Breadcrumb: | ||||
|         return ( | ||||
|             SdrDeviceBreadcrumb() | ||||
|             .append(BreadcrumbItem(self.device["name"], "settings/sdr/{}".format(self.device_id))) | ||||
|             .append(BreadcrumbItem("New profile", "settings/sdr/{}/newprofile".format(self.device_id))) | ||||
|         ) | ||||
|  | ||||
|     def _get_profile(self): | ||||
|         return "new", self.stack | ||||
|  | ||||
|   | ||||
| @@ -43,8 +43,3 @@ class MapController(WebpageController): | ||||
|     def indexAction(self): | ||||
|         # TODO check if we have a google maps api key first? | ||||
|         self.serve_template("map.html", **self.template_variables()) | ||||
|  | ||||
|  | ||||
| class FeatureController(WebpageController): | ||||
|     def indexAction(self): | ||||
|         self.serve_template("features.html", **self.template_variables()) | ||||
|   | ||||
| @@ -99,7 +99,6 @@ class FeatureDetector(object): | ||||
|  | ||||
|         def feature_details(name): | ||||
|             return { | ||||
|                 "description": "", | ||||
|                 "available": self.is_available(name), | ||||
|                 "requirements": {name: requirement_details(name) for name in self.get_requirements(name)}, | ||||
|             } | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| from owrx.controllers.status import StatusController | ||||
| from owrx.controllers.template import IndexController, MapController, FeatureController | ||||
| from owrx.controllers.template import IndexController, MapController | ||||
| from owrx.controllers.feature import FeatureController | ||||
| from owrx.controllers.assets import OwrxAssetsController, AprsSymbolsController, CompiledAssetsController | ||||
| from owrx.controllers.websocket import WebSocketController | ||||
| from owrx.controllers.api import ApiController | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Jakob Ketterl
					Jakob Ketterl