diff --git a/hyperglass/configuration/models/opengraph.py b/hyperglass/configuration/models/opengraph.py
index 0c33a28..76380fb 100644
--- a/hyperglass/configuration/models/opengraph.py
+++ b/hyperglass/configuration/models/opengraph.py
@@ -6,8 +6,7 @@ from typing import Optional
from pathlib import Path
# Third Party
-import PIL.Image as PilImage
-from pydantic import FilePath, StrictInt, root_validator
+from pydantic import FilePath, StrictInt, validator
# Project
from hyperglass.models import HyperglassModel
@@ -21,11 +20,11 @@ class OpenGraph(HyperglassModel):
width: Optional[StrictInt]
height: Optional[StrictInt]
- image: FilePath = DEFAULT_IMAGES / "hyperglass-opengraph.png"
+ image: FilePath = DEFAULT_IMAGES / "hyperglass-opengraph.jpg"
- @root_validator
- def validate_opengraph(cls, values):
- """Set default opengraph image location.
+ @validator("image")
+ def validate_opengraph(cls, value):
+ """Ensure the opengraph image is a supported format.
Arguments:
value {FilePath} -- Path to opengraph image file.
@@ -34,41 +33,11 @@ class OpenGraph(HyperglassModel):
{Path} -- Opengraph image file path object
"""
supported_extensions = (".jpg", ".jpeg", ".png")
- if (
- values["image"] is not None
- and values["image"].suffix not in supported_extensions
- ):
+ if value is not None and value.suffix not in supported_extensions:
raise ValueError(
"OpenGraph image must be one of {e}".format(
e=", ".join(supported_extensions)
)
)
- with PilImage.open(values["image"]) as img:
- width, height = img.size
- if values["width"] is None:
- values["width"] = width
- if values["height"] is None:
- values["height"] = height
-
- return values
-
- class Config:
- """Pydantic model configuration."""
-
- title = "OpenGraph"
- description = "OpenGraph configuration parameters"
- fields = {
- "width": {
- "title": "Width",
- "description": "Width of OpenGraph image. If unset, the width will be automatically derived by reading the image file.",
- },
- "height": {
- "title": "Height",
- "description": "Height of OpenGraph image. If unset, the height will be automatically derived by reading the image file.",
- },
- "image": {
- "title": "Image File",
- "description": "Valid path to a JPG or PNG file to use as the OpenGraph image.",
- },
- }
+ return value
diff --git a/hyperglass/configuration/models/web.py b/hyperglass/configuration/models/web.py
index 44cd152..86b725f 100644
--- a/hyperglass/configuration/models/web.py
+++ b/hyperglass/configuration/models/web.py
@@ -92,10 +92,10 @@ class Greeting(HyperglassModel):
class Logo(HyperglassModel):
"""Validation model for logo configuration."""
- light: FilePath = DEFAULT_IMAGES / "hyperglass-light.png"
- dark: FilePath = DEFAULT_IMAGES / "hyperglass-dark.png"
- favicon: FilePath = DEFAULT_IMAGES / "icon.svg"
- width: Optional[Union[StrictInt, constr(regex=r"^([1-9][0-9]?|100)\%$")]] = "80%"
+ light: FilePath = DEFAULT_IMAGES / "hyperglass-light.svg"
+ dark: FilePath = DEFAULT_IMAGES / "hyperglass-dark.svg"
+ favicon: FilePath = DEFAULT_IMAGES / "hyperglass-icon.svg"
+ width: Optional[Union[StrictInt, constr(regex=r"^([1-9][0-9]?|100)\%$")]] = "75%"
height: Optional[Union[StrictInt, constr(regex=r"^([1-9][0-9]?|100)\%$")]]
@@ -144,8 +144,8 @@ class Text(HyperglassModel):
class ThemeColors(HyperglassModel):
"""Validation model for theme colors."""
- black: Color = "#262626"
- white: Color = "#f7f7f7"
+ black: Color = "#121212"
+ white: Color = "#f5f6f7"
gray: Color = "#c1c7cc"
red: Color = "#d84b4b"
orange: Color = "#ff6b35"
diff --git a/hyperglass/examples/hyperglass.yaml b/hyperglass/examples/hyperglass.yaml
index e69de29..ba1008f 100644
--- a/hyperglass/examples/hyperglass.yaml
+++ b/hyperglass/examples/hyperglass.yaml
@@ -0,0 +1,194 @@
+# cache:
+# database: 1
+# host: localhost
+# port: 6379
+# show_text: true
+# timeout: 120
+# cors_origins: []
+# debug: true
+# developer_mode: true
+# docs:
+# base_url: https://lg.example.net
+# communities:
+# description: List of BGP communities.
+# summary: BGP Communities List
+# title: BGP Communities
+# description: ''
+# devices:
+# description:
+# List of all devices/locations with associated identifiers, display
+# names, networks, & VRFs.
+# summary: Devices List
+# title: Devices
+# enable: true
+# mode: redoc
+# openapi_uri: /openapi.json
+# queries:
+# description: List of supported query types.
+# summary: Query Types
+# title: Supported Queries
+# query:
+# description: Request a query response per-location.
+# summary: Query the Looking Glass
+# title: Submit Query
+# title: '{site_title} API Documentation'
+# uri: /api/docs
+# listen_address: 0.0.0.0
+# listen_port: 8001
+# logging:
+# directory: /tmp
+# format: text
+# http: null
+# max_size: 50000000
+# syslog: null
+# messages:
+# acl_denied: '{target} is a member of {denied_network}, which is not allowed.'
+# acl_not_allowed: '{target} is not allowed.'
+# authentication_error: Authentication error occurred.
+# connection_error: 'Error connecting to {device_name}: {error}'
+# feature_not_enabled: '{feature} is not enabled.'
+# general: Something went wrong.
+# invalid_field: '{input} is an invalid {field}.'
+# invalid_input: '{target} is not a valid {query_type} target.'
+# no_input: '{field} must be specified.'
+# no_output: The query completed, but no matching results were found.
+# no_response: No response.
+# parsing_error: An error occurred while parsing the query output.
+# request_timeout: Request timed out.
+# vrf_not_associated: VRF {vrf_name} is not associated with {device_name}.
+# vrf_not_found: VRF {vrf_name} is not defined.
+# netmiko_delay_factor: 0.1
+# org_name: Beloved Hyperglass User
+# primary_asn: '65001'
+# queries:
+# bgp_aspath:
+# display_name: BGP AS Path
+# enable: true
+# pattern:
+# asdot: ^(\^|^\_)((\d+\.\d+)\_|(\d+\.\d+)\$|(\d+\.\d+)\(\_\.\+\_\))+$
+# asplain: .*
+# mode: asplain
+# bgp_community:
+# communities:
+# - community: 14525:5001
+# description: Phoenix, AZ Metro Aggregate Routes
+# display_name: 14525:5001
+# display_name: BGP Community
+# enable: true
+# mode: select
+# pattern:
+# decimal: ^[0-9]{1,10}$
+# extended_as: ^([0-9]{0,5})\:([0-9]{1,5})$
+# large: ^([0-9]{1,10})\:([0-9]{1,10})\:[0-9]{1,10}$
+# bgp_route:
+# display_name: BGP Route
+# enable: true
+# ping:
+# display_name: Ping
+# enable: true
+# traceroute:
+# display_name: Traceroute
+# enable: true
+# request_timeout: 90
+# site_description: Beloved Hyperglass User Network Looking Glass
+# site_keywords:
+# - Beloved Hyperglass User
+# - bgp
+# - communities
+# - community
+# - dev hyperglass
+# - hyperglass
+# - internet service provider
+# - ip
+# - ipv4
+# - ipv6
+# - isp
+# - lg
+# - looking glass
+# - network
+# - peer
+# - peering
+# - routing
+# - transit
+# site_title: dev hyperglass
+# structured:
+# communities:
+# items:
+# - 14525:\d{4}
+# mode: permit
+# rpki:
+# mode: external
+# web:
+# credit:
+# enable: true
+# dns_provider:
+# name: cloudflare
+# url: https://cloudflare-dns.com/dns-query
+# external_link:
+# enable: true
+# title: PeeringDB
+# url: https://www.peeringdb.com/asn/{primary_asn}
+# greeting:
+# button: Continue
+# enable: false
+# file: null
+# required: false
+# title: Welcome
+# help_menu:
+# enable: true
+# file: null
+# title: Help
+# logo:
+# dark: /Users/ml/dev/hyperglass/hyperglass/images/hyperglass-dark.svg
+# favicon: /Users/ml/dev/hyperglass/hyperglass/images/hyperglass-icon.svg
+# height: null
+# light: /Users/ml/dev/hyperglass/hyperglass/images/hyperglass-light.svg
+# width: 75%
+# opengraph:
+# height: null
+# image: /Users/ml/dev/hyperglass/hyperglass/images/hyperglass-opengraph.jpg
+# width: null
+# terms:
+# enable: true
+# file: null
+# title: Terms
+# text:
+# cache_icon: Cached from {time} UTC
+# cache_prefix: 'Results cached for '
+# complete_time: Completed in {seconds}
+# fqdn_tooltip: Use {protocol}
+# query_location: Location
+# query_target: Target
+# query_type: Query Type
+# query_vrf: Routing Table
+# rpki_invalid: Invalid
+# rpki_unknown: No ROAs Exist
+# rpki_unverified: Not Verified
+# rpki_valid: Valid
+# subtitle: really really really really really long subtitle
+# title: hyperglass
+# title_mode: logo_subtitle
+# theme:
+# colors:
+# black: '#121212'
+# blue: '#314cb6'
+# cyan: '#118ab2'
+# danger: '#d84b4b'
+# error: '#ff6b35'
+# gray: '#c1c7cc'
+# green: '#35b246'
+# orange: '#ff6b35'
+# pink: '#f2607d'
+# primary: '#118ab2'
+# purple: '#8d30b5'
+# red: '#d84b4b'
+# secondary: '#314cb6'
+# success: '#35b246'
+# teal: '#35b299'
+# warning: '#edae49'
+# white: '#f5f6f7'
+# yellow: '#edae49'
+# default_color_mode: null
+# fonts:
+# body: Nunito
+# mono: Fira Code
diff --git a/hyperglass/ui/components/Meta.js b/hyperglass/ui/components/Meta.js
index fd0a345..c83d36c 100644
--- a/hyperglass/ui/components/Meta.js
+++ b/hyperglass/ui/components/Meta.js
@@ -28,13 +28,10 @@ const Meta = () => {
"isp"
];
const language = config?.language ?? "en";
- const ogImage = config?.web.opengraph.image ?? null;
- const ogImageHeight = config?.web.opengraph.height ?? null;
- const ogImageWidth = config?.web.opengraph.width ?? null;
const primaryFont = googleFontUrl(theme.fonts.body);
const monoFont = googleFontUrl(theme.fonts.mono);
useEffect(() => {
- if (typeof window !== undefined && location === {}) {
+ if (typeof window !== "undefined" && location === {}) {
setLocation(window.location);
}
}, [location]);
@@ -48,11 +45,8 @@ const Meta = () => {
-
-
-
diff --git a/hyperglass/ui/pages/_app.js b/hyperglass/ui/pages/_app.js
index a9e7348..a212260 100644
--- a/hyperglass/ui/pages/_app.js
+++ b/hyperglass/ui/pages/_app.js
@@ -1,4 +1,5 @@
-import React from "react";
+import * as React from "react";
+import Head from "next/head";
// import { useRouter } from "next/router";
import { HyperglassProvider } from "~/components/HyperglassProvider";
// import Error from "./_error";
@@ -11,9 +12,20 @@ const Hyperglass = ({ Component, pageProps }) => {
// return