956 Templates to support dark mode

pull/1186/head
tanc 2 years ago
parent 427cf105a3
commit b2da26b2f1

@ -18,13 +18,14 @@
<li><code>tgram://</code> only supports very limited HTML and can fail when extra tags are sent, <a href="https://core.telegram.org/bots/api#html-style">read more here</a> (or use plaintext/markdown format)</li>
</ul>
</div>
<br/>
<div class="notifications-wrapper">
<a id="send-test-notification" class="pure-button button-secondary button-xsmall" style="font-size: 70%">Send test notification</a>
{% if emailprefix %}
{% if emailprefix %}
<a id="add-email-helper" class="pure-button button-secondary button-xsmall" style="font-size: 70%">Add email</a>
{% endif %}
{% endif %}
<a href="{{url_for('notification_logs')}}" class="pure-button button-secondary button-xsmall" style="font-size: 70%">Notification debug logs</a>
</div>
</div>
<div id="notification-customisation" class="pure-control-group">
<div class="pure-control-group">
{{ render_field(form.notification_title, class="m-d notification-title", placeholder=settings_application['notification_title']) }}

@ -1,59 +1,63 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="Self hosted website change detection.">
<!DOCTYPE html>
<html lang="en" data-darkmode="{{ dark_mode|lower }}">
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<meta name="description" content="Self hosted website change detection."/>
<title>Change Detection{{extra_title}}</title>
<link rel="alternate" type="application/rss+xml" title="Changedetection.io » Feed{% if active_tag %}- {{active_tag}}{% endif %}" href="{{ url_for('rss', tag=active_tag , token=app_rss_token)}}" />
<link rel="stylesheet" href="{{url_for('static_content', group='styles', filename='pure-min.css')}}">
<link rel="stylesheet" href="{{url_for('static_content', group='styles', filename='styles.css')}}">
<link rel="alternate" type="application/rss+xml" title="Changedetection.io » Feed{% if active_tag %}- {{active_tag}}{% endif %}" href="{{ url_for('rss', tag=active_tag , token=app_rss_token)}}"/>
<link rel="stylesheet" href="{{url_for('static_content', group='styles', filename='pure-min.css')}}"/>
<link rel="stylesheet" href="{{url_for('static_content', group='styles', filename='styles.css')}}"/>
{% if extra_stylesheets %}
{% for m in extra_stylesheets %}
<link rel="stylesheet" href="{{ m }}?ver=1000">
<link rel="stylesheet" href="{{ m }}?ver=1000"/>
{% endfor %}
{% endif %}
<link rel="apple-touch-icon" sizes="180x180" href="{{url_for('static_content', group='favicons', filename='apple-touch-icon.png')}}">
<link rel="icon" type="image/png" sizes="32x32" href="{{url_for('static_content', group='favicons', filename='favicon-32x32.png')}}">
<link rel="icon" type="image/png" sizes="16x16" href="{{url_for('static_content', group='favicons', filename='favicon-16x16.png')}}">
<link rel="manifest" href="{{url_for('static_content', group='favicons', filename='site.webmanifest')}}">
<link rel="mask-icon" href="{{url_for('static_content', group='favicons', filename='safari-pinned-tab.svg')}}" color="#5bbad5">
<link rel="shortcut icon" href="{{url_for('static_content', group='favicons', filename='favicon.ico')}}">
<meta name="msapplication-TileColor" content="#da532c">
<meta name="msapplication-config" content="favicons/browserconfig.xml">
<meta name="theme-color" content="#ffffff">
<link rel="apple-touch-icon" sizes="180x180" href="{{url_for('static_content', group='favicons', filename='apple-touch-icon.png')}}"/>
<link rel="icon" type="image/png" sizes="32x32" href="{{url_for('static_content', group='favicons', filename='favicon-32x32.png')}}"/>
<link rel="icon" type="image/png" sizes="16x16" href="{{url_for('static_content', group='favicons', filename='favicon-16x16.png')}}"/>
<link rel="manifest" href="{{url_for('static_content', group='favicons', filename='site.webmanifest')}}"/>
<link rel="mask-icon" href="{{url_for('static_content', group='favicons', filename='safari-pinned-tab.svg')}}" color="#5bbad5"/>
<link rel="shortcut icon" href="{{url_for('static_content', group='favicons', filename='favicon.ico')}}"/>
<meta name="msapplication-TileColor" content="#da532c"/>
<meta name="msapplication-config" content="favicons/browserconfig.xml"/>
<meta name="theme-color" content="#ffffff"/>
<style>
body::before {
background-image: url({{url_for('static_content', group='images', filename='gradient-border.png')}});
background-image: url({{url_for('static_content', group='images', filename='gradient-border.png') }});
}
</style>
<script type="text/javascript" src="{{url_for('static_content', group='js', filename='jquery-3.6.0.min.js')}}"></script>
</head>
</head>
<body>
<div class="header">
<body>
<div class="header">
<div class="home-menu pure-menu pure-menu-horizontal pure-menu-fixed" id="nav-menu">
{% if has_password and not current_user.is_authenticated %}
<a class="pure-menu-heading" href="https://github.com/dgtlmoon/changedetection.io" rel="noopener"><strong>Change</strong>Detection.io</a>
<a class="pure-menu-heading" href="https://github.com/dgtlmoon/changedetection.io" rel="noopener">
<strong>Change</strong>Detection.io</a>
{% else %}
<a class="pure-menu-heading" href="{{url_for('index')}}"><strong>Change</strong>Detection.io</a>
<a class="pure-menu-heading" href="{{url_for('index')}}">
<strong>Change</strong>Detection.io</a>
{% endif %}
{% if current_diff_url %}
<a class=current-diff-url href="{{ current_diff_url }}"><span style="max-width: 30%; overflow: hidden;">{{ current_diff_url }}</span></a>
<a class="current-diff-url" href="{{ current_diff_url }}">
<span style="max-width: 30%; overflow: hidden">{{ current_diff_url }}</span></a>
{% else %}
{% if new_version_available and not (has_password and not current_user.is_authenticated) %}
<span id="new-version-text" class="pure-menu-heading"><a href="https://github.com/dgtlmoon/changedetection.io">A new version is available</a></span>
{% if new_version_available and not(has_password and not current_user.is_authenticated) %}
<span id="new-version-text" class="pure-menu-heading">
<a href="https://github.com/dgtlmoon/changedetection.io">A new version is available</a>
</span>
{% endif %}
{% endif %}
<ul class="pure-menu-list" id="top-right-menu">
{% if current_user.is_authenticated or not has_password %}
{% if not current_diff_url %}
{% if not
current_diff_url %}
<li class="pure-menu-item">
<a href="{{ url_for('settings_page')}}" class="pure-menu-link">SETTINGS</a>
</li>
@ -73,49 +77,75 @@
<a class="pure-menu-link" href="https://github.com/dgtlmoon/changedetection.io">Website Change Detection and Notification.</a>
</li>
{% endif %}
{% if current_user.is_authenticated %}
<li class="pure-menu-item"><a href="{{url_for('logout')}}" class="pure-menu-link">LOG OUT</a></li>
<li class="pure-menu-item">
<a href="{{url_for('logout')}}" class="pure-menu-link">LOG OUT</a>
</li>
{% endif %}
<li class="pure-menu-item">
{% if dark_mode %}
{% set darkClass = 'dark' %}
{% endif %}
<li class="pure-menu-item"><a class="github-link" href="https://github.com/dgtlmoon/changedetection.io">
<svg class="octicon octicon-mark-github v-align-middle" height="32" viewBox="0 0 16 16"
version="1.1"
width="32" aria-hidden="true">
<path fill-rule="evenodd"
d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"></path>
</svg>
</a></li>
<button class="toggle-theme {{darkClass}}" type="button">
<span class="visually-hidden">Toggle light/dark mode</span>
<span class="icon-light">
{% include "svgs/light-mode-toggle-icon.svg" %}
</span>
<span class="icon-dark">
{% include "svgs/dark-mode-toggle-icon.svg" %}
</span>
</button>
<a class="github-link" href="https://github.com/dgtlmoon/changedetection.io">
{% include "svgs/github.svg" %}
</a>
</li>
</ul>
</div>
</div>
{% if hosted_sticky %}<div class="sticky-tab" id="hosted-sticky"><a href="https://lemonade.changedetection.io/start?ref={{guid}}">Let us host your instance!</a></div>{% endif %}
{% if left_sticky %}<div class="sticky-tab" id="left-sticky"><a href="{{url_for('preview_page', uuid=uuid)}}">Show current snapshot</a></div> {% endif %}
{% if right_sticky %}<div class="sticky-tab" id="right-sticky">{{ right_sticky }}</div> {% endif %}
<section class="content">
</div>
{% if hosted_sticky %}
<div class="sticky-tab" id="hosted-sticky">
<a href="https://lemonade.changedetection.io/start?ref={{guid}}">Let us host your instance!</a>
</div>
{% endif %}
{% if left_sticky %}
<div class="sticky-tab" id="left-sticky">
<a href="{{url_for('preview_page', uuid=uuid)}}">Show current snapshot</a>
</div>
{% endif %}
{% if right_sticky %}
<div class="sticky-tab" id="right-sticky">{{ right_sticky }}</div>
{% endif %}
<section class="content">
<header>
{% block header %}{% endblock %}
</header>
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
<ul class=messages>
{% with messages = get_flashed_messages(with_categories = true) %}
{% if
messages %}
<ul class="messages">
{% for category, message in messages %}
<li class="{{ category }}">{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
{% endwith %}
{% if session['share-link'] %}
<ul class="messages with-share-link">
<li class="message">Share this link: <span id="share-link">{{ session['share-link'] }}</span> <img style="height: 1em;display:inline-block;" src="{{url_for('static_content', group='images', filename='copy.svg')}}" /></li>
<li class="message">
Share this link:
<span id="share-link">{{ session['share-link'] }}</span>
<img style="height: 1em; display: inline-block" src="{{url_for('static_content', group='images', filename='copy.svg')}}"/>
</li>
</ul>
{% endif %}
{% block content %}{% endblock %}
</section>
<script
type="text/javascript"
src="{{url_for('static_content', group='js', filename='toggle-theme.js')}}"
defer></script>
</body>
{% block content %}
{% endblock %}
</section>
</body>
</html>

@ -1,28 +1,45 @@
{% extends 'base.html' %}
{% block content %}
{% extends 'base.html' %} {% block content %}
<div class="edit-form">
<div class="box-wrap inner">
<form class="pure-form pure-form-stacked" action="{{url_for('clear_all_history')}}" method="POST">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
<form
class="pure-form pure-form-stacked"
action="{{url_for('clear_all_history')}}"
method="POST"
>
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
<fieldset>
<div class="pure-control-group">
This will remove version history (snapshots) for ALL watches, but keep your list of URLs! <br/>
You may like to use the <strong>BACKUP</strong> link first.<br/>
This will remove version history (snapshots) for ALL watches, but keep
your list of URLs! <br />
You may like to use the <strong>BACKUP</strong> link first.<br />
</div>
<br/>
<br />
<div class="pure-control-group">
<label for="confirmtext">Confirmation text</label>
<input type="text" id="confirmtext" required="" name="confirmtext" value="" size="10"/>
<span class="pure-form-message-inline">Type in the word <strong>clear</strong> to confirm that you understand.</span>
<input
type="text"
id="confirmtext"
required=""
name="confirmtext"
value=""
size="10"
/>
<span class="pure-form-message-inline"
>Type in the word <strong>clear</strong> to confirm that you
understand.</span
>
</div>
<br/>
<br />
<div class="pure-control-group">
<button type="submit" class="pure-button pure-button-primary">Clear History!</button>
<button type="submit" class="pure-button pure-button-primary">
Clear History!
</button>
</div>
<br/>
<br />
<div class="pure-control-group">
<a href="{{url_for('index')}}" class="pure-button button-small button-cancel">Cancel</a>
<a href="{{url_for('index')}}" class="pure-button button-cancel"
>Cancel</a
>
</div>
</fieldset>
</form>

@ -1,72 +1,130 @@
{% 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>
{% 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 %}
{% if emailprefix %}
const email_notification_prefix=JSON.parse('{{ emailprefix|tojson }}');
{% endif %}
{% 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>
<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>
<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>
<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 &amp; Triggers</a></li>
<li class="tab">
<a id="visualselector-tab" href="#visualselector"
>Visual Filter Selector</a
>
</li>
<li class="tab">
<a href="#filters-and-triggers">Filters &amp; 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() }}"/>
<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/>
{{ 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>
<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>
{{ 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>
<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">
@ -75,7 +133,9 @@
<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.
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>
@ -85,9 +145,20 @@
<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>
<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 %}
@ -105,48 +176,59 @@
<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>
<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>
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>
<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") }}
{{ 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
}") }}
{{ 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')}}">
<img
class="beta-logo"
src="{{url_for('static_content', group='images', filename='beta-logo.png')}}"
/>
<fieldset>
<div class="pure-control-group">
<!--
@ -156,29 +238,58 @@ User-Agent: wonderbra 1.0") }}
-->
<!--- 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 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" >
<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>
<h2>Click here to Start</h2>
Please allow 10-15 seconds for the browser to connect.
</span>
<div class="spinner" style="display: none;"></div>
<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>
<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>
@ -196,146 +307,276 @@ User-Agent: wonderbra 1.0") }}
<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.
<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 &dash; an empty Notification URL list here will still send notifications.
<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 &dash; 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>
<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) }}
{{ 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/>
<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>
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>
<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 &lt;element&gt; contains &lt;![CDATA[]]&gt;</strong></span><br/>
{% 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 &lt;element&gt;
contains &lt;![CDATA[]]&gt;</strong
></span
><br />
{% endif %}
<span class="pure-form-message-inline">One rule per line, <i>any</i> rules that matches will be used.<br/>
<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).
<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>
<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>
<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,
<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>
<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/>
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") }}
{{ 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>
<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
") }}
{{ 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>
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
") }}
{{ 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>
<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") }}
{{ 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>
<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") }}
{{ 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;
<li>
Extracts text in the final output (line by line) after other
filters using regular expressions;
<ul>
<li>Regular expression &dash; 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 &dash; example <code>Out of stock</code></li>
<li>Use groups to extract just that text &dash; example <code>/reports.+?(\d+)/i</code> returns a list of years only</li>
<li>
Regular expression &dash; 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 &dash; example <code>Out of stock</code>
</li>
<li>
Use groups to extract just that text &dash; example
<code>/reports.+?(\d+)/i</code> returns a list of years
only
</li>
</ul>
</li>
<li>One line per regular-expression/ string match</li>
@ -346,18 +587,30 @@ Unavailable") }}
</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')}}">
<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 &dash; after the <i>Browser Steps</i> has completed.<br/><br/>
The Visual Selector tool lets you select the <i>text</i> elements
that will be used for the change detection &dash; 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>
<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 -->
@ -366,12 +619,27 @@ Unavailable") }}
<img id="selector-background" />
<canvas id="selector-canvas"></canvas>
</div>
<div id="selector-current-xpath" style="overflow-x: hidden"><strong>Currently:</strong>&nbsp;<span class="text">Loading...</span></div>
<div id="selector-current-xpath" style="overflow-x: hidden">
<strong>Currently:</strong>&nbsp;<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>
<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>
@ -381,12 +649,19 @@ Unavailable") }}
<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-small button-error ">Delete</a>
<a href="{{url_for('clear_watch_history', uuid=uuid)}}"
class="pure-button button-small button-error ">Clear History</a>
<a href="{{url_for('form_clone', uuid=uuid)}}"
class="pure-button button-small ">Create Copy</a>
<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>

@ -1,18 +1,28 @@
{% 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 %}
{% 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>
const notification_base_url="{{url_for('ajax_callback_send_notification_test')}}";
{% if emailprefix %}
{% if emailprefix %}
const email_notification_prefix=JSON.parse('{{emailprefix|tojson}}');
{% endif %}
{% endif %}
</script>
<script type="text/javascript" src="{{url_for('static_content', group='js', filename='tabs.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='tabs.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='global-settings.js')}}" defer></script>
<script
type="text/javascript"
src="{{url_for('static_content', group='js', filename='global-settings.js')}}"
defer
></script>
<div class="edit-form">
<div class="tabs collapsable">
<ul>
@ -24,58 +34,91 @@
</ul>
</div>
<div class="box-wrap inner">
<form class="pure-form pure-form-stacked settings" action="{{url_for('settings_page')}}" method="POST">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
<form
class="pure-form pure-form-stacked settings"
action="{{url_for('settings_page')}}"
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.requests.form.time_between_check, class="time-check-widget") }}
<span class="pure-form-message-inline">Default time for all watches, when the watch does not have a specific time setting.</span>
{{ render_field(form.requests.form.time_between_check,
class="time-check-widget") }}
<span class="pure-form-message-inline"
>Default time for all watches, when the watch does not have a
specific time setting.</span
>
</div>
<div class="pure-control-group">
{{ render_field(form.requests.form.jitter_seconds, class="jitter_seconds") }}
<span class="pure-form-message-inline">Example - 3 seconds random jitter could trigger up to 3 seconds earlier or up to 3 seconds later</span>
{{ render_field(form.requests.form.jitter_seconds,
class="jitter_seconds") }}
<span class="pure-form-message-inline"
>Example - 3 seconds random jitter could trigger up to 3 seconds
earlier or up to 3 seconds later</span
>
</div>
<div class="pure-control-group">
{{ render_field(form.application.form.filter_failure_notification_threshold_attempts, class="filter_failure_notification_threshold_attempts") }}
<span class="pure-form-message-inline">After this many consecutive times that the CSS/xPath filter is missing, send a notification
<br/>
{{
render_field(form.application.form.filter_failure_notification_threshold_attempts,
class="filter_failure_notification_threshold_attempts") }}
<span class="pure-form-message-inline"
>After this many consecutive times that the CSS/xPath filter is
missing, send a notification
<br />
Set to <strong>0</strong> to disable
</span>
</div>
<div class="pure-control-group">
{% if not hide_remove_pass %}
{% if current_user.is_authenticated %}
{{ render_button(form.application.form.removepassword_button) }}
{% else %}
{{ render_field(form.application.form.password) }}
<span class="pure-form-message-inline">Password protection for your changedetection.io application.</span>
{% endif %}
{% else %}
{% if not hide_remove_pass %} {% if current_user.is_authenticated %}
{{ render_button(form.application.form.removepassword_button) }} {%
else %} {{ render_field(form.application.form.password) }}
<span class="pure-form-message-inline"
>Password protection for your changedetection.io
application.</span
>
{% endif %} {% else %}
<span class="pure-form-message-inline">Password is locked.</span>
{% endif %}
</div>
<div class="pure-control-group">
{{ render_field(form.application.form.base_url, placeholder="http://yoursite.com:5000/",
class="m-d") }}
{{ render_field(form.application.form.base_url,
placeholder="http://yoursite.com:5000/", class="m-d") }}
<span class="pure-form-message-inline">
Base URL used for the <code>{base_url}</code> token in notifications and RSS links.<br/>Default value is the ENV var 'BASE_URL' (Currently "{{settings_application['current_base_url']}}"),
<a href="https://github.com/dgtlmoon/changedetection.io/wiki/Configurable-BASE_URL-setting">read more here</a>.
Base URL used for the <code>{base_url}</code> token in
notifications and RSS links.<br />Default value is the ENV var
'BASE_URL' (Currently
"{{settings_application['current_base_url']}}"),
<a
href="https://github.com/dgtlmoon/changedetection.io/wiki/Configurable-BASE_URL-setting"
>read more here</a
>.
</span>
</div>
<div class="pure-control-group">
{{ render_checkbox_field(form.application.form.extract_title_as_title) }}
<span class="pure-form-message-inline">Note: This will automatically apply to all existing watches.</span>
{{
render_checkbox_field(form.application.form.extract_title_as_title)
}}
<span class="pure-form-message-inline"
>Note: This will automatically apply to all existing
watches.</span
>
</div>
<div class="pure-control-group">
{{ render_checkbox_field(form.application.form.empty_pages_are_a_change) }}
<span class="pure-form-message-inline">When a page contains HTML, but no renderable text appears (empty page), is this considered a change?</span>
{{
render_checkbox_field(form.application.form.empty_pages_are_a_change)
}}
<span class="pure-form-message-inline"
>When a page contains HTML, but no renderable text appears (empty
page), is this considered a change?</span
>
</div>
{% if form.requests.proxy %}
<div class="pure-control-group inline-radio">
{{ render_field(form.requests.form.proxy, class="fetch-backend-proxy") }}
{{ render_field(form.requests.form.proxy,
class="fetch-backend-proxy") }}
<span class="pure-form-message-inline">
Choose a default proxy for all watches
</span>
@ -87,25 +130,42 @@
<div class="tab-pane-inner" id="notifications">
<fieldset>
<div class="field-group">
{{ render_common_settings_form(form.application.form, emailprefix, settings_application) }}
{{ render_common_settings_form(form.application.form, emailprefix,
settings_application) }}
</div>
</fieldset>
</div>
<div class="tab-pane-inner" id="fetching">
<div class="pure-control-group inline-radio">
{{ render_field(form.application.form.fetch_backend, class="fetch-backend") }}
{{ render_field(form.application.form.fetch_backend,
class="fetch-backend") }}
<span class="pure-form-message-inline">
<p>Use the <strong>Basic</strong> method (default) where your watched sites don'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>
<p>
Use the <strong>Basic</strong> method (default) where your watched
sites don'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>
</span>
<br/>
Tip: <a href="https://github.com/dgtlmoon/changedetection.io/wiki/Proxy-configuration#brightdata-proxy-support">Connect using BrightData Proxies, find out more here.</a>
<br />
Tip:
<a
href="https://github.com/dgtlmoon/changedetection.io/wiki/Proxy-configuration#brightdata-proxy-support"
>Connect using BrightData Proxies, find out more here.</a
>
</div>
<fieldset class="pure-group" id="webdriver-override-options">
<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/>
<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.
</div>
<div class="pure-control-group">
@ -115,43 +175,68 @@
</div>
<div class="tab-pane-inner" id="filters">
<fieldset class="pure-group">
{{ render_checkbox_field(form.application.form.ignore_whitespace) }}
<span class="pure-form-message-inline">Ignore whitespace, tabs and new-lines/line-feeds when considering if a change was detected.<br/>
<i>Note:</i> Changing this will change the status of your existing watches, possibly trigger alerts etc.
<span class="pure-form-message-inline"
>Ignore whitespace, tabs and new-lines/line-feeds when considering
if a change was detected.<br />
<i>Note:</i> Changing this will change the status of your existing
watches, possibly trigger alerts etc.
</span>
</fieldset>
<fieldset class="pure-group">
{{ render_checkbox_field(form.application.form.render_anchor_tag_content) }}
<span class="pure-form-message-inline">Render anchor tag content, default disabled, when enabled renders links as <code>(link text)[https://somesite.com]</code>
<br/>
<i>Note:</i> Changing this could affect the content of your existing watches, possibly trigger alerts etc.
{{
render_checkbox_field(form.application.form.render_anchor_tag_content)
}}
<span class="pure-form-message-inline"
>Render anchor tag content, default disabled, when enabled renders
links as <code>(link text)[https://somesite.com]</code>
<br />
<i>Note:</i> Changing this could affect the content of your existing
watches, possibly trigger alerts etc.
</span>
</fieldset>
<fieldset class="pure-group">
{{ render_field(form.application.form.global_subtractive_selectors, rows=5, placeholder="header
footer
nav
.stockticker") }}
{{ render_field(form.application.form.global_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>
<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>
</fieldset>
<fieldset class="pure-group">
{{ render_field(form.application.form.global_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">Note: This is applied globally in addition to the per-watch rules.</span><br/>
{{ render_field(form.application.form.global_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"
>Note: This is applied globally in addition to the per-watch
rules.</span
><br />
<span class="pure-form-message-inline">
<ul>
<li>Note: This is applied globally in addition to the per-watch rules.</li>
<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>
Note: This is applied globally in addition to the per-watch
rules.
</li>
<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>
@ -159,14 +244,25 @@ nav
</div>
<div class="tab-pane-inner" id="api">
<p>Drive your changedetection.io via API, More about <a href="https://github.com/dgtlmoon/changedetection.io/wiki/API-Reference">API access here</a></p>
<p>
Drive your changedetection.io via API, More about
<a
href="https://github.com/dgtlmoon/changedetection.io/wiki/API-Reference"
>API access here</a
>
</p>
<div class="pure-control-group">
{{ render_checkbox_field(form.application.form.api_access_token_enabled) }}
<div class="pure-form-message-inline">Restrict API access limit by using <code>x-api-key</code> header</div><br/>
<div class="pure-form-message-inline"><br/>API Key <span id="api-key">{{api_key}}</span>
<span style="display:none;" id="api-key-copy" >copy</span>
{{
render_checkbox_field(form.application.form.api_access_token_enabled)
}}
<div class="pure-form-message-inline">
Restrict API access limit by using <code>x-api-key</code> header
</div>
<br />
<div class="pure-form-message-inline">
<br />API Key <span id="api-key">{{api_key}}</span>
<span style="display: none" id="api-key-copy">copy</span>
</div>
</div>
</div>
@ -174,10 +270,15 @@ nav
<div id="actions">
<div class="pure-control-group">
{{ render_button(form.save_button) }}
<a href="{{url_for('index')}}" class="pure-button button-small button-cancel">Back</a>
<a href="{{url_for('clear_all_history')}}" class="pure-button button-small button-cancel">Clear Snapshot History</a>
<a href="{{url_for('index')}}" class="pure-button button-cancel"
>Back</a
>
<a
href="{{url_for('clear_all_history')}}"
class="pure-button button-cancel"
>Clear Snapshot History</a
>
</div>
</div>
</form>
</div>

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" shape-rendering="geometricPrecision" text-rendering="geometricPrecision" image-rendering="optimizeQuality" fill-rule="evenodd" clip-rule="evenodd" viewBox="0 0 512 262.86"><path fill-rule="nonzero" d="M316.78 16.55h-205.9c-30.5 0-58.22 12.48-78.31 32.57C12.47 69.21 0 96.93 0 127.44c0 30.5 12.47 58.22 32.57 78.31 20.09 20.1 47.81 32.57 78.31 32.57h193.25c21.54 15.43 47.9 24.54 76.26 24.54h.18c36.14 0 69.02-14.79 92.83-38.6 23.8-23.81 38.6-56.67 38.6-92.83 0-36.15-14.78-69.03-38.63-92.8C449.53 14.8 416.67 0 380.57 0h-.18c-23.02 0-44.72 6.02-63.61 16.55zm70.62 97.17.43.09c.82-3.45 2.83-6.19 6.04-8.16 3.2-1.98 6.53-2.57 10.01-1.75l.1-.43c-3.47-.82-6.2-2.83-8.17-6.03-1.98-3.22-2.57-6.55-1.75-10.01l-.43-.1c-.82 3.47-2.83 6.2-6.03 8.18-3.21 1.98-6.55 2.56-10.02 1.74l-.1.43c3.47.82 6.2 2.84 8.18 6.04 1.99 3.19 2.56 6.52 1.74 10zm36.87 16.77.53.12c1.02-4.35 3.55-7.78 7.58-10.26 4.02-2.49 8.2-3.22 12.56-2.19l.13-.53c-4.35-1.03-7.78-3.55-10.26-7.59-2.49-4.03-3.22-8.22-2.2-12.56l-.53-.12c-1.02 4.35-3.55 7.77-7.58 10.26-4.02 2.49-8.21 3.22-12.56 2.19l-.13.53c4.36 1.03 7.78 3.55 10.26 7.58 2.49 4.02 3.22 8.22 2.2 12.57zm-38.79-61.01c-15.69 7.67-26.98 23.26-28.29 41.93-1.96 27.88 19.05 52.06 46.92 54.02 13.23.93 25.64-3.32 35.22-11.02 4.75-3.82 9.66-.45 7.59 4.36-11.33 26.42-38.45 44.04-68.74 41.91-38.29-2.69-67.14-35.91-64.45-74.19C316.3 89.8 347.05 61.67 383.44 62c6.71.06 8.13 4.5 2.04 7.48zm-5.09-53.95h.18c63.75 0 115.91 52.15 115.91 115.9 0 63.75-52.23 115.91-115.91 115.91h-.18c-63.68 0-115.91-52.16-115.91-115.91s52.16-115.9 115.91-115.9z"/></svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

@ -0,0 +1,3 @@
<svg class="octicon octicon-mark-github v-align-middle" height="32" viewbox="0 0 16 16" version="1.1" width="32" aria-hidden="true">
<path fill-rule="evenodd" d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"></path>
</svg>

After

Width:  |  Height:  |  Size: 749 B

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" shape-rendering="geometricPrecision" text-rendering="geometricPrecision" image-rendering="optimizeQuality" fill-rule="evenodd" clip-rule="evenodd" viewBox="0 0 512 256.04"><path d="M128.02 0h.18c22.03 0 42.83 5.66 61 15.6h210.38c30.89 0 59 12.65 79.38 33.04C499.35 68.99 512 97.1 512 128.02c0 30.92-12.66 59.03-33.02 79.4l-.42.38c-20.34 20.15-48.29 32.64-78.98 32.64H189.24c-18.17 9.93-38.98 15.6-61.04 15.6h-.18c-35.2 0-67.22-14.41-90.42-37.6C14.41 195.25 0 163.24 0 128.02s14.4-67.24 37.59-90.43l.91-.83C61.65 14.05 93.29 0 128.02 0zm-5.95 54.42c0-1.95.8-3.73 2.08-5 2.74-2.77 7.27-2.76 10.02-.01l.14.16a7.042 7.042 0 0 1 1.94 4.85v12.95c0 1.95-.8 3.73-2.08 5.01-2.75 2.75-7.27 2.75-10.02 0a7.084 7.084 0 0 1-2.08-5.01V54.42zm6.05 31.17c11.72 0 22.32 4.75 30 12.43 7.67 7.68 12.43 18.29 12.43 30 0 11.72-4.75 22.32-12.43 30s-18.28 12.43-30 12.43c-11.72 0-22.32-4.75-30.01-12.43-7.67-7.68-12.43-18.28-12.43-30 0-11.72 4.76-22.32 12.43-30 7.69-7.67 18.3-12.43 30.01-12.43zm-56.33-5.34a7.114 7.114 0 0 1-2.07-5.01c0-3.9 3.18-7.09 7.09-7.09 1.81 0 3.62.69 5 2.07l9.16 9.16a7.065 7.065 0 0 1 2.08 5.01c0 1.8-.7 3.62-2.08 5.01a7.057 7.057 0 0 1-5.01 2.08c-1.8 0-3.61-.7-5-2.07l-9.17-9.16zm-17.28 53.81c-1.95 0-3.73-.8-5-2.08-2.77-2.74-2.76-7.27-.01-10.01l.15-.14a7.04 7.04 0 0 1 4.86-1.94h12.94a7.082 7.082 0 0 1 7.09 7.09c0 1.95-.8 3.73-2.07 5.01a7.099 7.099 0 0 1-5.02 2.07H54.51zm25.82 50.28a7.049 7.049 0 0 1-5 2.07c-3.91 0-7.09-3.16-7.09-7.08 0-1.81.68-3.62 2.07-5.01l9.31-9.29a7.02 7.02 0 0 1 4.86-1.94 7.09 7.09 0 0 1 7.09 7.09c0 1.79-.69 3.6-2.08 4.99l-9.16 9.17zm53.82 17.29c0 1.94-.8 3.73-2.08 5-2.74 2.76-7.27 2.75-10.02 0l-.13-.15a7.033 7.033 0 0 1-1.94-4.85v-12.95c0-1.96.8-3.73 2.07-5.01 2.76-2.75 7.27-2.75 10.03 0a7.1 7.1 0 0 1 2.07 5.01v12.95zm50.28-25.83a7.055 7.055 0 0 1 2.07 5.01c0 3.89-3.18 7.09-7.08 7.09-1.81 0-3.63-.69-5.01-2.07l-9.16-9.16a7.095 7.095 0 0 1-2.07-5.02c0-3.9 3.18-7.09 7.08-7.09 1.8 0 3.61.7 5 2.08l9.17 9.16zm17.29-53.82c1.93 0 3.73.81 5 2.08 2.76 2.75 2.75 7.27 0 10.02l-.15.14a7.098 7.098 0 0 1-4.85 1.94h-12.95c-1.96 0-3.74-.8-5.01-2.08-2.76-2.75-2.76-7.27 0-10.02a7.049 7.049 0 0 1 5.01-2.08h12.95zM175.89 71.7a7.074 7.074 0 0 1 5-2.07c3.9 0 7.1 3.19 7.1 7.09 0 1.81-.69 3.62-2.07 5l-9.32 9.31a7.12 7.12 0 0 1-4.86 1.93c-3.91 0-7.09-3.18-7.09-7.09 0-1.8.7-3.61 2.08-5l9.16-9.17zm34.17-41.87c2.96 2.47 5.81 5.07 8.53 7.8 23.22 23.15 37.63 55.17 37.63 90.39s-14.42 67.23-37.6 90.42a130.2 130.2 0 0 1-8.5 7.77h189.46c26.83 0 51.24-10.91 69.02-28.5l.32-.35c17.79-17.79 28.85-42.35 28.85-69.34 0-26.99-11.06-51.55-28.85-69.35-17.77-17.8-42.33-28.84-69.34-28.84H210.06zm-82.04-14.71h.18c62.09 0 112.89 50.81 112.89 112.9 0 62.1-50.86 112.9-112.89 112.9h-.18c-62.03 0-112.9-50.8-112.9-112.9 0-62.09 50.81-112.9 112.9-112.9z"/></svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

@ -80,15 +80,15 @@
<td class="inline checkbox-uuid" ><input name="uuids" type="checkbox" value="{{ watch.uuid}} "/> <span>{{ loop.index }}</span></td>
<td class="inline watch-controls">
{% if not watch.paused %}
<a class="state-off" href="{{url_for('index', op='pause', uuid=watch.uuid, tag=active_tag)}}"><img src="{{url_for('static_content', group='images', filename='pause.svg')}}" alt="Pause checks" title="Pause checks"/></a>
<a class="state-off" href="{{url_for('index', op='pause', uuid=watch.uuid, tag=active_tag)}}"><img src="{{url_for('static_content', group='images', filename='pause.svg')}}" alt="Pause checks" title="Pause checks" class="icon icon-pause"/></a>
{% else %}
<a class="state-on" href="{{url_for('index', op='pause', uuid=watch.uuid, tag=active_tag)}}"><img src="{{url_for('static_content', group='images', filename='play.svg')}}" alt="UnPause checks" title="UnPause checks"/></a>
<a class="state-on" href="{{url_for('index', op='pause', uuid=watch.uuid, tag=active_tag)}}"><img src="{{url_for('static_content', group='images', filename='play.svg')}}" alt="UnPause checks" title="UnPause checks" class="icon icon-unpause"/></a>
{% endif %}
<a class="state-{{'on' if watch.notification_muted}}" href="{{url_for('index', op='mute', uuid=watch.uuid, tag=active_tag)}}"><img src="{{url_for('static_content', group='images', filename='bell-off.svg')}}" alt="Mute notifications" title="Mute notifications"/></a>
<a class="link-mute state-{{'on' if watch.notification_muted else 'off'}}" href="{{url_for('index', op='mute', uuid=watch.uuid, tag=active_tag)}}"><img src="{{url_for('static_content', group='images', filename='bell-off.svg')}}" alt="Mute notifications" title="Mute notifications" class="icon icon-mute"/></a>
</td>
<td class="title-col inline">{{watch.title if watch.title is not none and watch.title|length > 0 else watch.url}}
<a class="external" target="_blank" rel="noopener" href="{{ watch.link.replace('source:','') }}"></a>
<a href="{{url_for('form_share_put_watch', uuid=watch.uuid)}}"><img style="height: 1em;display:inline-block;" src="{{url_for('static_content', group='images', filename='spread.svg')}}" /></a>
<a class="link-spread" href="{{url_for('form_share_put_watch', uuid=watch.uuid)}}"><img style="height: 1em;display:inline-block;" src="{{url_for('static_content', group='images', filename='spread.svg')}}" class="icon icon-spread" /></a>
{%if watch.fetch_backend == "html_webdriver" %}<img style="height: 1em; display:inline-block;" src="{{url_for('static_content', group='images', filename='Google-Chrome-icon.png')}}" />{% endif %}
@ -111,13 +111,13 @@
</td>
<td>
<a {% if watch.uuid in queued_uuids %}disabled="true"{% endif %} href="{{ url_for('form_watch_checknow', uuid=watch.uuid, tag=request.args.get('tag')) }}"
class="recheck pure-button button-small pure-button-primary">{% if watch.uuid in queued_uuids %}Queued{% else %}Recheck{% endif %}</a>
<a href="{{ url_for('edit_page', uuid=watch.uuid)}}" class="pure-button button-small pure-button-primary">Edit</a>
class="recheck pure-button pure-button-primary">{% if watch.uuid in queued_uuids %}Queued{% else %}Recheck{% endif %}</a>
<a href="{{ url_for('edit_page', uuid=watch.uuid)}}" class="pure-button pure-button-primary">Edit</a>
{% if watch.history_n >= 2 %}
<a href="{{ url_for('diff_history_page', uuid=watch.uuid) }}" target="{{watch.uuid}}" class="pure-button button-small pure-button-primary diff-link">Diff</a>
<a href="{{ url_for('diff_history_page', uuid=watch.uuid) }}" target="{{watch.uuid}}" class="pure-button pure-button-primary diff-link">Diff</a>
{% else %}
{% if watch.history_n == 1 or (watch.history_n ==0 and watch.error_text_ctime )%}
<a href="{{ url_for('preview_page', uuid=watch.uuid)}}" target="{{watch.uuid}}" class="pure-button button-small pure-button-primary">Preview</a>
<a href="{{ url_for('preview_page', uuid=watch.uuid)}}" target="{{watch.uuid}}" class="pure-button pure-button-primary">Preview</a>
{% endif %}
{% endif %}
</td>

Loading…
Cancel
Save