introduce breadcrumbs in the web config

This commit is contained in:
Jakob Ketterl 2021-04-18 17:49:13 +02:00
parent 1968e15237
commit e8cf014903
17 changed files with 139 additions and 16 deletions

View File

@ -152,3 +152,7 @@ h1 {
.scheduler-static-time-inputs > select { .scheduler-static-time-inputs > select {
flex: 1 0 auto; flex: 1 0 auto;
} }
.breadcrumb {
margin-top: .5rem;
}

View File

@ -10,6 +10,7 @@
</HEAD><BODY> </HEAD><BODY>
${header} ${header}
<div class="container"> <div class="container">
${breadcrumb}
<h1>OpenWebRX Feature Report</h1> <h1>OpenWebRX Feature Report</h1>
<table class="features table"> <table class="features table">
<tr> <tr>
@ -19,5 +20,6 @@
<th>Available</th> <th>Available</th>
</tr> </tr>
</table> </table>
${breadcrumb}
</div> </div>
</BODY></HTML> </BODY></HTML>

View File

@ -13,8 +13,7 @@ $(function(){
}); });
$table.append( $table.append(
'<tr>' + '<tr>' +
'<td colspan=2>' + name + '</td>' + '<td colspan=3>' + name + '</td>' +
'<td>' + converter.makeHtml(details.description) + '</td>' +
'<td>' + (details.available ? 'YES' : 'NO') + '</td>' + '<td>' + (details.available ? 'YES' : 'NO') + '</td>' +
'</tr>' + '</tr>' +
requirements.join("") requirements.join("")

View File

@ -11,6 +11,7 @@
<body> <body>
${header} ${header}
<div class="container"> <div class="container">
${breadcrumb}
<div class="row"> <div class="row">
<h1 class="col-12">Bookmarks</h1> <h1 class="col-12">Bookmarks</h1>
</div> </div>
@ -24,6 +25,7 @@ ${header}
<button type="button" class="btn btn-primary bookmark-add">Add a new bookmark</button> <button type="button" class="btn btn-primary bookmark-add">Add a new bookmark</button>
</div> </div>
</div> </div>
${breadcrumb}
</div> </div>
<div class="modal" id="deleteModal" tabindex="-1" role="dialog"> <div class="modal" id="deleteModal" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document"> <div class="modal-dialog" role="document">

View File

@ -11,10 +11,12 @@
<body> <body>
${header} ${header}
<div class="container"> <div class="container">
${breadcrumb}
<div class="row"> <div class="row">
<h1 class="col-12">${title}</h1> <h1 class="col-12">${title}</h1>
</div> </div>
${content} ${content}
${breadcrumb}
</div> </div>
${modal} ${modal}
</body> </body>

42
owrx/breadcrumb.py Normal file
View 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

View 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())

View File

@ -2,6 +2,7 @@ from owrx.config import Config
from owrx.controllers.admin import AuthorizationMixin from owrx.controllers.admin import AuthorizationMixin
from owrx.controllers.template import WebpageController from owrx.controllers.template import WebpageController
from owrx.form.error import FormError from owrx.form.error import FormError
from owrx.breadcrumb import Breadcrumb, BreadcrumbItem, BreadcrumbMixin
from abc import ABCMeta, abstractmethod from abc import ABCMeta, abstractmethod
from urllib.parse import parse_qs from urllib.parse import parse_qs
@ -50,7 +51,7 @@ class SettingsController(AuthorizationMixin, WebpageController):
self.serve_template("settings.html", **self.template_variables()) 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): def __init__(self, handler, request, options):
super().__init__(handler, request, options) super().__init__(handler, request, options)
self.errors = {} self.errors = {}
@ -144,3 +145,9 @@ class SettingsFormController(AuthorizationMixin, WebpageController, metaclass=AB
def buildModal(self): def buildModal(self):
return "" return ""
class SettingsBreadcrumb(Breadcrumb):
def __init__(self):
super().__init__([])
self.append(BreadcrumbItem("Settings", "settings"))

View File

@ -1,11 +1,16 @@
from owrx.controllers.settings import SettingsFormController, Section from owrx.controllers.settings import SettingsFormController, Section
from owrx.form import CheckboxInput, ServicesCheckboxInput from owrx.form import CheckboxInput, ServicesCheckboxInput
from owrx.breadcrumb import Breadcrumb, BreadcrumbItem
from owrx.controllers.settings import SettingsBreadcrumb
class BackgroundDecodingController(SettingsFormController): class BackgroundDecodingController(SettingsFormController):
def getTitle(self): def getTitle(self):
return "Background decoding" return "Background decoding"
def get_breadcrumb(self) -> Breadcrumb:
return SettingsBreadcrumb().append(BreadcrumbItem("Background decoding", "settings/backgrounddecoding"))
def getSections(self): def getSections(self):
return [ return [
Section( Section(

View File

@ -1,7 +1,9 @@
from owrx.controllers.template import WebpageController from owrx.controllers.template import WebpageController
from owrx.controllers.admin import AuthorizationMixin from owrx.controllers.admin import AuthorizationMixin
from owrx.controllers.settings import SettingsBreadcrumb
from owrx.bookmarks import Bookmark, Bookmarks from owrx.bookmarks import Bookmark, Bookmarks
from owrx.modes import Modes from owrx.modes import Modes
from owrx.breadcrumb import Breadcrumb, BreadcrumbItem, BreadcrumbMixin
import json import json
import math import math
@ -10,7 +12,10 @@ import logging
logger = logging.getLogger(__name__) 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): def template_variables(self):
variables = super().template_variables() variables = super().template_variables()
variables["bookmarks"] = self.render_table() variables["bookmarks"] = self.render_table()

View File

@ -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 import CheckboxInput, NumberInput, DropdownInput, Js8ProfileCheckboxInput, MultiCheckboxInput, Option
from owrx.form.wfm import WfmTauValues from owrx.form.wfm import WfmTauValues
from owrx.form.wsjt import Q65ModeMatrix, WsjtDecodingDepthsInput from owrx.form.wsjt import Q65ModeMatrix, WsjtDecodingDepthsInput
from owrx.wsjt import Fst4Profile, Fst4wProfile from owrx.wsjt import Fst4Profile, Fst4wProfile
from owrx.breadcrumb import Breadcrumb, BreadcrumbItem
class DecodingSettingsController(SettingsFormController): class DecodingSettingsController(SettingsFormController):
def getTitle(self): def getTitle(self):
return "Demodulation and decoding" return "Demodulation and decoding"
def get_breadcrumb(self) -> Breadcrumb:
return SettingsBreadcrumb().append(BreadcrumbItem("Demodulation and decoding", "settings/decoding"))
def getSections(self): def getSections(self):
return [ return [
Section( Section(

View File

@ -14,6 +14,8 @@ from owrx.form.receiverid import ReceiverKeysConverter
from owrx.form.gfx import AvatarInput, TopPhotoInput from owrx.form.gfx import AvatarInput, TopPhotoInput
from owrx.form.device import WaterfallLevelsInput, WaterfallAutoLevelsInput from owrx.form.device import WaterfallLevelsInput, WaterfallAutoLevelsInput
from owrx.waterfall import WaterfallOptions from owrx.waterfall import WaterfallOptions
from owrx.breadcrumb import Breadcrumb, BreadcrumbItem
from owrx.controllers.settings import SettingsBreadcrumb
import shutil import shutil
import os import os
from glob import glob from glob import glob
@ -27,6 +29,9 @@ class GeneralSettingsController(SettingsFormController):
def getTitle(self): def getTitle(self):
return "General Settings" return "General Settings"
def get_breadcrumb(self) -> Breadcrumb:
return SettingsBreadcrumb().append(BreadcrumbItem("General Settings", "settings/general"))
def getSections(self): def getSections(self):
return [ return [
Section( Section(

View File

@ -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.converter import OptionalConverter
from owrx.form.aprs import AprsBeaconSymbols, AprsAntennaDirections from owrx.form.aprs import AprsBeaconSymbols, AprsAntennaDirections
from owrx.form import TextInput, CheckboxInput, DropdownInput, NumberInput from owrx.form import TextInput, CheckboxInput, DropdownInput, NumberInput
from owrx.breadcrumb import Breadcrumb, BreadcrumbItem
class ReportingController(SettingsFormController): class ReportingController(SettingsFormController):
def getTitle(self): 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): def getSections(self):
return [ return [

View File

@ -4,16 +4,23 @@ from owrx.controllers.settings import SettingsFormController
from owrx.source import SdrDeviceDescription, SdrDeviceDescriptionMissing, SdrClientClass from owrx.source import SdrDeviceDescription, SdrDeviceDescriptionMissing, SdrClientClass
from owrx.config import Config from owrx.config import Config
from owrx.connection import OpenWebRxReceiverClient 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 urllib.parse import quote, unquote
from owrx.sdr import SdrService from owrx.sdr import SdrService
from owrx.form import TextInput, DropdownInput, Option from owrx.form import TextInput, DropdownInput, Option
from owrx.form.validator import RequiredValidator from owrx.form.validator import RequiredValidator
from owrx.property import PropertyLayer, PropertyStack from owrx.property import PropertyLayer, PropertyStack
from owrx.breadcrumb import BreadcrumbMixin, Breadcrumb, BreadcrumbItem
from abc import ABCMeta, abstractmethod 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): def template_variables(self):
variables = super().template_variables() variables = super().template_variables()
variables["content"] = self.render_devices() variables["content"] = self.render_devices()
@ -21,6 +28,9 @@ class SdrDeviceListController(AuthorizationMixin, WebpageController):
variables["modal"] = "" variables["modal"] = ""
return variables return variables
def get_breadcrumb(self):
return SdrDeviceBreadcrumb()
def render_devices(self): def render_devices(self):
def render_device(device_id, config): def render_device(device_id, config):
sources = SdrService.getAllSources() sources = SdrService.getAllSources()
@ -213,6 +223,11 @@ class SdrFormControllerWithModal(SdrFormController, metaclass=ABCMeta):
class SdrDeviceController(SdrFormControllerWithModal): class SdrDeviceController(SdrFormControllerWithModal):
def get_breadcrumb(self) -> Breadcrumb:
return SdrDeviceBreadcrumb().append(
BreadcrumbItem(self.device["name"], "settings/sdr/{}".format(self.device_id))
)
def getData(self): def getData(self):
return self.device return self.device
@ -271,6 +286,9 @@ class NewSdrDeviceController(SettingsFormController):
self.stack.addLayer(0, id_layer) self.stack.addLayer(0, id_layer)
self.stack.addLayer(1, self.data_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): def getSections(self):
return [ return [
Section( Section(
@ -313,6 +331,17 @@ class SdrProfileController(SdrFormControllerWithModal):
super().__init__(handler, request, options) super().__init__(handler, request, options)
self.profile_id, self.profile = self._get_profile() 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): def getData(self):
return self.profile return self.profile
@ -378,6 +407,13 @@ class NewProfileController(SdrProfileController):
self.stack.addLayer(1, id_layer) self.stack.addLayer(1, id_layer)
super().__init__(handler, request, options) 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): def _get_profile(self):
return "new", self.stack return "new", self.stack

View File

@ -43,8 +43,3 @@ class MapController(WebpageController):
def indexAction(self): def indexAction(self):
# TODO check if we have a google maps api key first? # TODO check if we have a google maps api key first?
self.serve_template("map.html", **self.template_variables()) self.serve_template("map.html", **self.template_variables())
class FeatureController(WebpageController):
def indexAction(self):
self.serve_template("features.html", **self.template_variables())

View File

@ -99,7 +99,6 @@ class FeatureDetector(object):
def feature_details(name): def feature_details(name):
return { return {
"description": "",
"available": self.is_available(name), "available": self.is_available(name),
"requirements": {name: requirement_details(name) for name in self.get_requirements(name)}, "requirements": {name: requirement_details(name) for name in self.get_requirements(name)},
} }

View File

@ -1,5 +1,6 @@
from owrx.controllers.status import StatusController 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.assets import OwrxAssetsController, AprsSymbolsController, CompiledAssetsController
from owrx.controllers.websocket import WebSocketController from owrx.controllers.websocket import WebSocketController
from owrx.controllers.api import ApiController from owrx.controllers.api import ApiController