diff --git a/CHANGELOG.md b/CHANGELOG.md index cdaebbeac2..7197e7cc8d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +## 0.28.0 - 2018-09-26 +## Added +- Default favicon for dash apps. [#406](https://github.com/plotly/dash/pull/406#issuecomment-424821743) +- Bust the cache of the assets favicon. + +## Fixed +- Remove the first and last blank lines from the HTML index string. [#403](https://github.com/plotly/dash/pull/403) + ## 0.27.0 - 2018-09-20 ## Added - Added support for serving dev bundles from the components suite, enable with `app.run_server(dev_tools_serve_dev_bundles=True)` [#369](https://github.com/plotly/dash/pull/369) diff --git a/MANIFEST.in b/MANIFEST.in index 04f196ac78..af967cd137 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,2 +1,3 @@ include README.md include LICENSE +include dash/favicon.ico diff --git a/dash/dash.py b/dash/dash.py index 1ea4532411..5c70884e2f 100644 --- a/dash/dash.py +++ b/dash/dash.py @@ -214,6 +214,9 @@ def add_url(name, view_func, methods=('GET',)): '{}'.format(self.config['routes_pathname_prefix']), self.index) + add_url('{}_favicon.ico'.format(self.config['routes_pathname_prefix']), + self._serve_default_favicon) + self.server.before_first_request(self._setup_server) self._layout = None @@ -459,11 +462,22 @@ def index(self, *args, **kwargs): # pylint: disable=unused-argument config = self._generate_config_html() metas = self._generate_meta_html() title = getattr(self, 'title', 'Dash') + if self._favicon: - favicon = ''.format( - self.get_asset_url(self._favicon)) + favicon_mod_time = os.path.getmtime( + os.path.join(self._assets_folder, self._favicon)) + favicon_url = self.get_asset_url(self._favicon) + '?m={}'.format( + favicon_mod_time + ) else: - favicon = '' + favicon_url = '{}_favicon.ico'.format( + self.config.requests_pathname_prefix) + + favicon = _format_tag('link', { + 'rel': 'icon', + 'type': 'image/x-icon', + 'href': favicon_url + }, opened=True) index = self.interpolate_index( metas=metas, title=title, css=css, config=config, @@ -973,6 +987,15 @@ def add_resource(p, filepath): def _invalid_resources_handler(self, err): return err.args[0], 404 + def _serve_default_favicon(self): + headers = { + 'Cache-Control': 'public, max-age={}'.format( + self.config.components_cache_max_age) + } + return flask.Response(pkgutil.get_data('dash', 'favicon.ico'), + headers=headers, + content_type='image/x-icon') + def get_asset_url(self, path): asset = _get_asset_path( self.config.requests_pathname_prefix, diff --git a/dash/favicon.ico b/dash/favicon.ico new file mode 100644 index 0000000000..cbdf9afdf1 Binary files /dev/null and b/dash/favicon.ico differ diff --git a/dash/version.py b/dash/version.py index cf7b6d6589..1bf36757cf 100644 --- a/dash/version.py +++ b/dash/version.py @@ -1 +1 @@ -__version__ = '0.27.0' +__version__ = '0.28.0'