diff --git a/hyperglass/models/config/devices.py b/hyperglass/models/config/devices.py
index c5c091a..55d284d 100644
--- a/hyperglass/models/config/devices.py
+++ b/hyperglass/models/config/devices.py
@@ -2,7 +2,7 @@
# Standard Library
import re
-from typing import Any, Set, Dict, List, Tuple, Union, Optional
+import typing as t
from pathlib import Path
from ipaddress import IPv4Address, IPv6Address
@@ -33,7 +33,7 @@ ALL_DEVICE_TYPES = {*DRIVER_MAP.keys(), *CLASS_MAPPER.keys()}
class DirectiveOptions(HyperglassModel, extra="ignore"):
"""Per-device directive options."""
- builtins: Union[StrictBool, List[StrictStr]] = True
+ builtins: t.Union[StrictBool, t.List[StrictStr]] = True
class Device(HyperglassModelWithId, extra="allow"):
@@ -41,21 +41,21 @@ class Device(HyperglassModelWithId, extra="allow"):
id: StrictStr
name: StrictStr
- description: Optional[StrictStr]
- avatar: Optional[FilePath]
- address: Union[IPv4Address, IPv6Address, StrictStr]
- group: Optional[StrictStr]
+ description: t.Optional[StrictStr]
+ avatar: t.Optional[FilePath]
+ address: t.Union[IPv4Address, IPv6Address, StrictStr]
+ group: t.Optional[StrictStr]
credential: Credential
- proxy: Optional[Proxy]
- display_name: Optional[StrictStr]
+ proxy: t.Optional[Proxy]
+ display_name: t.Optional[StrictStr]
port: StrictInt = 22
http: HttpConfiguration = HttpConfiguration()
platform: StrictStr
- structured_output: Optional[StrictBool]
+ structured_output: t.Optional[StrictBool]
directives: Directives = Directives()
- driver: Optional[SupportedDriver]
- driver_config: Dict[str, Any] = {}
- attrs: Dict[str, str] = {}
+ driver: t.Optional[SupportedDriver]
+ driver_config: t.Dict[str, t.Any] = {}
+ attrs: t.Dict[str, str] = {}
def __init__(self, **kw) -> None:
"""Check legacy fields and ensure an `id` is set."""
@@ -70,7 +70,7 @@ class Device(HyperglassModelWithId, extra="allow"):
return str(self.address)
@staticmethod
- def _with_id(values: Dict) -> str:
+ def _with_id(values: t.Dict) -> str:
"""Generate device id & handle legacy display_name field."""
def generate_id(name: str) -> str:
@@ -94,7 +94,7 @@ class Device(HyperglassModelWithId, extra="allow"):
return {"id": device_id, "name": display_name, "display_name": None, **values}
- def export_api(self) -> Dict[str, Any]:
+ def export_api(self) -> t.Dict[str, t.Any]:
"""Export API-facing device fields."""
return {
"id": self.id,
@@ -103,7 +103,7 @@ class Device(HyperglassModelWithId, extra="allow"):
}
@property
- def directive_commands(self) -> List[str]:
+ def directive_commands(self) -> t.List[str]:
"""Get all commands associated with the device."""
return [
command
@@ -113,7 +113,7 @@ class Device(HyperglassModelWithId, extra="allow"):
]
@property
- def directive_ids(self) -> List[str]:
+ def directive_ids(self) -> t.List[str]:
"""Get all directive IDs associated with the device."""
return [directive.id for directive in self.directives]
@@ -146,7 +146,9 @@ class Device(HyperglassModelWithId, extra="allow"):
)
@validator("address")
- def validate_address(cls, value, values):
+ def validate_address(
+ cls, value: t.Union[IPv4Address, IPv6Address, str], values: t.Dict[str, t.Any]
+ ) -> t.Union[IPv4Address, IPv6Address, str]:
"""Ensure a hostname is resolvable."""
if not isinstance(value, (IPv4Address, IPv6Address)):
@@ -160,8 +162,8 @@ class Device(HyperglassModelWithId, extra="allow"):
@validator("avatar")
def validate_avatar(
- cls, value: Union[FilePath, None], values: Dict[str, Any]
- ) -> Union[FilePath, None]:
+ cls, value: t.Union[FilePath, None], values: t.Dict[str, t.Any]
+ ) -> t.Union[FilePath, None]:
"""Migrate avatar to static directory."""
if value is not None:
# Standard Library
@@ -181,7 +183,7 @@ class Device(HyperglassModelWithId, extra="allow"):
return value
@validator("platform", pre=True, always=True)
- def validate_platform(cls: "Device", value: Any, values: Dict[str, Any]) -> str:
+ def validate_platform(cls: "Device", value: t.Any, values: t.Dict[str, t.Any]) -> str:
"""Validate & rewrite device platform, set default `directives`."""
if value is None:
@@ -202,7 +204,7 @@ class Device(HyperglassModelWithId, extra="allow"):
return value
@validator("structured_output", pre=True, always=True)
- def validate_structured_output(cls, value: bool, values: Dict[str, Any]) -> bool:
+ def validate_structured_output(cls, value: bool, values: t.Dict[str, t.Any]) -> bool:
"""Validate structured output is supported on the device & set a default."""
if value is True:
@@ -221,7 +223,9 @@ class Device(HyperglassModelWithId, extra="allow"):
return value
@validator("directives", pre=True, always=True)
- def validate_directives(cls: "Device", value, values) -> "Directives":
+ def validate_directives(
+ cls: "Device", value: t.Optional[t.List[str]], values: t.Dict[str, t.Any]
+ ) -> "Directives":
"""Associate directive IDs to loaded directive objects."""
directives = use_state("directives")
@@ -234,7 +238,7 @@ class Device(HyperglassModelWithId, extra="allow"):
**{
k: v
for statement in directive_ids
- if isinstance(statement, Dict)
+ if isinstance(statement, t.Dict)
for k, v in statement.items()
}
)
@@ -253,14 +257,14 @@ class Device(HyperglassModelWithId, extra="allow"):
if directive_options.builtins is True:
# Add all builtins.
device_directives += builtins
- elif isinstance(directive_options.builtins, List):
+ elif isinstance(directive_options.builtins, t.List):
# If the user provides a list of builtin directives to include, add only those.
device_directives += builtins.matching(*directive_options.builtins)
return device_directives
@validator("driver")
- def validate_driver(cls, value: Optional[str], values: Dict) -> Dict:
+ def validate_driver(cls: "Device", value: t.Optional[str], values: t.Dict[str, t.Any]) -> str:
"""Set the correct driver and override if supported."""
return get_driver(values["platform"], value)
@@ -268,25 +272,25 @@ class Device(HyperglassModelWithId, extra="allow"):
class Devices(MultiModel, model=Device, unique_by="id"):
"""Container for all devices."""
- def __init__(self, *items: Dict[str, Any]) -> None:
+ def __init__(self: "Devices", *items: t.Dict[str, t.Any]) -> None:
"""Generate IDs prior to validation."""
with_id = (Device._with_id(item) for item in items)
super().__init__(*with_id)
- def export_api(self) -> List[Dict[str, Any]]:
+ def export_api(self: "Devices") -> t.List[t.Dict[str, t.Any]]:
"""Export API-facing device fields."""
return [d.export_api() for d in self]
- def valid_id_or_name(self, value: str) -> bool:
+ def valid_id_or_name(self: "Devices", value: str) -> bool:
"""Determine if a value is a valid device name or ID."""
for device in self:
if value == device.id or value == device.name:
return True
return False
- def directive_plugins(self) -> Dict[Path, Tuple[StrictStr]]:
+ def directive_plugins(self: "Devices") -> t.Dict[Path, t.Tuple[StrictStr]]:
"""Get a mapping of plugin paths to associated directive IDs."""
- result: Dict[Path, Set[StrictStr]] = {}
+ result: t.Dict[Path, t.Set[StrictStr]] = {}
# Unique set of all directives.
directives = {directive for device in self for directive in device.directives}
# Unique set of all plugin file names.
@@ -301,9 +305,8 @@ class Devices(MultiModel, model=Device, unique_by="id"):
# Convert the directive set to a tuple.
return {k: tuple(v) for k, v in result.items()}
- def frontend(self) -> List[Dict[str, Any]]:
+ def frontend(self: "Devices") -> t.List[t.Dict[str, t.Any]]:
"""Export grouped devices for UIParameters."""
- params = use_state("params")
groups = {device.group for device in self}
return [
{
@@ -317,7 +320,7 @@ class Devices(MultiModel, model=Device, unique_by="id"):
if device.avatar is not None
else None,
"description": device.description,
- "directives": [d.frontend(params) for d in device.directives],
+ "directives": [d.frontend() for d in device.directives],
}
for device in self
if device.group == group
diff --git a/hyperglass/models/config/params.py b/hyperglass/models/config/params.py
index 681ef49..1c00bd3 100644
--- a/hyperglass/models/config/params.py
+++ b/hyperglass/models/config/params.py
@@ -143,10 +143,6 @@ class Params(ParamsPublic, HyperglassModel):
"""Get all validated external common plugins as Path objects."""
return tuple(Path(p) for p in self.plugins)
- def content_params(self) -> Dict[str, Any]:
- """Export content-specific parameters."""
- return self.dict(include={"primary_asn", "org_name", "site_title", "site_description"})
-
def frontend(self) -> Dict[str, Any]:
"""Export UI-specific parameters."""
diff --git a/hyperglass/models/directive.py b/hyperglass/models/directive.py
index 03fb6b8..4c1b980 100644
--- a/hyperglass/models/directive.py
+++ b/hyperglass/models/directive.py
@@ -26,10 +26,6 @@ from hyperglass.exceptions.private import InputValidationError
from .main import MultiModel, HyperglassModel, HyperglassUniqueModel
from .fields import Action
-if t.TYPE_CHECKING:
- # Local
- from .config.params import Params
-
IPv4PrefixLength = conint(ge=0, le=32)
IPv6PrefixLength = conint(ge=0, le=128)
IPNetwork = t.Union[IPv4Network, IPv6Network]
@@ -277,7 +273,7 @@ class Directive(HyperglassUniqueModel, unique_by=("id", "table_output")):
return [str(f) for f in matching_plugins]
return []
- def frontend(self: "Directive", params: "Params") -> t.Dict[str, t.Any]:
+ def frontend(self: "Directive") -> t.Dict[str, t.Any]:
"""Prepare a representation of the directive for the UI."""
value = {
@@ -291,11 +287,7 @@ class Directive(HyperglassUniqueModel, unique_by=("id", "table_output")):
if self.info is not None:
with self.info.open() as md:
- value["info"] = {
- "enable": True,
- "params": params.content_params(),
- "content": md.read(),
- }
+ value["info"] = md.read()
if self.field.is_select:
value["options"] = [o.export_dict() for o in self.field.options if o is not None]
diff --git a/hyperglass/models/ui.py b/hyperglass/models/ui.py
index a727681..c30f4af 100644
--- a/hyperglass/models/ui.py
+++ b/hyperglass/models/ui.py
@@ -17,14 +17,6 @@ Alignment = Union[Literal["left"], Literal["center"], Literal["right"], None]
StructuredDataField = Tuple[str, str, Alignment]
-class UIDirectiveInfo(HyperglassModel):
- """UI: Directive Info."""
-
- enable: StrictBool
- params: Dict[str, str]
- content: StrictStr
-
-
class UIDirective(HyperglassModel):
"""UI: Directive."""
@@ -33,7 +25,7 @@ class UIDirective(HyperglassModel):
field_type: StrictStr
groups: List[StrictStr]
description: StrictStr
- info: Optional[UIDirectiveInfo] = None
+ info: Optional[str] = None
options: Optional[List[Dict[str, Any]]]
diff --git a/hyperglass/ui/components/help/modal.tsx b/hyperglass/ui/components/help/modal.tsx
index 56c9fac..99dc468 100644
--- a/hyperglass/ui/components/help/modal.tsx
+++ b/hyperglass/ui/components/help/modal.tsx
@@ -11,16 +11,15 @@ import {
} from '@chakra-ui/react';
import { DynamicIcon, Markdown } from '~/components';
import { useColorValue } from '~/context';
-import { isQueryContent } from '~/types';
import type { THelpModal } from './types';
export const HelpModal = (props: THelpModal): JSX.Element => {
- const { visible, item, name, ...rest } = props;
+ const { visible, item, name, title, ...rest } = props;
const { isOpen, onOpen, onClose } = useDisclosure();
const bg = useColorValue('whiteSolid.50', 'blackSolid.800');
const color = useColorValue('black', 'white');
- if (!isQueryContent(item)) {
+ if (item === null) {
return <>>;
}
return (
@@ -33,19 +32,19 @@ export const HelpModal = (props: THelpModal): JSX.Element => {
minW={3}
size="md"
variant="link"
- icon={}
onClick={onOpen}
colorScheme="blue"
aria-label={`${name}_help`}
+ icon={}
/>
- {item.params.title}
+ {title}
-
+
diff --git a/hyperglass/ui/components/help/types.ts b/hyperglass/ui/components/help/types.ts
index aeefec8..23572d6 100644
--- a/hyperglass/ui/components/help/types.ts
+++ b/hyperglass/ui/components/help/types.ts
@@ -1,8 +1,8 @@
import type { ModalContentProps } from '@chakra-ui/react';
-import type { QueryContent } from '~/types';
-export interface THelpModal extends ModalContentProps {
- item: QueryContent | null;
+export interface THelpModal extends Omit {
+ title: string | null;
+ item: string | null;
name: string;
visible: boolean;
}
diff --git a/hyperglass/ui/components/lookingGlass.tsx b/hyperglass/ui/components/lookingGlass.tsx
index 9e5e944..0f45b40 100644
--- a/hyperglass/ui/components/lookingGlass.tsx
+++ b/hyperglass/ui/components/lookingGlass.tsx
@@ -189,9 +189,10 @@ export const LookingGlass = (): JSX.Element => {
label={web.text.queryType}
labelAddOn={
}
>
diff --git a/hyperglass/ui/types/config.ts b/hyperglass/ui/types/config.ts
index 63ba68a..56d6181 100644
--- a/hyperglass/ui/types/config.ts
+++ b/hyperglass/ui/types/config.ts
@@ -112,7 +112,7 @@ type _DirectiveBase = {
field_type: 'text' | 'select' | null;
description: string;
groups: string[];
- info: _QueryContent | null;
+ info: string | null;
};
type _DirectiveOption = {
@@ -136,18 +136,6 @@ interface _Device {
description: string | null;
}
-interface _QueryContent {
- content: string;
- enable: boolean;
- params: {
- primary_asn: _Config['primary_asn'];
- org_name: _Config['org_name'];
- site_title: _Config['site_title'];
- title: string;
- [k: string]: string;
- };
-}
-
interface _Content {
credit: string;
greeting: string;
@@ -196,7 +184,6 @@ export interface Favicon {
export type Config = CamelCasedPropertiesDeep<_ConfigDeep> & CamelCasedProperties<_ConfigShallow>;
export type ThemeConfig = CamelCasedProperties<_ThemeConfig>;
export type Content = CamelCasedProperties<_Content>;
-export type QueryContent = CamelCasedPropertiesDeep<_QueryContent>;
export type Device = CamelCasedPropertiesDeep<_Device>;
export type DeviceGroup = CamelCasedPropertiesDeep<_DeviceGroup>;
export type Directive = CamelCasedPropertiesDeep<_Directive>;
diff --git a/hyperglass/ui/types/guards.ts b/hyperglass/ui/types/guards.ts
index ad3dc1d..ed2c4e3 100644
--- a/hyperglass/ui/types/guards.ts
+++ b/hyperglass/ui/types/guards.ts
@@ -1,5 +1,5 @@
import type { FormData, TStringTableData, TQueryResponseString } from './data';
-import type { QueryContent, DirectiveSelect, Directive } from './config';
+import type { DirectiveSelect, Directive } from './config';
export function isString(a: unknown): a is string {
return typeof a === 'string';
@@ -25,10 +25,6 @@ export function isStringOutput(data: unknown): data is TQueryResponseString {
);
}
-export function isQueryContent(content: unknown): content is QueryContent {
- return isObject(content) && 'content' in content;
-}
-
/**
* Determine if a form field name is a valid form key name.
*/