You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
674 lines
26 KiB
674 lines
26 KiB
{% extends 'base.html' %} {% block content %} {% from '_helpers.jinja' import
|
|
render_field, render_checkbox_field, render_button %} {% from
|
|
'_common_fields.jinja' import render_common_settings_form %}
|
|
<script
|
|
type="text/javascript"
|
|
src="{{url_for('static_content', group='js', filename='tabs.js')}}"
|
|
defer
|
|
></script>
|
|
<script>
|
|
const notification_base_url="{{url_for('ajax_callback_send_notification_test')}}";
|
|
const watch_visual_selector_data_url="{{url_for('static_content', group='visual_selector_data', filename=uuid)}}";
|
|
const screenshot_url="{{url_for('static_content', group='screenshot', filename=uuid)}}";
|
|
const playwright_enabled={% if playwright_enabled %} true {% else %} false {% endif %};
|
|
|
|
{% if emailprefix %}
|
|
const email_notification_prefix=JSON.parse('{{ emailprefix|tojson }}');
|
|
{% endif %}
|
|
|
|
const browser_steps_config=JSON.parse('{{ browser_steps_config|tojson }}');
|
|
const browser_steps_sync_url="{{url_for('browser_steps.browsersteps_ui_update', uuid=uuid)}}";
|
|
</script>
|
|
|
|
<script
|
|
type="text/javascript"
|
|
src="{{url_for('static_content', group='js', filename='watch-settings.js')}}"
|
|
defer
|
|
></script>
|
|
<script
|
|
type="text/javascript"
|
|
src="{{url_for('static_content', group='js', filename='limit.js')}}"
|
|
defer
|
|
></script>
|
|
<script
|
|
type="text/javascript"
|
|
src="{{url_for('static_content', group='js', filename='notifications.js')}}"
|
|
defer
|
|
></script>
|
|
<script
|
|
type="text/javascript"
|
|
src="{{url_for('static_content', group='js', filename='visual-selector.js')}}"
|
|
defer
|
|
></script>
|
|
{% if playwright_enabled %}
|
|
<script
|
|
type="text/javascript"
|
|
src="{{url_for('static_content', group='js', filename='browser-steps.js')}}"
|
|
defer
|
|
></script>
|
|
{% endif %}
|
|
|
|
<div class="edit-form monospaced-textarea">
|
|
<div class="tabs collapsable">
|
|
<ul>
|
|
<li class="tab" id=""><a href="#general">General</a></li>
|
|
<li class="tab"><a href="#request">Request</a></li>
|
|
{% if playwright_enabled %}
|
|
<li class="tab">
|
|
<a id="browsersteps-tab" href="#browser-steps">Browser Steps</a>
|
|
</li>
|
|
{% endif %}
|
|
<li class="tab">
|
|
<a id="visualselector-tab" href="#visualselector"
|
|
>Visual Filter Selector</a
|
|
>
|
|
</li>
|
|
<li class="tab">
|
|
<a href="#filters-and-triggers">Filters & Triggers</a>
|
|
</li>
|
|
<li class="tab"><a href="#notifications">Notifications</a></li>
|
|
</ul>
|
|
</div>
|
|
|
|
<div class="box-wrap inner">
|
|
<form
|
|
class="pure-form pure-form-stacked"
|
|
action="{{ url_for('edit_page', uuid=uuid, next = request.args.get('next'), unpause_on_save = request.args.get('unpause_on_save')) }}"
|
|
method="POST"
|
|
>
|
|
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
|
|
|
|
<div class="tab-pane-inner" id="general">
|
|
<fieldset>
|
|
<div class="pure-control-group">
|
|
{{ render_field(form.url, placeholder="https://...", required=true,
|
|
class="m-d") }}
|
|
<span class="pure-form-message-inline"
|
|
>Some sites use JavaScript to create the content, for this you
|
|
should
|
|
<a
|
|
href="https://github.com/dgtlmoon/changedetection.io/wiki/Fetching-pages-with-WebDriver"
|
|
>use the Chrome/WebDriver Fetcher</a
|
|
></span
|
|
><br />
|
|
<span class="pure-form-message-inline"
|
|
>You can use variables in the URL, perfect for inserting the
|
|
current date and other logic,
|
|
<a
|
|
href="https://github.com/dgtlmoon/changedetection.io/wiki/Handling-variables-in-the-watched-URL"
|
|
>help and examples here</a
|
|
></span
|
|
><br />
|
|
</div>
|
|
<div class="pure-control-group">
|
|
{{ render_field(form.title, class="m-d") }}
|
|
</div>
|
|
<div class="pure-control-group">
|
|
{{ render_field(form.tag) }}
|
|
<span class="pure-form-message-inline"
|
|
>Organisational tag/group name used in the main listing page</span
|
|
>
|
|
</div>
|
|
<div class="pure-control-group">
|
|
{{ render_field(form.time_between_check, class="time-check-widget")
|
|
}} {% if has_empty_checktime %}
|
|
<span class="pure-form-message-inline"
|
|
>Currently using the
|
|
<a href="{{ url_for('settings_page', uuid=uuid) }}"
|
|
>default global settings</a
|
|
>, change to another value if you want to be specific.</span
|
|
>
|
|
{% else %}
|
|
<span class="pure-form-message-inline"
|
|
>Set to blank to use the
|
|
<a href="{{ url_for('settings_page', uuid=uuid) }}"
|
|
>default global settings</a
|
|
>.</span
|
|
>
|
|
{% endif %}
|
|
</div>
|
|
<div class="pure-control-group">
|
|
{{ render_checkbox_field(form.extract_title_as_title) }}
|
|
</div>
|
|
<div class="pure-control-group">
|
|
{{ render_checkbox_field(form.filter_failure_notification_send) }}
|
|
<span class="pure-form-message-inline">
|
|
Sends a notification when the filter can no longer be seen on the
|
|
page, good for knowing when the page changed and your filter will
|
|
not work anymore.
|
|
</span>
|
|
</div>
|
|
</fieldset>
|
|
</div>
|
|
|
|
<div class="tab-pane-inner" id="request">
|
|
<div class="pure-control-group inline-radio">
|
|
{{ render_field(form.fetch_backend, class="fetch-backend") }}
|
|
<span class="pure-form-message-inline">
|
|
<p>
|
|
Use the <strong>Basic</strong> method (default) where your watched
|
|
site doesn't need Javascript to render.
|
|
</p>
|
|
<p>
|
|
The <strong>Chrome/Javascript</strong> method requires a network
|
|
connection to a running WebDriver+Chrome server, set by the ENV
|
|
var 'WEBDRIVER_URL'.
|
|
</p>
|
|
Tip:
|
|
<a
|
|
href="https://github.com/dgtlmoon/changedetection.io/wiki/Proxy-configuration#brightdata-proxy-support"
|
|
>Connect using BrightData Proxies, find out more here.</a
|
|
>
|
|
</span>
|
|
</div>
|
|
{% if form.proxy %}
|
|
<div class="pure-control-group inline-radio">
|
|
{{ render_field(form.proxy, class="fetch-backend-proxy") }}
|
|
<span class="pure-form-message-inline">
|
|
Choose a proxy for this watch
|
|
</span>
|
|
</div>
|
|
{% endif %}
|
|
<div class="pure-control-group inline-radio">
|
|
{{ render_checkbox_field(form.ignore_status_codes) }}
|
|
</div>
|
|
<fieldset id="webdriver-override-options">
|
|
<div class="pure-control-group">
|
|
{{ render_field(form.webdriver_delay) }}
|
|
<div class="pure-form-message-inline">
|
|
<strong
|
|
>If you're having trouble waiting for the page to be fully
|
|
rendered (text missing etc), try increasing the 'wait' time
|
|
here.</strong
|
|
>
|
|
<br />
|
|
This will wait <i>n</i> seconds before extracting the text. {% if
|
|
using_global_webdriver_wait %} <br /><strong
|
|
>Using the current global default settings</strong
|
|
>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
<div class="pure-control-group">
|
|
{{ render_field(form.webdriver_js_execute_code) }}
|
|
<div class="pure-form-message-inline">
|
|
Run this code before performing change detection, handy for
|
|
filling in fields and other actions
|
|
<a
|
|
href="https://github.com/dgtlmoon/changedetection.io/wiki/Run-JavaScript-before-change-detection"
|
|
>More help and examples here</a
|
|
>
|
|
</div>
|
|
</div>
|
|
</fieldset>
|
|
<fieldset class="pure-group" id="requests-override-options">
|
|
{% if not playwright_enabled %}
|
|
<div class="pure-form-message-inline">
|
|
<strong
|
|
>Request override is currently only used by the
|
|
<i>Basic fast Plaintext/HTTP Client</i> method.</strong
|
|
>
|
|
</div>
|
|
{% endif %}
|
|
<div class="pure-control-group" id="request-method">
|
|
{{ render_field(form.method) }}
|
|
</div>
|
|
<div class="pure-control-group" id="request-headers">
|
|
{{ render_field(form.headers, rows=5, placeholder="Example
|
|
Cookie: foobar User-Agent: wonderbra 1.0") }}
|
|
</div>
|
|
<div class="pure-control-group" id="request-body">
|
|
{{ render_field(form.body, rows=5, placeholder="Example
|
|
{\"name\":\"John\", \"age\":30, \"car\":null }") }}
|
|
</div>
|
|
</fieldset>
|
|
</div>
|
|
{% if playwright_enabled %}
|
|
<div class="tab-pane-inner" id="browser-steps">
|
|
<img
|
|
class="beta-logo"
|
|
src="{{url_for('static_content', group='images', filename='beta-logo.png')}}"
|
|
/>
|
|
<fieldset>
|
|
<div class="pure-control-group">
|
|
<!--
|
|
Too hard right now, better to just send the events to the fetcher for now and leave it in the final screenshot
|
|
and/or report an error
|
|
<a id="play-steps" class="pure-button button-secondary button-xsmall" style="font-size: 70%">Play steps ▶</a>
|
|
-->
|
|
|
|
<!--- Do this later -->
|
|
<div class="checkbox" style="display: none">
|
|
<input type="checkbox" id="include_text_elements" />
|
|
<label for="include_text_elements">Turn on text finder</label>
|
|
</div>
|
|
|
|
<div id="loading-status-text" style="display: none">
|
|
Please wait, first browser step can take a little time to load..
|
|
<div class="spinner"></div>
|
|
</div>
|
|
<div class="flex-wrapper">
|
|
<div
|
|
id="browser-steps-ui"
|
|
class="noselect"
|
|
style="width: 100%; background-color: #eee; border-radius: 5px"
|
|
>
|
|
<div
|
|
class="noselect"
|
|
id="browsersteps-selector-wrapper"
|
|
style="width: 100%"
|
|
>
|
|
<span class="loader">
|
|
<span id="browsersteps-click-start">
|
|
<h2>Click here to Start</h2>
|
|
Please allow 10-15 seconds for the browser to connect.
|
|
</span>
|
|
<div class="spinner" style="display: none"></div>
|
|
</span>
|
|
<img
|
|
class="noselect"
|
|
id="browsersteps-img"
|
|
src=""
|
|
style="max-width: 100%; width: 100%"
|
|
/>
|
|
<canvas
|
|
class="noselect"
|
|
id="browsersteps-selector-canvas"
|
|
style="max-width: 100%; width: 100%"
|
|
></canvas>
|
|
</div>
|
|
</div>
|
|
<div
|
|
id="browser-steps-fieldlist"
|
|
style="padding-left: 1em; width: 350px; font-size: 80%"
|
|
>
|
|
<span id="browserless-seconds-remaining">Loading</span>
|
|
<span style="font-size: 80%">
|
|
(<a
|
|
target="_new"
|
|
href="https://github.com/dgtlmoon/changedetection.io/pull/478/files#diff-1a79d924d1840c485238e66772391268a89c95b781d69091384cf1ea1ac146c9R4"
|
|
>?</a
|
|
>)
|
|
</span>
|
|
{{ render_field(form.browser_steps) }}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</fieldset>
|
|
</div>
|
|
{% endif %}
|
|
|
|
<div class="tab-pane-inner" id="notifications">
|
|
<fieldset>
|
|
<div class="pure-control-group inline-radio">
|
|
{{ render_checkbox_field(form.notification_muted) }}
|
|
</div>
|
|
{% if is_html_webdriver %}
|
|
<div class="pure-control-group inline-radio">
|
|
{{ render_checkbox_field(form.notification_screenshot) }}
|
|
<span class="pure-form-message-inline">
|
|
<strong>Use with caution!</strong> This will easily fill up your
|
|
email storage quota or flood other storages.
|
|
</span>
|
|
</div>
|
|
{% endif %}
|
|
<div class="field-group" id="notification-field-group">
|
|
{% if has_default_notification_urls %}
|
|
<div class="inline-warning">
|
|
<img
|
|
class="inline-warning-icon"
|
|
src="{{url_for('static_content', group='images', filename='notice.svg')}}"
|
|
alt="Look out!"
|
|
title="Lookout!"
|
|
/>
|
|
There are
|
|
<a href="{{ url_for('settings_page')}}#notifications"
|
|
>system-wide notification URLs enabled</a
|
|
>, this form will override notification settings for this watch
|
|
only ‐ an empty Notification URL list here will still send
|
|
notifications.
|
|
</div>
|
|
{% endif %}
|
|
<a
|
|
href="#notifications"
|
|
id="notification-setting-reset-to-default"
|
|
class="pure-button button-xsmall"
|
|
style="
|
|
right: 20px;
|
|
top: 20px;
|
|
position: absolute;
|
|
background-color: #5f42dd;
|
|
border-radius: 4px;
|
|
font-size: 70%;
|
|
color: #fff;
|
|
"
|
|
>Use system defaults</a
|
|
>
|
|
|
|
{{ render_common_settings_form(form, emailprefix,
|
|
settings_application) }}
|
|
</div>
|
|
</fieldset>
|
|
</div>
|
|
|
|
<div class="tab-pane-inner" id="filters-and-triggers">
|
|
<div class="pure-control-group">
|
|
<strong>Pro-tips:</strong><br />
|
|
<ul>
|
|
<li>
|
|
Use the preview page to see your filters and triggers highlighted.
|
|
</li>
|
|
<li>
|
|
Some sites use JavaScript to create the content, for this you
|
|
should
|
|
<a
|
|
href="https://github.com/dgtlmoon/changedetection.io/wiki/Fetching-pages-with-WebDriver"
|
|
>use the Chrome/WebDriver Fetcher</a
|
|
>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<fieldset>
|
|
<div class="pure-control-group">
|
|
{{ render_checkbox_field(form.check_unique_lines) }}
|
|
<span class="pure-form-message-inline"
|
|
>Good for websites that just move the content around, and you want
|
|
to know when NEW content is added, compares new lines against all
|
|
history for this watch.</span
|
|
>
|
|
</div>
|
|
</fieldset>
|
|
<div class="pure-control-group">
|
|
{% set field = render_field(form.include_filters, rows=5,
|
|
placeholder="#example
|
|
xpath://body/div/span[contains(@class, 'example-class')]", class="m-d") %} {{ field }} {% if '/text()' in
|
|
field %}
|
|
<span class="pure-form-message-inline"
|
|
><strong
|
|
>Note!: //text() function does not work where the <element>
|
|
contains <![CDATA[]]></strong
|
|
></span
|
|
><br />
|
|
{% endif %}
|
|
<span class="pure-form-message-inline"
|
|
>One rule per line, <i>any</i> rules that matches will be used.<br />
|
|
<ul>
|
|
<li>
|
|
CSS - Limit text to this CSS rule, only text matching this CSS
|
|
rule is included.
|
|
</li>
|
|
<li>
|
|
JSON - Limit text to this JSON rule, using either
|
|
<a href="https://pypi.org/project/jsonpath-ng/" target="new"
|
|
>JSONPath</a
|
|
>
|
|
or
|
|
<a href="https://stedolan.github.io/jq/" target="new">jq</a> (if
|
|
installed).
|
|
<ul>
|
|
<li>
|
|
JSONPath: Prefix with <code>json:</code>, use
|
|
<code>json:$</code> to force re-formatting if required,
|
|
<a href="https://jsonpath.com/" target="new"
|
|
>test your JSONPath here</a
|
|
>.
|
|
</li>
|
|
{% if jq_support %}
|
|
<li>
|
|
jq: Prefix with <code>jq:</code> and
|
|
<a href="https://jqplay.org/" target="new"
|
|
>test your jq here</a
|
|
>. Using
|
|
<a href="https://stedolan.github.io/jq/" target="new">jq</a>
|
|
allows for complex filtering and processing of JSON data
|
|
with built-in functions, regex, filtering, and more. See
|
|
examples and documentation
|
|
<a href="https://stedolan.github.io/jq/manual/" target="new"
|
|
>here</a
|
|
>.
|
|
</li>
|
|
{% else %}
|
|
<li>jq support not installed</li>
|
|
{% endif %}
|
|
</ul>
|
|
</li>
|
|
<li>
|
|
XPath - Limit text to this XPath rule, simply start with a
|
|
forward-slash,
|
|
<ul>
|
|
<li>
|
|
Example: <code>//*[contains(@class, 'sametext')]</code> or
|
|
<code>xpath://*[contains(@class, 'sametext')]</code>,
|
|
<a href="http://xpather.com/" target="new"
|
|
>test your XPath here</a
|
|
>
|
|
</li>
|
|
<li>
|
|
Example: Get all titles from an RSS feed
|
|
<code>//title/text()</code>
|
|
</li>
|
|
</ul>
|
|
</li>
|
|
</ul>
|
|
Please be sure that you thoroughly understand how to write CSS,
|
|
JSONPath, XPath{% if jq_support %}, or jq selector{%endif%} rules
|
|
before filing an issue on GitHub!
|
|
<a
|
|
href="https://github.com/dgtlmoon/changedetection.io/wiki/CSS-Selector-help"
|
|
>here for more CSS selector help</a
|
|
>.<br />
|
|
</span>
|
|
</div>
|
|
<div class="pure-control-group">
|
|
{{ render_field(form.subtractive_selectors, rows=5,
|
|
placeholder="header footer nav .stockticker") }}
|
|
<span class="pure-form-message-inline">
|
|
<ul>
|
|
<li>
|
|
Remove HTML element(s) by CSS selector before text conversion.
|
|
</li>
|
|
<li>
|
|
Add multiple elements or CSS selectors per line to ignore
|
|
multiple parts of the HTML.
|
|
</li>
|
|
</ul>
|
|
</span>
|
|
</div>
|
|
<fieldset class="pure-group">
|
|
{{ render_field(form.ignore_text, rows=5, placeholder="Some text to ignore in a line /some.regex\d{2}/ for case-INsensitive regex ") }}
|
|
<span class="pure-form-message-inline">
|
|
<ul>
|
|
<li>
|
|
Each line processed separately, any line matching will be
|
|
ignored (removed before creating the checksum)
|
|
</li>
|
|
<li>
|
|
Regular Expression support, wrap the entire line in forward
|
|
slash <code>/regex/</code>
|
|
</li>
|
|
<li>
|
|
Changing this will affect the comparison checksum which may
|
|
trigger an alert
|
|
</li>
|
|
<li>Use the preview/show current tab to see ignores</li>
|
|
</ul>
|
|
</span>
|
|
</fieldset>
|
|
<fieldset>
|
|
<div class="pure-control-group">
|
|
{{ render_field(form.trigger_text, rows=5, placeholder="Some text to wait for in a line /some.regex\d{2}/ for case-INsensitive regex ")
|
|
}}
|
|
<span class="pure-form-message-inline">
|
|
<ul>
|
|
<li>
|
|
Text to wait for before triggering a change/notification, all
|
|
text and regex are tested <i>case-insensitive</i>.
|
|
</li>
|
|
<li>
|
|
Trigger text is processed from the result-text that comes out
|
|
of any CSS/JSON Filters for this watch
|
|
</li>
|
|
<li>
|
|
Each line is processed separately (think of each line as "OR")
|
|
</li>
|
|
<li>
|
|
Note: Wrap in forward slash / to use regex example:
|
|
<code>/foo\d/</code>
|
|
</li>
|
|
</ul>
|
|
</span>
|
|
</div>
|
|
</fieldset>
|
|
<fieldset>
|
|
<div class="pure-control-group">
|
|
{{ render_field(form.text_should_not_be_present, rows=5,
|
|
placeholder="For example:
|
|
|
|
Out of stock
|
|
Sold out
|
|
Not in stock
|
|
Unavailable") }}
|
|
<span class="pure-form-message-inline">
|
|
<ul>
|
|
<li>
|
|
Block change-detection while this text is on the page, all
|
|
text and regex are tested <i>case-insensitive</i>, good for
|
|
waiting for when a product is available again
|
|
</li>
|
|
<li>
|
|
Block text is processed from the result-text that comes out of
|
|
any CSS/JSON Filters for this watch
|
|
</li>
|
|
<li>
|
|
All lines here must not exist (think of each line as "OR")
|
|
</li>
|
|
<li>
|
|
Note: Wrap in forward slash / to use regex example:
|
|
<code>/foo\d/</code>
|
|
</li>
|
|
</ul>
|
|
</span>
|
|
</div>
|
|
</fieldset>
|
|
<fieldset>
|
|
<div class="pure-control-group">
|
|
{{ render_field(form.extract_text, rows=5, placeholder="\d+ online")
|
|
}}
|
|
<span class="pure-form-message-inline">
|
|
<ul>
|
|
<li>
|
|
Extracts text in the final output (line by line) after other
|
|
filters using regular expressions;
|
|
<ul>
|
|
<li>
|
|
Regular expression ‐ example
|
|
<code>/reports.+?2022/i</code>
|
|
</li>
|
|
<li>
|
|
Use <code>//(?aiLmsux))</code> type flags (more
|
|
<a
|
|
href="https://docs.python.org/3/library/re.html#index-15"
|
|
>information here</a
|
|
>)<br />
|
|
</li>
|
|
<li>
|
|
Keyword example ‐ example <code>Out of stock</code>
|
|
</li>
|
|
<li>
|
|
Use groups to extract just that text ‐ example
|
|
<code>/reports.+?(\d+)/i</code> returns a list of years
|
|
only
|
|
</li>
|
|
</ul>
|
|
</li>
|
|
<li>One line per regular-expression/ string match</li>
|
|
</ul>
|
|
</span>
|
|
</div>
|
|
</fieldset>
|
|
</div>
|
|
|
|
<div class="tab-pane-inner visual-selector-ui" id="visualselector">
|
|
<img
|
|
class="beta-logo"
|
|
src="{{url_for('static_content', group='images', filename='beta-logo.png')}}"
|
|
/>
|
|
|
|
<fieldset>
|
|
<div class="pure-control-group">
|
|
{% if visualselector_enabled %}
|
|
<span class="pure-form-message-inline">
|
|
The Visual Selector tool lets you select the <i>text</i> elements
|
|
that will be used for the change detection ‐ after the
|
|
<i>Browser Steps</i> has completed.<br /><br />
|
|
</span>
|
|
|
|
<div id="selector-header">
|
|
<a
|
|
id="clear-selector"
|
|
class="pure-button button-secondary button-xsmall"
|
|
style="font-size: 70%"
|
|
>Clear selection</a
|
|
>
|
|
<i class="fetching-update-notice" style="font-size: 80%"
|
|
>One moment, fetching screenshot and element information..</i
|
|
>
|
|
</div>
|
|
<div id="selector-wrapper" style="display: none">
|
|
<!-- request the screenshot and get the element offset info ready -->
|
|
<!-- use img src ready load to know everything is ready to map out -->
|
|
<!-- @todo: maybe something interesting like a field to select 'elements that contain text... and their parents n' -->
|
|
<img id="selector-background" />
|
|
<canvas id="selector-canvas"></canvas>
|
|
</div>
|
|
<div id="selector-current-xpath" style="overflow-x: hidden">
|
|
<strong>Currently:</strong> <span class="text"
|
|
>Loading...</span
|
|
>
|
|
</div>
|
|
{% else %}
|
|
<span class="pure-form-message-inline">
|
|
<p>
|
|
Sorry, this functionality only works with Playwright/Chrome
|
|
enabled watches.
|
|
</p>
|
|
<p>
|
|
Enable the Playwright Chrome fetcher, or alternatively try our
|
|
<a href="https://lemonade.changedetection.io/start"
|
|
>very affordable subscription based service</a
|
|
>.
|
|
</p>
|
|
<p>
|
|
This is because Selenium/WebDriver can not extract full page
|
|
screenshots reliably.
|
|
</p>
|
|
</span>
|
|
{% endif %}
|
|
</div>
|
|
</fieldset>
|
|
</div>
|
|
|
|
<div id="actions">
|
|
<div class="pure-control-group">
|
|
{{ render_button(form.save_button) }}
|
|
<a
|
|
href="{{url_for('form_delete', uuid=uuid)}}"
|
|
class="pure-button button-warning"
|
|
>Delete</a
|
|
>
|
|
<a
|
|
href="{{url_for('clear_watch_history', uuid=uuid)}}"
|
|
class="pure-button button-warning"
|
|
>Clear History</a
|
|
>
|
|
<a href="{{url_for('form_clone', uuid=uuid)}}" class="pure-button"
|
|
>Create Copy</a
|
|
>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
{% endblock %}
|