mirror of
https://github.com/dgtlmoon/changedetection.io.git
synced 2026-05-06 01:31:06 +00:00
3d14df6a11
Multi-language / Translations Support (#3696) - Complete internationalization system implemented - Support for 7 languages: Czech (cs), German (de), French (fr), Italian (it), Korean (ko), Chinese Simplified (zh), Chinese Traditional (zh_TW) - Language selector with localized flags and theming - Flash message translations - Multiple translation fixes and improvements across all languages - Language setting preserved across redirects Pluggable Content Fetchers (#3653) - New architecture for extensible content fetcher system - Allows custom fetcher implementations Image / Screenshot Comparison Processor (#3680) - New processor for visual change detection (disabled for this release) - Supporting CSS/JS infrastructure added UI Improvements Design & Layout - Auto-generated tag color schemes - Simplified login form styling - Removed hard-coded CSS, moved to SCSS variables - Tag UI cleanup and improvements - Automatic tab wrapper functionality - Menu refactoring for better organization - Cleanup of offset settings - Hide sticky tabs on narrow viewports - Improved responsive layout (#3702) User Experience - Modal alerts/confirmations on delete/clear operations (#3693, #3598, #3382) - Auto-add https:// to URLs in quickwatch form if not present - Better redirect handling on login (#3699) - 'Recheck all' now returns to correct group/tag (#3673) - Language set redirect keeps hash fragment - More friendly human-readable text throughout UI Performance & Reliability Scheduler & Processing - Soft delays instead of blocking time.sleep() calls (#3710) - More resilient handling of same UUID being processed (#3700) - Better Puppeteer timeout handling - Improved Puppeteer shutdown/cleanup (#3692) - Requests cleanup now properly async History & Rendering - Faster server-side "difference" rendering on History page (#3442) - Show ignored/triggered rows in history - API: Retry watch data if watch dict changed (more reliable) API Improvements - Watch get endpoint: retry mechanism for changed watch data - WatchHistoryDiff API endpoint includes extra format args (#3703) Testing Improvements - Replace time.sleep with wait_for_notification_endpoint_output (#3716) - Test for mode switching (#3701) - Test for #3720 added (#3725) - Extract-text difference test fixes - Improved dev workflow Bug Fixes - Notification error text output (#3672, #3669, #3280) - HTML validation fixes (#3704) - Template discovery path fixes - Notification debug log now uses system locale for dates/times - Puppeteer spelling mistake in log output - Recalculation on anchor change - Queue bubble update disabled temporarily Dependency Updates - beautifulsoup4 updated (#3724) - psutil 7.1.0 → 7.2.1 (#3723) - python-engineio ~=4.12.3 → ~=4.13.0 (#3707) - python-socketio ~=5.14.3 → ~=5.16.0 (#3706) - flask-socketio ~=5.5.1 → ~=5.6.0 (#3691) - brotli ~=1.1 → ~=1.2 (#3687) - lxml updated (#3590) - pytest ~=7.2 → ~=9.0 (#3676) - jsonschema ~=4.0 → ~=4.25 (#3618) - pluggy ~=1.5 → ~=1.6 (#3616) - cryptography 44.0.1 → 46.0.3 (security) (#3589) Documentation - README updated with viewport size setup information Development Infrastructure - Dev container only built on dev branch - Improved dev workflow tooling
122 lines
6.6 KiB
HTML
122 lines
6.6 KiB
HTML
{% extends 'base.html' %}
|
|
{% block content %}
|
|
{% from '_helpers.html' import render_field %}
|
|
<script src="{{url_for('static_content', group='js', filename='tabs.js')}}" defer></script>
|
|
<div class="edit-form monospaced-textarea">
|
|
|
|
<div class="tabs collapsable">
|
|
<ul>
|
|
<li class="tab" id=""><a href="#url-list">{{ _('URL List') }}</a></li>
|
|
<li class="tab"><a href="#distill-io">{{ _('Distill.io') }}</a></li>
|
|
<li class="tab"><a href="#xlsx">{{ _('.XLSX & Wachete') }}</a></li>
|
|
</ul>
|
|
</div>
|
|
|
|
<div class="box-wrap inner">
|
|
<form class="pure-form" action="{{url_for('imports.import_page')}}" method="POST" enctype="multipart/form-data">
|
|
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
|
|
<div class="tab-pane-inner" id="url-list">
|
|
<div class="pure-control-group">
|
|
{{ _('Enter one URL per line, and optionally add tags for each URL after a space, delineated by comma (,):') }}
|
|
<br>
|
|
<p><strong>{{ _('Example:') }} </strong><code>https://example.com tag1, tag2, last tag</code></p>
|
|
{{ _('URLs which do not pass validation will stay in the textarea.') }}
|
|
</div>
|
|
{{ render_field(form.processor, class="processor") }}
|
|
|
|
<div class="pure-control-group">
|
|
<textarea name="urls" class="pure-input-1-2" placeholder="https://"
|
|
style="width: 100%;
|
|
font-family:monospace;
|
|
white-space: pre;
|
|
overflow-wrap: normal;
|
|
overflow-x: scroll;" rows="25">{{ import_url_list_remaining }}</textarea>
|
|
</div>
|
|
<div id="quick-watch-processor-type"></div>
|
|
|
|
</div>
|
|
|
|
<div class="tab-pane-inner" id="distill-io">
|
|
|
|
|
|
|
|
<div class="pure-control-group">
|
|
{{ _('Copy and Paste your Distill.io watch \'export\' file, this should be a JSON file.') }}<br>
|
|
{{ _('This is') }} <i>{{ _('experimental') }}</i>, {{ _('supported fields are') }} <code>name</code>, <code>uri</code>, <code>tags</code>, <code>config:selections</code>, {{ _('the rest (including') }} <code>schedule</code>) {{ _('are ignored.') }}
|
|
<br>
|
|
<p>
|
|
{{ _('How to export?') }} <a href="https://distill.io/docs/web-monitor/how-export-and-import-monitors/">https://distill.io/docs/web-monitor/how-export-and-import-monitors/</a><br>
|
|
{{ _('Be sure to set your default fetcher to Chrome if required.') }}<br>
|
|
</p>
|
|
</div>
|
|
|
|
|
|
<textarea name="distill-io" class="pure-input-1-2" style="width: 100%;
|
|
font-family:monospace;
|
|
white-space: pre;
|
|
overflow-wrap: normal;
|
|
overflow-x: scroll;" placeholder="Example Distill.io JSON export file
|
|
|
|
{
|
|
"client": {
|
|
"local": 1
|
|
},
|
|
"data": [
|
|
{
|
|
"name": "Unraid | News",
|
|
"uri": "https://unraid.net/blog",
|
|
"config": "{\"selections\":[{\"frames\":[{\"index\":0,\"excludes\":[],\"includes\":[{\"type\":\"xpath\",\"expr\":\"(//div[@id='App']/div[contains(@class,'flex')]/main[contains(@class,'relative')]/section[contains(@class,'relative')]/div[@class='container']/div[contains(@class,'flex')]/div[contains(@class,'w-full')])[1]\"}]}],\"dynamic\":true,\"delay\":2}],\"ignoreEmptyText\":true,\"includeStyle\":false,\"dataAttr\":\"text\"}",
|
|
"tags": [],
|
|
"content_type": 2,
|
|
"state": 40,
|
|
"schedule": "{\"type\":\"INTERVAL\",\"params\":{\"interval\":4447}}",
|
|
"ts": "2022-03-27T15:51:15.667Z"
|
|
}
|
|
]
|
|
}
|
|
" rows="25">{{ original_distill_json }}</textarea>
|
|
|
|
</div>
|
|
<div class="tab-pane-inner" id="xlsx">
|
|
<fieldset>
|
|
<div class="pure-control-group">
|
|
{{ render_field(form.xlsx_file, class="processor") }}
|
|
</div>
|
|
<div class="pure-control-group">
|
|
{{ render_field(form.file_mapping, class="processor") }}
|
|
</div>
|
|
</fieldset>
|
|
<div class="pure-control-group">
|
|
<span class="pure-form-message-inline">
|
|
{{ _('Table of custom column and data types mapping for the') }} <strong>{{ _('Custom mapping') }}</strong> {{ _('File mapping type.') }}
|
|
</span>
|
|
<table style="border: 1px solid #aaa; padding: 0.5rem; border-radius: 4px;">
|
|
<tr>
|
|
<td><strong>{{ _('Column #') }}</strong></td>
|
|
{% for n in range(4) %}
|
|
<td><input type="number" name="custom_xlsx[col_{{n}}]" style="width: 4rem;" min="1"></td>
|
|
{% endfor %}
|
|
</tr>
|
|
<tr>
|
|
<td><strong>{{ _('Type') }}</strong></td>
|
|
{% for n in range(4) %}
|
|
<td><select name="custom_xlsx[col_type_{{n}}]">
|
|
<option value="" style="color: #aaa"> -- {{ _('none') }} --</option>
|
|
<option value="url">{{ _('URL') }}</option>
|
|
<option value="title">{{ _('Title') }}</option>
|
|
<option value="include_filters">{{ _('CSS/xPath filter') }}</option>
|
|
<option value="tag">{{ _('Group / Tag name(s)') }}</option>
|
|
<option value="interval_minutes">{{ _('Recheck time (minutes)') }}</option>
|
|
</select></td>
|
|
{% endfor %}
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
<button type="submit" class="pure-button pure-input-1-2 pure-button-primary">{{ _('Import') }}</button>
|
|
</form>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
{% endblock %} |