From e6ca7986ad35d601ac155603e3e316fd4c354dbc Mon Sep 17 00:00:00 2001 From: Philipp Rudiger Date: Mon, 5 Oct 2020 15:51:53 +0200 Subject: [PATCH] Add logo option for BaseTemplates (#1608) --- examples/reference/templates/Bootstrap.ipynb | 1 + .../reference/templates/GoldenLayout.ipynb | 1 + examples/reference/templates/Material.ipynb | 1 + examples/reference/templates/Vanilla.ipynb | 1 + panel/pane/image.py | 14 ++++++++++++++ panel/template/base.py | 14 ++++++++++++++ panel/template/bootstrap/bootstrap.css | 8 ++++++++ panel/template/bootstrap/bootstrap.html | 7 ++++++- panel/template/golden/golden.css | 11 ++++++++++- panel/template/golden/golden.html | 9 +++++++-- panel/template/material/material.css | 10 ++++++++++ panel/template/material/material.html | 7 ++++++- panel/template/vanilla/vanilla.css | 19 +++++++++++++------ panel/template/vanilla/vanilla.html | 11 ++++++++--- 14 files changed, 100 insertions(+), 14 deletions(-) diff --git a/examples/reference/templates/Bootstrap.ipynb b/examples/reference/templates/Bootstrap.ipynb index 4d21c5a992..bec0c2851a 100644 --- a/examples/reference/templates/Bootstrap.ipynb +++ b/examples/reference/templates/Bootstrap.ipynb @@ -35,6 +35,7 @@ "* **`busy_indicator`** (BooleanIndicator): Visual indicator of application busy state.\n", "* **`header_background`** (str): Optional header background color override.\n", "* **`header_color`** (str): Optional header text color override.\n", + "* **`logo`** (str): URI of logo to add to the header (if local file, logo is base64 encoded as URI).\n", "* **`theme`** (Theme): A Theme class (available in `panel.template.theme`)\n", "* **`title`** (str): A title to show in the header.\n", "\n", diff --git a/examples/reference/templates/GoldenLayout.ipynb b/examples/reference/templates/GoldenLayout.ipynb index e2c0d12af0..47e69b41b8 100644 --- a/examples/reference/templates/GoldenLayout.ipynb +++ b/examples/reference/templates/GoldenLayout.ipynb @@ -35,6 +35,7 @@ "* **`busy_indicator`** (BooleanIndicator): Visual indicator of application busy state.\n", "* **`header_background`** (str): Optional header background color override.\n", "* **`header_color`** (str): Optional header text color override.\n", + "* **`logo`** (str): URI of logo to add to the header (if local file, logo is base64 encoded as URI).\n", "* **`theme`** (Theme): A Theme class (available in `panel.template.theme`)\n", "* **`title`** (str): A title to show in the header.\n", "\n", diff --git a/examples/reference/templates/Material.ipynb b/examples/reference/templates/Material.ipynb index 27ef72e6f7..88631cbb12 100644 --- a/examples/reference/templates/Material.ipynb +++ b/examples/reference/templates/Material.ipynb @@ -35,6 +35,7 @@ "* **`busy_indicator`** (BooleanIndicator): Visual indicator of application busy state.\n", "* **`header_background`** (str): Optional header background color override.\n", "* **`header_color`** (str): Optional header text color override.\n", + "* **`logo`** (str): URI of logo to add to the header (if local file, logo is base64 encoded as URI).\n", "* **`theme`** (Theme): A Theme class (available in `panel.template.theme`)\n", "* **`title`** (str): A title to show in the header.\n", "\n", diff --git a/examples/reference/templates/Vanilla.ipynb b/examples/reference/templates/Vanilla.ipynb index a5175eb416..04632da4e5 100644 --- a/examples/reference/templates/Vanilla.ipynb +++ b/examples/reference/templates/Vanilla.ipynb @@ -35,6 +35,7 @@ "* **`busy_indicator`** (BooleanIndicator): Visual indicator of application busy state.\n", "* **`header_background`** (str): Optional header background color override.\n", "* **`header_color`** (str): Optional header text color override.\n", + "* **`logo`** (str): URI of logo to add to the header (if local file, logo is base64 encoded as URI).\n", "* **`theme`** (Theme): A Theme class (available in `panel.template.theme`)\n", "* **`title`** (str): A title to show in the header.\n", "\n", diff --git a/panel/pane/image.py b/panel/pane/image.py index 810a0f4cae..d151239d35 100644 --- a/panel/pane/image.py +++ b/panel/pane/image.py @@ -84,6 +84,13 @@ def _img(self): r = requests.request(url=self.object, method='GET') return r.content + def _b64(self): + data = self._img() + if not isinstance(data, bytes): + data = data.encode('utf-8') + b64 = base64.b64encode(data).decode("utf-8") + return "data:image/"+self.imgtype+f";base64,{b64}" + def _imgshape(self, data): """Calculate and return image width,height""" raise NotImplementedError @@ -207,6 +214,13 @@ def _img(self): return self.object return super(SVG, self)._img() + def _b64(self): + data = self._img() + if not isinstance(data, bytes): + data = data.encode('utf-8') + b64 = base64.b64encode(data).decode("utf-8") + return f"data:image/svg+xml;base64,{b64}" + def _imgshape(self, data): return (self.width, self.height) diff --git a/panel/template/base.py b/panel/template/base.py index ce736b3c9f..ce4d730a9d 100644 --- a/panel/template/base.py +++ b/panel/template/base.py @@ -4,6 +4,7 @@ """ from __future__ import absolute_import, division, unicode_literals +import os import sys import uuid @@ -25,6 +26,7 @@ from ..layout import Column, ListLike from ..models.comm_manager import CommManager from ..pane import panel as _panel, HTML, Str, HoloViews +from ..pane.image import ImageBase from ..viewable import ServableMixin, Viewable from ..widgets import Button from ..widgets.indicators import BooleanIndicator, LoadingSpinner @@ -319,6 +321,10 @@ class BasicTemplate(BaseTemplate): modal = param.ClassSelector(class_=ListLike, constant=True, doc=""" A list-like container which populates the modal""") + logo = param.String(constant=True, doc=""" + URI of logo to add to the header (if local file, logo is + base64 encoded as URI).""") + title = param.String(doc="A title to show in the header.") header_background = param.String(doc="Optional header background color override") @@ -388,6 +394,14 @@ def _init_doc(self, doc=None, comm=None, title=None, notebook=False, location=Tr def _update_vars(self, *args): self._render_variables['app_title'] = self.title + if os.path.isfile(self.logo): + img = _panel(self.logo) + if not isinstance(img, ImageBase): + raise ValueError("Could not determine file type of logo: {self.logo}.") + logo = img._b64() + else: + logo = self.logo + self._render_variables['app_logo'] = logo self._render_variables['header_background'] = self.header_background self._render_variables['header_color'] = self.header_color diff --git a/panel/template/bootstrap/bootstrap.css b/panel/template/bootstrap/bootstrap.css index a65fb8bfc6..590dcff682 100644 --- a/panel/template/bootstrap/bootstrap.css +++ b/panel/template/bootstrap/bootstrap.css @@ -31,6 +31,13 @@ body { a.navbar-brand { padding-left: 10px; + display: flex; + align-items: center; + font-size: 1.5em; +} + +img.app-logo { + padding-right: 10px; } p.bk.card-button { @@ -75,3 +82,4 @@ p.bk.card-button { display: flex; margin-left: auto; } + diff --git a/panel/template/bootstrap/bootstrap.html b/panel/template/bootstrap/bootstrap.html index 871ad0b384..993a879388 100644 --- a/panel/template/bootstrap/bootstrap.html +++ b/panel/template/bootstrap/bootstrap.html @@ -16,7 +16,12 @@ {% endif %} - {{ app_title }} + + {% if app_logo %} + + {% endif %} + {{ app_title }} + {% for doc in docs %} {% for root in doc.roots %} {% if "header" in root.tags %} diff --git a/panel/template/golden/golden.css b/panel/template/golden/golden.css index 0947059d5b..5e38c0bca5 100644 --- a/panel/template/golden/golden.css +++ b/panel/template/golden/golden.css @@ -34,13 +34,22 @@ body { color: white; } +.app-header { + display: flex; +} + +img.app-logo { + padding-left: 10px; +} + .header-adjust { padding-top: 64px; } .header-title { font-size: 1.5em; - padding-left: 1.5em; + line-height: 2em; + padding-left: 1em; font: 1.5em Arial, sans-serif; color: white; text-align: center; diff --git a/panel/template/golden/golden.html b/panel/template/golden/golden.html index 2d836a0268..5d6f2c0659 100644 --- a/panel/template/golden/golden.html +++ b/panel/template/golden/golden.html @@ -11,8 +11,13 @@ {% block contents %}