diff --git a/hyperglass/configuration/main.py b/hyperglass/configuration/main.py index 7875887..06e0d28 100644 --- a/hyperglass/configuration/main.py +++ b/hyperglass/configuration/main.py @@ -141,7 +141,7 @@ set_log_level(logger=log, debug=user_config.get("debug", True)) # Map imported user configuration to expected schema. log.debug("Unvalidated configuration from {}: {}", CONFIG_MAIN, user_config) -params: Params = validate_config(config=user_config, importer=Params) +params = validate_config(config=user_config, importer=Params) # Re-evaluate debug state after config is validated log_level = current_log_level(log) diff --git a/hyperglass/configuration/validation.py b/hyperglass/configuration/validation.py index ddb62f6..9f09dde 100644 --- a/hyperglass/configuration/validation.py +++ b/hyperglass/configuration/validation.py @@ -3,38 +3,20 @@ Some validations need to occur across multiple config files. """ # Standard Library -from typing import Dict, List, Union, Callable +from typing import Any, Dict, List, Union, TypeVar # Third Party from pydantic import ValidationError # Project -from hyperglass.models import HyperglassModel -from hyperglass.constants import TRANSPORT_REST, SUPPORTED_STRUCTURED_OUTPUT -from hyperglass.models.commands import Commands -from hyperglass.exceptions.private import ConfigError, ConfigInvalid +from hyperglass.exceptions.private import ConfigInvalid + +Importer = TypeVar("Importer") -def validate_nos_commands(all_nos: List[str], commands: Commands) -> bool: - """Ensure defined devices have associated commands.""" - custom_commands = commands.dict().keys() - - for nos in all_nos: - valid = False - if nos in (*SUPPORTED_STRUCTURED_OUTPUT, *TRANSPORT_REST, *custom_commands): - valid = True - - if not valid: - raise ConfigError( - '"{nos}" is used on a device, ' - + 'but no command profile for "{nos}" is defined.', - nos=nos, - ) - - return True - - -def validate_config(config: Union[Dict, List], importer: Callable) -> HyperglassModel: +def validate_config( + config: Union[Dict[str, Any], List[Any]], importer: Importer +) -> Importer: """Validate a config dict against a model.""" validated = None try: diff --git a/hyperglass/models/__init__.py b/hyperglass/models/__init__.py index 98929cf..3a064f0 100644 --- a/hyperglass/models/__init__.py +++ b/hyperglass/models/__init__.py @@ -1,4 +1,6 @@ """All Data Models used by hyperglass.""" # Local -from .main import HyperglassModel, HyperglassModelExtra +from .main import HyperglassModel + +__all__ = ("HyperglassModel",) diff --git a/hyperglass/models/commands/__init__.py b/hyperglass/models/commands/__init__.py index 7a49b0b..b7a1699 100644 --- a/hyperglass/models/commands/__init__.py +++ b/hyperglass/models/commands/__init__.py @@ -5,7 +5,7 @@ from .frr import FRRCommands from .bird import BIRDCommands from .tnsr import TNSRCommands from .vyos import VyosCommands -from ..main import HyperglassModelExtra +from ..main import HyperglassModel from .common import CommandGroup from .huawei import HuaweiCommands from .juniper import JuniperCommands @@ -34,7 +34,7 @@ _NOS_MAP = { } -class Commands(HyperglassModelExtra): +class Commands(HyperglassModel, extra="allow", validate_all=False): """Base class for command definitions.""" arista_eos: CommandGroup = AristaEOSCommands() @@ -69,8 +69,3 @@ class Commands(HyperglassModelExtra): nos_cmds = nos_cmd_set(**cmds) setattr(obj, nos, nos_cmds) return obj - - class Config: - """Override pydantic config.""" - - validate_all = False diff --git a/hyperglass/models/commands/common.py b/hyperglass/models/commands/common.py index 347efd2..8795d78 100644 --- a/hyperglass/models/commands/common.py +++ b/hyperglass/models/commands/common.py @@ -4,7 +4,7 @@ from pydantic import StrictStr # Local -from ..main import HyperglassModel, HyperglassModelExtra +from ..main import HyperglassModel class CommandSet(HyperglassModel): @@ -17,7 +17,7 @@ class CommandSet(HyperglassModel): traceroute: StrictStr -class CommandGroup(HyperglassModelExtra): +class CommandGroup(HyperglassModel, extra="allow"): """Validation model for all commands.""" ipv4_default: CommandSet diff --git a/hyperglass/models/config/credential.py b/hyperglass/models/config/credential.py index 364fc4e..3a28eda 100644 --- a/hyperglass/models/config/credential.py +++ b/hyperglass/models/config/credential.py @@ -7,12 +7,12 @@ from typing import Optional from pydantic import FilePath, SecretStr, StrictStr, constr, root_validator # Local -from ..main import HyperglassModelExtra +from ..main import HyperglassModel Methods = constr(regex=r"(password|unencrypted_key|encrypted_key)") -class Credential(HyperglassModelExtra): +class Credential(HyperglassModel, extra="allow"): """Model for per-credential config in devices.yaml.""" username: StrictStr diff --git a/hyperglass/models/config/devices.py b/hyperglass/models/config/devices.py index 8bd1ff1..256007f 100644 --- a/hyperglass/models/config/devices.py +++ b/hyperglass/models/config/devices.py @@ -26,7 +26,7 @@ from hyperglass.models.commands.generic import Directive # Local from .ssl import Ssl -from ..main import HyperglassModel, HyperglassModelExtra +from ..main import HyperglassModel from .proxy import Proxy from .params import Params from ..fields import SupportedDriver @@ -34,7 +34,7 @@ from .network import Network from .credential import Credential -class Device(HyperglassModelExtra): +class Device(HyperglassModel, extra="allow"): """Validation model for per-router config in devices.yaml.""" _id: StrictStr = PrivateAttr() @@ -222,7 +222,7 @@ class Device(HyperglassModelExtra): return get_driver(values["nos"], value) -class Devices(HyperglassModelExtra): +class Devices(HyperglassModel, extra="allow"): """Validation model for device configurations.""" _ids: List[StrictStr] = [] @@ -290,7 +290,7 @@ class Devices(HyperglassModelExtra): "directives": [c.frontend(params) for c in device.commands], } for device in self.objects - if device.network.display_name in names + if device.network.display_name == name ], } for name in names diff --git a/hyperglass/models/config/logging.py b/hyperglass/models/config/logging.py index db718eb..ee89bb9 100644 --- a/hyperglass/models/config/logging.py +++ b/hyperglass/models/config/logging.py @@ -24,7 +24,7 @@ from pydantic import ( from hyperglass.constants import __version__ # Local -from ..main import HyperglassModel, HyperglassModelExtra +from ..main import HyperglassModel HttpAuthMode = constr(regex=r"(basic|api_key)") HttpProvider = constr(regex=r"(msteams|slack|generic)") @@ -55,7 +55,7 @@ class HttpAuth(HyperglassModel): return (self.username, self.password.get_secret_value()) -class Http(HyperglassModelExtra): +class Http(HyperglassModel, extra="allow"): """HTTP logging parameters.""" enable: StrictBool = True diff --git a/hyperglass/models/config/params.py b/hyperglass/models/config/params.py index 8f7ae4d..d335f76 100644 --- a/hyperglass/models/config/params.py +++ b/hyperglass/models/config/params.py @@ -191,7 +191,7 @@ class Params(ParamsPublic, HyperglassModel): def frontend(self) -> Dict[str, Any]: """Export UI-specific parameters.""" - return self.dict( + return self.export_dict( include={ "cache": {"show_text", "timeout"}, "debug": ..., diff --git a/hyperglass/models/config/vrf.py b/hyperglass/models/config/vrf.py index 56d1800..e4c8fab 100644 --- a/hyperglass/models/config/vrf.py +++ b/hyperglass/models/config/vrf.py @@ -22,7 +22,7 @@ from pydantic import ( from hyperglass.log import log # Local -from ..main import HyperglassModel, HyperglassModelExtra +from ..main import HyperglassModel ACLAction = constr(regex=r"permit|deny") AddressFamily = Union[Literal[4], Literal[6]] @@ -125,7 +125,7 @@ class AccessList6(HyperglassModel): return value -class InfoConfigParams(HyperglassModelExtra): +class InfoConfigParams(HyperglassModel, extra="allow"): """Validation model for per-help params.""" title: Optional[StrictStr] @@ -197,7 +197,7 @@ class Info(HyperglassModel): } -class DeviceVrf4(HyperglassModelExtra): +class DeviceVrf4(HyperglassModel, extra="allow"): """Validation model for IPv4 AFI definitions.""" source_address: IPv4Address @@ -205,7 +205,7 @@ class DeviceVrf4(HyperglassModelExtra): force_cidr: StrictBool = True -class DeviceVrf6(HyperglassModelExtra): +class DeviceVrf6(HyperglassModel, extra="allow"): """Validation model for IPv6 AFI definitions.""" source_address: IPv6Address diff --git a/hyperglass/models/main.py b/hyperglass/models/main.py index 12eaae1..0c1f171 100644 --- a/hyperglass/models/main.py +++ b/hyperglass/models/main.py @@ -2,51 +2,55 @@ # Standard Library import re -from typing import Type, TypeVar +from pathlib import Path # Third Party -from pydantic import HttpUrl, BaseModel +from pydantic import HttpUrl, BaseModel, BaseConfig # Project +from hyperglass.log import log from hyperglass.util import snake_to_camel -def clean_name(_name: str) -> str: - """Remove unsupported characters from field names. - - Converts any "desirable" seperators to underscore, then removes all - characters that are unsupported in Python class variable names. - Also removes leading numbers underscores. - """ - _replaced = re.sub(r"[\-|\.|\@|\~|\:\/|\s]", "_", _name) - _scrubbed = "".join(re.findall(r"([a-zA-Z]\w+|\_+)", _replaced)) - return _scrubbed.lower() - - -AsUIModel = TypeVar("AsUIModel", bound="BaseModel") - - class HyperglassModel(BaseModel): """Base model for all hyperglass configuration models.""" - class Config: - """Pydantic model configuration. - - See https://pydantic-docs.helpmanual.io/usage/model_config - """ + class Config(BaseConfig): + """Pydantic model configuration.""" validate_all = True extra = "forbid" validate_assignment = True - alias_generator = clean_name - json_encoders = {HttpUrl: lambda v: str(v)} + allow_population_by_field_name = True + json_encoders = {HttpUrl: lambda v: str(v), Path: str} + + @classmethod + def alias_generator(cls: "HyperglassModel", field: str) -> str: + """Remove unsupported characters from field names. + + Converts any "desirable" seperators to underscore, then removes all + characters that are unsupported in Python class variable names. + Also removes leading numbers underscores. + """ + _replaced = re.sub(r"[\-|\.|\@|\~|\:\/|\s]", "_", field) + _scrubbed = "".join(re.findall(r"([a-zA-Z]\w+|\_+)", _replaced)) + snake_field = _scrubbed.lower() + if snake_field != field: + log.debug( + "Model field '{}.{}' was converted from {} to {}", + cls.__module__, + snake_field, + repr(field), + repr(snake_field), + ) + return snake_to_camel(snake_field) def export_json(self, *args, **kwargs): """Return instance as JSON.""" - export_kwargs = {"by_alias": True, "exclude_unset": False} + export_kwargs = {"by_alias": False, "exclude_unset": False} - for key in export_kwargs.keys(): + for key in kwargs.keys(): export_kwargs.pop(key, None) return self.json(*args, **export_kwargs, **kwargs) @@ -54,9 +58,9 @@ class HyperglassModel(BaseModel): def export_dict(self, *args, **kwargs): """Return instance as dictionary.""" - export_kwargs = {"by_alias": True, "exclude_unset": False} + export_kwargs = {"by_alias": False, "exclude_unset": False} - for key in export_kwargs.keys(): + for key in kwargs.keys(): export_kwargs.pop(key, None) return self.dict(*args, **export_kwargs, **kwargs) @@ -71,34 +75,10 @@ class HyperglassModel(BaseModel): import yaml export_kwargs = { - "by_alias": kwargs.pop("by_alias", True), - "exclude_unset": kwargs.pop("by_alias", False), + "by_alias": kwargs.pop("by_alias", False), + "exclude_unset": kwargs.pop("exclude_unset", False), } return yaml.safe_dump( json.loads(self.export_json(**export_kwargs)), *args, **kwargs ) - - -class HyperglassModelExtra(HyperglassModel): - """Model for hyperglass configuration models with dynamic fields.""" - - class Config: - """Pydantic model configuration.""" - - extra = "allow" - - -class HyperglassUIModel(HyperglassModel): - """Base class for UI configuration parameters.""" - - class Config: - """Pydantic model configuration.""" - - alias_generator = snake_to_camel - allow_population_by_field_name = True - - -def as_ui_model(name: str, model: Type[AsUIModel]) -> Type[AsUIModel]: - """Override a model's configuration to confirm to a UI model.""" - return type(name, (model, HyperglassUIModel), {}) diff --git a/hyperglass/models/ui.py b/hyperglass/models/ui.py index 823e961..d6466ce 100644 --- a/hyperglass/models/ui.py +++ b/hyperglass/models/ui.py @@ -7,7 +7,7 @@ from typing import Any, Dict, List, Tuple, Union, Literal, Optional from pydantic import StrictStr, StrictBool # Local -from .main import HyperglassUIModel, as_ui_model +from .main import HyperglassModel from .config.web import WebPublic from .config.cache import CachePublic from .config.params import ParamsPublic @@ -16,12 +16,8 @@ from .config.messages import Messages Alignment = Union[Literal["left"], Literal["center"], Literal["right"], None] StructuredDataField = Tuple[str, str, Alignment] -CacheUI = as_ui_model("CacheUI", CachePublic) -WebUI = as_ui_model("WebUI", WebPublic) -MessagesUI = as_ui_model("MessagesUI", Messages) - -class UIDirectiveInfo(HyperglassUIModel): +class UIDirectiveInfo(HyperglassModel): """UI: Directive Info.""" enable: StrictBool @@ -29,7 +25,7 @@ class UIDirectiveInfo(HyperglassUIModel): content: StrictStr -class UIDirective(HyperglassUIModel): +class UIDirective(HyperglassModel): """UI: Directive.""" id: StrictStr @@ -41,7 +37,7 @@ class UIDirective(HyperglassUIModel): options: Optional[List[Dict[str, Any]]] -class UILocation(HyperglassUIModel): +class UILocation(HyperglassModel): """UI: Location (Device).""" id: StrictStr @@ -50,26 +46,26 @@ class UILocation(HyperglassUIModel): directives: List[UIDirective] = [] -class UINetwork(HyperglassUIModel): +class UINetwork(HyperglassModel): """UI: Network.""" display_name: StrictStr locations: List[UILocation] = [] -class UIContent(HyperglassUIModel): +class UIContent(HyperglassModel): """UI: Content.""" credit: StrictStr greeting: StrictStr -class UIParameters(HyperglassUIModel, ParamsPublic): +class UIParameters(ParamsPublic, HyperglassModel): """UI Configuration Parameters.""" - cache: CacheUI - web: WebUI - messages: MessagesUI + cache: CachePublic + web: WebPublic + messages: Messages version: StrictStr networks: List[UINetwork] = [] parsed_data_fields: Tuple[StructuredDataField, ...] diff --git a/hyperglass/models/webhook.py b/hyperglass/models/webhook.py index a61e273..1b69882 100644 --- a/hyperglass/models/webhook.py +++ b/hyperglass/models/webhook.py @@ -11,7 +11,7 @@ from pydantic import StrictStr, root_validator from hyperglass.log import log # Local -from .main import HyperglassModel, HyperglassModelExtra +from .main import HyperglassModel _WEBHOOK_TITLE = "hyperglass received a valid query with the following data" _ICON_URL = "https://res.cloudinary.com/hyperglass/image/upload/v1593192484/icon.png" @@ -39,7 +39,7 @@ class WebhookHeaders(HyperglassModel): } -class WebhookNetwork(HyperglassModelExtra): +class WebhookNetwork(HyperglassModel, extra="allow"): """Webhook data model.""" prefix: StrictStr = "Unknown" diff --git a/hyperglass/ui/components/footer/button.tsx b/hyperglass/ui/components/footer/button.tsx index 231a7d8..ae2a238 100644 --- a/hyperglass/ui/components/footer/button.tsx +++ b/hyperglass/ui/components/footer/button.tsx @@ -4,13 +4,13 @@ import { Markdown } from '~/components'; import { useColorValue, useBreakpointValue, useConfig } from '~/context'; import { useOpposingColor, useStrf } from '~/hooks'; -import type { IConfig } from '~/types'; +import type { Config } from '~/types'; import type { TFooterButton } from './types'; /** * Filter the configuration object based on values that are strings for formatting. */ -function getConfigFmt(config: IConfig): Record { +function getConfigFmt(config: Config): Record { const fmt = {} as Record; for (const [k, v] of Object.entries(config)) { if (typeof v === 'string') { diff --git a/hyperglass/ui/components/footer/footer.tsx b/hyperglass/ui/components/footer/footer.tsx index 9da92bf..f38d664 100644 --- a/hyperglass/ui/components/footer/footer.tsx +++ b/hyperglass/ui/components/footer/footer.tsx @@ -10,12 +10,12 @@ import { FooterLink } from './link'; import { isLink, isMenu } from './types'; import type { ButtonProps, LinkProps } from '@chakra-ui/react'; -import type { TLink, TMenu } from '~/types'; +import type { Link, Menu } from '~/types'; const CodeIcon = dynamic(() => import('@meronex/icons/fi').then(i => i.FiCode)); const ExtIcon = dynamic(() => import('@meronex/icons/go').then(i => i.GoLinkExternal)); -function buildItems(links: TLink[], menus: TMenu[]): [(TLink | TMenu)[], (TLink | TMenu)[]] { +function buildItems(links: Link[], menus: Menu[]): [(Link | Menu)[], (Link | Menu)[]] { const leftLinks = links.filter(link => link.side === 'left'); const leftMenus = menus.filter(menu => menu.side === 'left'); const rightLinks = links.filter(link => link.side === 'right'); @@ -27,7 +27,7 @@ function buildItems(links: TLink[], menus: TMenu[]): [(TLink | TMenu)[], (TLink } export const Footer: React.FC = () => { - const { web, content, primary_asn } = useConfig(); + const { web, content, primaryAsn } = useConfig(); const footerBg = useColorValue('blackAlpha.50', 'whiteAlpha.100'); const footerColor = useColorValue('black', 'white'); @@ -57,10 +57,10 @@ export const Footer: React.FC = () => { > {left.map(item => { if (isLink(item)) { - const url = strF(item.url, { primary_asn }, '/'); + const url = strF(item.url, { primaryAsn }, '/'); const icon: Partial = {}; - if (item.show_icon) { + if (item.showIcon) { icon.rightIcon = ; } return ; @@ -73,10 +73,10 @@ export const Footer: React.FC = () => { {!isMobile && } {right.map(item => { if (isLink(item)) { - const url = strF(item.url, { primary_asn }, '/'); + const url = strF(item.url, { primaryAsn }, '/'); const icon: Partial = {}; - if (item.show_icon) { + if (item.showIcon) { icon.rightIcon = ; } return ; diff --git a/hyperglass/ui/components/footer/types.ts b/hyperglass/ui/components/footer/types.ts index 8f6143d..9b0e172 100644 --- a/hyperglass/ui/components/footer/types.ts +++ b/hyperglass/ui/components/footer/types.ts @@ -1,5 +1,5 @@ import type { ButtonProps, LinkProps, MenuListProps } from '@chakra-ui/react'; -import type { TLink, TMenu } from '~/types'; +import type { Link, Menu } from '~/types'; type TFooterSide = 'left' | 'right'; @@ -17,10 +17,10 @@ export interface TColorModeToggle extends ButtonProps { size?: string; } -export function isLink(item: TLink | TMenu): item is TLink { +export function isLink(item: Link | Menu): item is Link { return 'url' in item; } -export function isMenu(item: TLink | TMenu): item is TMenu { +export function isMenu(item: Link | Menu): item is Menu { return 'content' in item; } diff --git a/hyperglass/ui/components/form/queryGroup.tsx b/hyperglass/ui/components/form/queryGroup.tsx index 6505b28..5f87e3b 100644 --- a/hyperglass/ui/components/form/queryGroup.tsx +++ b/hyperglass/ui/components/form/queryGroup.tsx @@ -24,13 +24,13 @@ export const QueryGroup: React.FC = (props: TQueryGroup) => { } else { selections.queryGroup.set(null); } - onChange({ field: 'query_group', value }); + onChange({ field: 'queryGroup', value }); } return ( + ); }; diff --git a/hyperglass/ui/components/form/resolvedTarget.tsx b/hyperglass/ui/components/form/resolvedTarget.tsx index bda17ef..5a65d8e 100644 --- a/hyperglass/ui/components/form/resolvedTarget.tsx +++ b/hyperglass/ui/components/form/resolvedTarget.tsx @@ -36,11 +36,11 @@ export const ResolvedTarget: React.FC = (props: TResolvedTarget const query4 = Array.from(families.value).includes(4); const query6 = Array.from(families.value).includes(6); - const tooltip4 = strF(web.text.fqdn_tooltip, { protocol: 'IPv4' }); - const tooltip6 = strF(web.text.fqdn_tooltip, { protocol: 'IPv6' }); + const tooltip4 = strF(web.text.fqdnTooltip, { protocol: 'IPv4' }); + const tooltip6 = strF(web.text.fqdnTooltip, { protocol: 'IPv6' }); - const [messageStart, messageEnd] = web.text.fqdn_message.split('{fqdn}'); - const [errorStart, errorEnd] = web.text.fqdn_error.split('{fqdn}'); + const [messageStart, messageEnd] = web.text.fqdnMessage.split('{fqdn}'); + const [errorStart, errorEnd] = web.text.fqdnError.split('{fqdn}'); const { data: data4, @@ -63,7 +63,7 @@ export const ResolvedTarget: React.FC = (props: TResolvedTarget const answer6 = useMemo(() => findAnswer(data6), [data6]); const handleOverride = useCallback( - (value: string): void => setTarget({ field: 'query_target', value }), + (value: string): void => setTarget({ field: 'queryTarget', value }), [setTarget], ); @@ -137,7 +137,7 @@ export const ResolvedTarget: React.FC = (props: TResolvedTarget onClick={errorClose} leftIcon={} > - {web.text.fqdn_error_button} + {web.text.fqdnErrorButton} )} diff --git a/hyperglass/ui/components/form/types.ts b/hyperglass/ui/components/form/types.ts index fc306dc..cf51583 100644 --- a/hyperglass/ui/components/form/types.ts +++ b/hyperglass/ui/components/form/types.ts @@ -1,6 +1,6 @@ import type { FormControlProps } from '@chakra-ui/react'; import type { UseFormRegister } from 'react-hook-form'; -import type { TBGPCommunity, OnChangeArgs, TFormData } from '~/types'; +import type { OnChangeArgs, FormData } from '~/types'; export interface TField extends FormControlProps { name: string; @@ -21,17 +21,10 @@ export interface TQueryGroup extends TQuerySelectField { groups: string[]; } -export interface TCommunitySelect { - name: string; - onChange: OnChange; - communities: TBGPCommunity[]; - register: UseFormRegister; -} - export interface TQueryTarget { name: string; placeholder: string; - register: UseFormRegister; + register: UseFormRegister; onChange(e: OnChangeArgs): void; } diff --git a/hyperglass/ui/components/header/logo.tsx b/hyperglass/ui/components/header/logo.tsx index d62f4aa..b044c2f 100644 --- a/hyperglass/ui/components/header/logo.tsx +++ b/hyperglass/ui/components/header/logo.tsx @@ -9,9 +9,9 @@ import type { TLogo } from './types'; */ function useLogo(): [string, () => void] { const { web } = useConfig(); - const { dark_format, light_format } = web.logo; + const { darkFormat, lightFormat } = web.logo; - const src = useColorValue(`/images/dark${dark_format}`, `/images/light${light_format}`); + const src = useColorValue(`/images/dark${darkFormat}`, `/images/light${lightFormat}`); // Use the hyperglass logo if the user's logo can't be loaded for whatever reason. const fallbackSrc = useColorValue( diff --git a/hyperglass/ui/components/header/title.tsx b/hyperglass/ui/components/header/title.tsx index d06dfea..203f839 100644 --- a/hyperglass/ui/components/header/title.tsx +++ b/hyperglass/ui/components/header/title.tsx @@ -106,7 +106,7 @@ const All: React.FC = () => ( export const Title: React.FC = (props: TTitle) => { const { fontSize, ...rest } = props; const { web } = useConfig(); - const titleMode = web.text.title_mode; + const { titleMode } = web.text; const { isSubmitting } = useLGState(); const { resetForm } = useLGMethods(); diff --git a/hyperglass/ui/components/help/types.ts b/hyperglass/ui/components/help/types.ts index 2a47dfc..aeefec8 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 { TQueryContent, TQueryFields } from '~/types'; +import type { QueryContent } from '~/types'; export interface THelpModal extends ModalContentProps { - item: TQueryContent | null; - name: TQueryFields; + item: QueryContent | null; + name: string; visible: boolean; } diff --git a/hyperglass/ui/components/layout/frame.tsx b/hyperglass/ui/components/layout/frame.tsx index 799612a..e73fd3a 100644 --- a/hyperglass/ui/components/layout/frame.tsx +++ b/hyperglass/ui/components/layout/frame.tsx @@ -11,7 +11,7 @@ import type { TFrame } from './types'; export const Frame = (props: TFrame): JSX.Element => { const router = useRouter(); - const { developer_mode, google_analytics } = useConfig(); + const { developerMode, googleAnalytics } = useConfig(); const { isSubmitting } = useLGState(); const { resetForm } = useLGMethods(); const { initialize, trackPage } = useGoogleAnalytics(); @@ -25,7 +25,7 @@ export const Frame = (props: TFrame): JSX.Element => { } useEffect(() => { - initialize(google_analytics, developer_mode); + initialize(googleAnalytics, developerMode); // eslint-disable-next-line react-hooks/exhaustive-deps }, []); @@ -62,10 +62,10 @@ export const Frame = (props: TFrame): JSX.Element => { {...props} />