mirror of
https://github.com/webrecorder/pywb.git
synced 2025-03-15 00:03:28 +01:00
ui/templates: fixes based on feedback from @ldko!
templates: add placeholder templates (footer.html, head.html) templates: allow 'base_html', 'footer_html', 'head_html', 'header_html' to be added via wb-manager 'add-template' cmd ui: fix logo path, support linking ui: make url on banner an input field docs: clarify docs around templates, paths
This commit is contained in:
parent
29860bcb24
commit
6260b226ce
@ -60,6 +60,15 @@ When using the custom banner, it is possible to configure a logo by setting ``ui
|
||||
|
||||
If omitted, the standard pywb logo will be used by default.
|
||||
|
||||
If set, the logo should point to a file in the static directory (default is ``static`` but can be changed via the ``static_dir`` config option).
|
||||
|
||||
For example, to use the file ``./static/my-logo.png`` as the logo, set:
|
||||
|
||||
.. code:: yaml
|
||||
|
||||
ui:
|
||||
logo: my-logo.png
|
||||
|
||||
|
||||
Updating the Vue UI
|
||||
-------------------
|
||||
|
@ -61,6 +61,9 @@ can also be overriden:
|
||||
* ``footer.html`` -- Template for adding content as the "footer" of the ``<body>`` tag of the ``base`` template
|
||||
|
||||
|
||||
Note: The default pywb ``head.html`` and ``footer.html`` are currently blank. They can be populated to customize the rendering, add analytics, etc... as needed.
|
||||
|
||||
|
||||
The ``base.html`` template also provides five blocks that can be supplied by templates that extend it.
|
||||
|
||||
* ``title`` -- Block for supplying the title for the page
|
||||
@ -157,7 +160,7 @@ Template variables:
|
||||
|
||||
* ``{{ ui }}`` - an optional ``ui`` dictionary from ``config.yaml``, if any
|
||||
|
||||
* ``{{ static_prefix }}`` - the prefix from which static files will be accessed from, e.g. ``http://localhost:8080/static/``
|
||||
* ``{{ static_prefix }}`` - the prefix from which static files will be accessed from, e.g. ``http://localhost:8080/static/``.
|
||||
|
||||
|
||||
Replay and Banner Templates
|
||||
@ -186,6 +189,8 @@ Template variables:
|
||||
|
||||
* ``{{ wb_prefix }}`` - the collection prefix, e.g. ``http://localhost:8080/pywb/``
|
||||
|
||||
* ``{{ host_prefix }}`` - the pywb server origin, e.g. ``http://localhost:8080``
|
||||
|
||||
* ``{{ config }}`` - provides the contents of the ``config.yaml`` as a dictionary.
|
||||
|
||||
* ``{{ ui }}`` - an optional ``ui`` dictionary from ``config.yaml``, if any.
|
||||
@ -232,10 +237,10 @@ Template variables:
|
||||
|
||||
* ``{{ wb_url }}`` - A complete ``WbUrl`` object, which contains the ``url``, ``timestamp`` and ``mod`` properties, representing the replay url.
|
||||
|
||||
* ``{{ is_framed }}`` - true/false if currently in framed mode.
|
||||
|
||||
* ``{{ wb_prefix }}`` - the collection prefix, e.g. ``http://localhost:8080/pywb/``
|
||||
|
||||
* ``{{ is_proxy }}`` - set to true if page is being loaded via an HTTP/S proxy (checks if WSGI env has ``wsgiprox.proxy_host`` set)
|
||||
|
||||
|
||||
|
||||
.. _custom-top-frame:
|
||||
@ -332,7 +337,7 @@ The following template variables are available to all templates.
|
||||
|
||||
* ``{{ env.pywb_proxy_magic }}`` - if set, indicates pywb is accessed via proxy. See :ref:`https-proxy`
|
||||
|
||||
* ``{{ static_prefix }}`` - path to use for loading static files.
|
||||
* ``{{ static_prefix }}`` - URL path to use for loading static files.
|
||||
|
||||
|
||||
UI Configuration
|
||||
|
@ -25,12 +25,13 @@ To enable the logo set the ``ui.logo`` property in ``config.yaml`` to point to t
|
||||
|
||||
The URL can be any image URL, including a URL served from the static directory.
|
||||
|
||||
For example, to add the default pywb logo to the banner, use the following in the config:
|
||||
For example, to add the default pywb logo to the banner, use the following in the config, which will
|
||||
load the logo from ``./static/pywb-logo-sm.png``
|
||||
|
||||
.. code:: yaml
|
||||
|
||||
ui:
|
||||
logo: /static/pywb-logo-sm.png
|
||||
logo: pywb-logo-sm.png
|
||||
|
||||
|
||||
New Vue-based UI (Alpha)
|
||||
@ -66,7 +67,7 @@ It is possible to change these settings via ``config.yaml``:
|
||||
|
||||
* ``static_prefix`` - sets the URL path used in pywb to serve static content (default ``static``)
|
||||
|
||||
* ``static_dir`` - sets the directory name used to read static files (default ``static``)
|
||||
* ``static_dir`` - sets the directory name used to read static files on disk (default ``static``)
|
||||
|
||||
While pywb can serve static files, it is recommended to use an existing web server to serve static files, especially if already using it in production.
|
||||
|
||||
|
@ -15,6 +15,11 @@ banner_html: banner.html
|
||||
head_insert_html: head_insert.html
|
||||
frame_insert_html: frame_insert.html
|
||||
|
||||
base_html: base.html
|
||||
header_html: header.html
|
||||
footer_html: footer.html
|
||||
head_html: head.html
|
||||
|
||||
query_html: query.html
|
||||
search_html: search.html
|
||||
not_found_html: not_found.html
|
||||
@ -39,6 +44,12 @@ html_templates:
|
||||
- not_found_html
|
||||
|
||||
- home_html
|
||||
|
||||
- base_html
|
||||
- header_html
|
||||
- head_html
|
||||
- footer_html
|
||||
|
||||
- error_html
|
||||
- proxy_cert_download_html
|
||||
- proxy_select_html
|
||||
|
@ -237,17 +237,20 @@ directory structure expected by pywb
|
||||
v = defaults[n]
|
||||
print('- {0}: (pywb/{1})'.format(n, v))
|
||||
|
||||
def _confirm_overwrite(self, full_path, msg):
|
||||
def _confirm_overwrite(self, full_path, msg, ignore=False):
|
||||
if not os.path.isfile(full_path):
|
||||
return True
|
||||
|
||||
if ignore:
|
||||
return False
|
||||
|
||||
res = get_input(msg)
|
||||
try:
|
||||
res = strtobool(res)
|
||||
except ValueError:
|
||||
res = False
|
||||
|
||||
if not res:
|
||||
if not res and not ignore:
|
||||
raise IOError('Skipping, {0} already exists'.format(full_path))
|
||||
|
||||
def _get_template_path(self, template_name, verb):
|
||||
@ -268,7 +271,7 @@ directory structure expected by pywb
|
||||
|
||||
return full_path, filename
|
||||
|
||||
def add_template(self, template_name, force=False):
|
||||
def add_template(self, template_name, force=False, ignore=False):
|
||||
full_path, filename = self._get_template_path(template_name, 'add')
|
||||
|
||||
msg = ('Template file "{0}" ({1}) already exists. ' +
|
||||
@ -276,7 +279,11 @@ directory structure expected by pywb
|
||||
msg = msg.format(full_path, template_name)
|
||||
|
||||
if not force:
|
||||
self._confirm_overwrite(full_path, msg)
|
||||
res = self._confirm_overwrite(full_path, msg, ignore)
|
||||
if ignore and not res:
|
||||
return
|
||||
|
||||
os.makedirs(os.path.dirname(full_path), exist_ok=True)
|
||||
|
||||
data = resource_string('pywb', filename)
|
||||
with open(full_path, 'w+b') as fh:
|
||||
@ -286,6 +293,9 @@ directory structure expected by pywb
|
||||
msg = 'Copied default template "{0}" to "{1}"'
|
||||
print(msg.format(filename, full_path))
|
||||
|
||||
if template_name != "base_html":
|
||||
self.add_template("base_html", force=False, ignore=True)
|
||||
|
||||
def remove_template(self, template_name, force=False):
|
||||
full_path, filename = self._get_template_path(template_name, 'remove')
|
||||
|
||||
|
@ -164,8 +164,9 @@ This file is part of pywb, https://github.com/webrecorder/pywb
|
||||
logo.setAttribute("class", "_wb_linked_logo");
|
||||
|
||||
var logoContents = "";
|
||||
logoContents += "<img src='" + window.banner_info.logoImg + "' alt='" + window.banner_info.logoAlt + "'>";
|
||||
logoContents += "<img src='" + window.banner_info.logoImg + "' class='_wb_mobile' alt='" + window.banner_info.logoAlt + "'>";
|
||||
var logoUrl = window.banner_info.staticPrefix + "/" + window.banner_info.logoImg;
|
||||
logoContents += "<img src='" + logoUrl + "' alt='" + window.banner_info.logoAlt + "'>";
|
||||
logoContents += "<img src='" + logoUrl + "' class='_wb_mobile' alt='" + window.banner_info.logoAlt + "'>";
|
||||
|
||||
logo.innerHTML = logoContents;
|
||||
this.banner.appendChild(logo);
|
||||
|
File diff suppressed because one or more lines are too long
@ -34,7 +34,7 @@ window.banner_info = {
|
||||
<link rel='stylesheet' href='{{ static_prefix }}/vue_banner.css'/>
|
||||
<script src="{{ static_prefix }}/vue/vueui.js"></script>
|
||||
<script>
|
||||
VueUI.main("{{ static_prefix }}", "{{ url }}", "{{ wb_prefix }}", "{{ timestamp }}");
|
||||
VueUI.main("{{ static_prefix }}", "{{ url }}", "{{ wb_prefix }}", "{{ timestamp }}", "{{ ui.logo }}");
|
||||
</script>
|
||||
|
||||
{% if ui.vue_timeline_banner %}
|
||||
|
2
pywb/templates/footer.html
Normal file
2
pywb/templates/footer.html
Normal file
@ -0,0 +1,2 @@
|
||||
{# place content to be added at the very end of the <body> tag in this file below #}
|
||||
|
1
pywb/templates/head.html
Normal file
1
pywb/templates/head.html
Normal file
@ -0,0 +1 @@
|
||||
{# place optional content to be injected into the <head> of every page in this file below #}
|
@ -1,3 +1,4 @@
|
||||
{# place content to be added at the very beginning of the <body> tag in this file below #}
|
||||
<header>
|
||||
{% if not err_msg and locales|length > 1 %}
|
||||
<div class="language-select">
|
||||
|
@ -10,7 +10,7 @@
|
||||
{% for route in routes %}
|
||||
<li>
|
||||
<a href="{{ env['pywb.app_prefix'] + ('/' + env.pywb_lang if env.pywb_lang else '') + '/' + route }}">{{ '/' + route }}</a>
|
||||
{% if all_metadata and all_metadata[route] %}
|
||||
{% if all_metadata and all_metadata[route] and all_metadata[route].title %}
|
||||
({{ all_metadata[route].title }})
|
||||
{% endif %}
|
||||
</li>
|
||||
|
@ -75,7 +75,7 @@
|
||||
renderCal.init();
|
||||
|
||||
{% else %}
|
||||
VueUI.main("{{ static_prefix }}", "{{ url }}", "{{ prefix }}");
|
||||
VueUI.main("{{ static_prefix }}", "{{ url }}", "{{ prefix }}", undefined, "{{ ui.logo }}");
|
||||
|
||||
{% endif %}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
__version__ = '2.6.9'
|
||||
__version__ = '2.7.0b1'
|
||||
|
||||
if __name__ == '__main__':
|
||||
print(__version__)
|
||||
|
@ -2,7 +2,7 @@
|
||||
<div class="app" :class="{expanded: showTimelineView}" data-app="webrecorder-replay-app">
|
||||
<div class="banner">
|
||||
<div class="line">
|
||||
<div class="logo"><img :src="config.logoImg" /></div>
|
||||
<div class="logo"><a href="/"><img :src="config.logoImg" style="max-width: 80px" /></a></div>
|
||||
<div class="timeline-wrap">
|
||||
<div class="line">
|
||||
<div class="breadcrumbs-wrap">
|
||||
@ -35,13 +35,15 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="snapshot-title">
|
||||
<div>{{ config.url }}</div>
|
||||
<form @submit="gotoUrl">
|
||||
<input id="theurl" type="text" :value="config.url"></input>
|
||||
</form>
|
||||
<div v-if="currentSnapshot && !showFullView">
|
||||
<span v-if="config.title">{{ config.title }}</span>
|
||||
Current capture: {{currentSnapshot.getTimeDateFormatted()}}
|
||||
</div>
|
||||
</div>
|
||||
<CalendarYear v-if="showFullView"
|
||||
<CalendarYear v-if="showFullView && currentPeriod && currentPeriod.children.length"
|
||||
:period="currentPeriod"
|
||||
:current-snapshot="currentSnapshot"
|
||||
@goto-period="gotoPeriod">
|
||||
@ -124,6 +126,13 @@ export default {
|
||||
this.$emit("show-snapshot", snapshot);
|
||||
this.showFullView = false;
|
||||
},
|
||||
gotoUrl(event) {
|
||||
event.preventDefault();
|
||||
const newUrl = document.querySelector("#theurl").value;
|
||||
if (newUrl !== this.url) {
|
||||
window.location.href = this.config.prefix + "*/" + newUrl;
|
||||
}
|
||||
},
|
||||
init() {
|
||||
this.config.url = this.config.initialView.url;
|
||||
if (this.config.initialView.title) {
|
||||
@ -134,9 +143,11 @@ export default {
|
||||
this.showTimelineView = true;
|
||||
} else {
|
||||
this.showFullView = false;
|
||||
this.showFullView = true;
|
||||
this.showTimelineView = true;
|
||||
if (this.currentPeriod.children.length) {
|
||||
this.setSnapshot(this.config.initialView);
|
||||
}
|
||||
}
|
||||
if (window.sessionStorage) {
|
||||
const currentPeriodId = window.sessionStorage.getItem(this.sessionStorageUrlKey);
|
||||
if (currentPeriodId) {
|
||||
@ -242,4 +253,7 @@ export default {
|
||||
font-weight: bold;
|
||||
font-size: 16px;
|
||||
}
|
||||
#theurl {
|
||||
width: 400px;
|
||||
}
|
||||
</style>
|
||||
|
@ -6,16 +6,17 @@ import Vue from "vue/dist/vue.esm.browser";
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
export function main(staticPrefix, url, prefix, timestamp) {
|
||||
new CDXLoader(staticPrefix, url, prefix, timestamp);
|
||||
export function main(staticPrefix, url, prefix, timestamp, logoUrl) {
|
||||
new CDXLoader(staticPrefix, url, prefix, timestamp, logoUrl);
|
||||
}
|
||||
|
||||
// ===========================================================================
|
||||
class CDXLoader {
|
||||
constructor(staticPrefix, url, prefix, timestamp) {
|
||||
constructor(staticPrefix, url, prefix, timestamp, logoUrl) {
|
||||
this.opts = {};
|
||||
this.prefix = prefix;
|
||||
this.staticPrefix = staticPrefix;
|
||||
this.logoUrl = logoUrl;
|
||||
|
||||
this.isReplay = (timestamp !== undefined);
|
||||
|
||||
@ -44,8 +45,7 @@ class CDXLoader {
|
||||
|
||||
this.opts.initialView = {url, timestamp};
|
||||
|
||||
// TODO: make configurable
|
||||
this.opts.logoImg = staticPrefix + "/pywb-logo-sm.png";
|
||||
this.opts.logoImg = this.staticPrefix + "/" + (this.logoUrl ? this.logoUrl : "pywb-logo-sm.png");
|
||||
|
||||
this.loadCDX(queryURL).then((cdxList) => {
|
||||
this.app = this.initApp(cdxList, this.opts, (snapshot) => this.loadSnapshot(snapshot));
|
||||
@ -60,7 +60,7 @@ class CDXLoader {
|
||||
app.$set(app, "snapshots", pywbData.snapshots);
|
||||
app.$set(app, "currentPeriod", pywbData.timeline);
|
||||
|
||||
app.$set(app, "config", {...app.config, ...config});
|
||||
app.$set(app, "config", {...app.config, ...config, prefix: this.prefix});
|
||||
|
||||
app.$mount("#app");
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user