Skip to content

Commit da6ac46

Browse files
committed
Merge branch 'master' into dev
2 parents a7add8b + 0dbfb02 commit da6ac46

File tree

35 files changed

+8071
-163
lines changed

35 files changed

+8071
-163
lines changed

changedetectionio/blueprint/backups/templates/backup_restore.html

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,7 @@
2020
<p>{{ _('Restore a backup. Must be a .zip backup file created on/after v0.53.1 (new database layout).') }}</p>
2121
<p>{{ _('Note: This does not override the main application settings, only watches and groups.') }}</p>
2222
<p class="pure-form-message">
23-
{{ _('Max upload size: %(upload)s MB &nbsp;·&nbsp; Max decompressed size: %(decomp)s MB',
24-
upload=max_upload_mb, decomp=max_decompressed_mb) }}
23+
{{ _('Max upload size: %(upload)s MB, Max decompressed size: %(decomp)s MB', upload=max_upload_mb, decomp=max_decompressed_mb) }}
2524
</p>
2625

2726
<form class="pure-form pure-form-stacked settings"

changedetectionio/blueprint/imports/importer.py

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -160,8 +160,7 @@ def run(self,
160160
flash(gettext("Unable to read export XLSX file, something wrong with the file?"), 'error')
161161
return
162162

163-
row_id = 2
164-
for row in wb.active.iter_rows(min_row=row_id):
163+
for row_id, row in enumerate(wb.active.iter_rows(min_row=2), start=2):
165164
try:
166165
extras = {}
167166
data = {}
@@ -212,8 +211,6 @@ def run(self,
212211
except Exception as e:
213212
logger.error(e)
214213
flash(gettext("Error processing row number {}, check all cell data types are correct, row was skipped.").format(row_id), 'error')
215-
else:
216-
row_id += 1
217214

218215
flash(gettext("{} imported from Wachete .xlsx in {:.2f}s").format(len(self.new_uuids), time.time() - now))
219216

@@ -241,10 +238,10 @@ def run(self,
241238

242239
# @todo cehck atleast 2 rows, same in other method
243240
from changedetectionio.forms import validate_url
244-
row_i = 1
241+
row_i = 0
245242

246243
try:
247-
for row in wb.active.iter_rows():
244+
for row_i, row in enumerate(wb.active.iter_rows(), start=1):
248245
url = None
249246
tags = None
250247
extras = {}
@@ -295,7 +292,5 @@ def run(self,
295292
except Exception as e:
296293
logger.error(e)
297294
flash(gettext("Error processing row number {}, check all cell data types are correct, row was skipped.").format(row_i), 'error')
298-
else:
299-
row_i += 1
300295

301296
flash(gettext("{} imported from custom .xlsx in {:.2f}s").format(len(self.new_uuids), time.time() - now))

changedetectionio/blueprint/imports/templates/import.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
<li class="tab" id=""><a href="#url-list">{{ _('URL List') }}</a></li>
1010
<li class="tab"><a href="#distill-io">{{ _('Distill.io') }}</a></li>
1111
<li class="tab"><a href="#xlsx">{{ _('.XLSX & Wachete') }}</a></li>
12+
<li class="tab"><a href="{{url_for('backups.restore.restore')}}">{{ _('Backup Restore') }}</a></li>
1213
</ul>
1314
</div>
1415

changedetectionio/blueprint/tags/__init__.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,14 @@ def tags_overview_page():
2222

2323
tag_count = Counter(tag for watch in datastore.data['watching'].values() if watch.get('tags') for tag in watch['tags'])
2424

25+
from changedetectionio import processors
2526
output = render_template("groups-overview.html",
2627
app_rss_token=datastore.data['settings']['application'].get('rss_access_token'),
2728
available_tags=sorted_tags,
2829
form=add_form,
30+
generate_tag_colors=processors.generate_processor_badge_colors,
2931
tag_count=tag_count,
32+
wcag_text_color=processors.wcag_text_color,
3033
)
3134

3235
return output
@@ -208,9 +211,17 @@ def form_tag_edit(uuid):
208211
template = env.from_string(template_str)
209212
included_content = template.render(**template_args)
210213

214+
# Watches whose URL currently matches this tag's pattern
215+
matching_watches = {
216+
w_uuid: watch
217+
for w_uuid, watch in datastore.data['watching'].items()
218+
if default.matches_url(watch.get('url', ''))
219+
}
220+
211221
output = render_template("edit-tag.html",
212222
extra_form_content=included_content,
213223
extra_tab_content=form.extra_tab_content() if form.extra_tab_content() else None,
224+
matching_watches=matching_watches,
214225
settings_application=datastore.data['settings']['application'],
215226
**template_args
216227
)

changedetectionio/blueprint/tags/form.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,11 @@
1010

1111
class group_restock_settings_form(restock_settings_form):
1212
overrides_watch = BooleanField('Activate for individual watches in this tag/group?', default=False)
13+
url_match_pattern = StringField('Auto-apply to watches with URLs matching',
14+
render_kw={"placeholder": "e.g. *://example.com/* or github.com/myorg"})
15+
tag_colour = StringField('Tag colour', default='')
1316

1417
class SingleTag(Form):
1518

1619
name = StringField('Tag name', [validators.InputRequired()], render_kw={"placeholder": "Name"})
1720
save_button = SubmitField('Save', render_kw={"class": "pure-button pure-button-primary"})
18-
19-
20-
21-

changedetectionio/blueprint/tags/templates/edit-tag.html

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,46 @@
4343
<div class="pure-control-group">
4444
{{ render_field(form.title, placeholder="https://...", required=true, class="m-d") }}
4545
</div>
46+
<div class="pure-control-group">
47+
{{ render_field(form.url_match_pattern, class="m-d") }}
48+
<span class="pure-form-message-inline">{{ _('Automatically applies this tag to any watch whose URL matches. Supports wildcards: <code>*example.com*</code> or plain substring: <code>github.com/myorg</code>')|safe }}</span>
49+
</div>
50+
{% if matching_watches %}
51+
<div class="pure-control-group">
52+
<label>{{ _('Currently matching watches') }} ({{ matching_watches|length }})</label>
53+
<ul class="tag-url-match-list">
54+
{% for w_uuid, w in matching_watches.items() %}
55+
<li><a href="{{ url_for('ui.ui_edit.edit_page', uuid=w_uuid) }}">{{ w.label }}</a></li>
56+
{% endfor %}
57+
</ul>
58+
</div>
59+
{% endif %}
60+
<div class="pure-control-group">
61+
<label>{{ _('Tag colour') }}</label>
62+
<div style="display:flex; align-items:center; gap:0.75em;">
63+
<input type="checkbox" id="use_custom_colour"
64+
{% if data.get('tag_colour') %}checked{% endif %}>
65+
<label for="use_custom_colour" style="margin:0">{{ _('Custom colour') }}</label>
66+
<input type="color" id="tag_colour_picker"
67+
value="{{ data.get('tag_colour') or '#4f8ef7' }}"
68+
{% if not data.get('tag_colour') %}disabled{% endif %}>
69+
<input type="hidden" name="tag_colour" id="tag_colour_hidden"
70+
value="{{ data.get('tag_colour', '') }}">
71+
</div>
72+
<span class="pure-form-message-inline">{{ _('Leave unchecked to use the auto-generated colour based on the tag name.') }}</span>
73+
</div>
74+
<script>
75+
(function () {
76+
var cb = document.getElementById('use_custom_colour');
77+
var picker = document.getElementById('tag_colour_picker');
78+
var hidden = document.getElementById('tag_colour_hidden');
79+
picker.addEventListener('input', function () { hidden.value = this.value; });
80+
cb.addEventListener('change', function () {
81+
picker.disabled = !this.checked;
82+
hidden.value = this.checked ? picker.value : '';
83+
});
84+
})();
85+
</script>
4686
</fieldset>
4787
</div>
4888

changedetectionio/blueprint/tags/templates/groups-overview.html

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,26 @@
33
{% from '_helpers.html' import render_simple_field, render_field %}
44
<script src="{{url_for('static_content', group='js', filename='jquery-3.6.0.min.js')}}"></script>
55
<script src="{{url_for('static_content', group='js', filename='modal.js')}}"></script>
6+
<style>
7+
{%- for uuid, tag in available_tags -%}
8+
{%- if tag and tag.title -%}
9+
{%- set class_name = tag.title|sanitize_tag_class -%}
10+
{%- if tag.get('tag_colour') -%}
11+
.watch-tag-list.tag-{{ class_name }} { background-color: {{ tag.tag_colour }}; color: {{ wcag_text_color(tag.tag_colour) }}; }
12+
{%- else -%}
13+
{%- set colors = generate_tag_colors(tag.title) -%}
14+
.watch-tag-list.tag-{{ class_name }} {
15+
background-color: {{ colors['light']['bg'] }};
16+
color: {{ colors['light']['color'] }};
17+
}
18+
html[data-darkmode="true"] .watch-tag-list.tag-{{ class_name }} {
19+
background-color: {{ colors['dark']['bg'] }};
20+
color: {{ colors['dark']['color'] }};
21+
}
22+
{%- endif -%}
23+
{%- endif -%}
24+
{%- endfor -%}
25+
</style>
626

727
<div class="box">
828
<form class="pure-form" action="{{ url_for('tags.form_tag_add') }}" method="POST" id="new-watch-form">
@@ -48,7 +68,7 @@
4868
<a class="link-mute state-{{'on' if tag.notification_muted else 'off'}}" href="{{url_for('tags.mute', uuid=tag.uuid)}}"><img src="{{url_for('static_content', group='images', filename='bell-off.svg')}}" alt="Mute notifications" title="Mute notifications" class="icon icon-mute" ></a>
4969
</td>
5070
<td>{{ "{:,}".format(tag_count[uuid]) if uuid in tag_count else 0 }}</td>
51-
<td class="title-col inline"> <a href="{{url_for('watchlist.index', tag=uuid) }}">{{ tag.title }}</a></td>
71+
<td class="title-col inline"> <a href="{{url_for('watchlist.index', tag=uuid) }}" class="watch-tag-list tag-{{ tag.title|sanitize_tag_class }}">{{ tag.title }}</a></td>
5272
<td>
5373
<a class="pure-button pure-button-primary" href="{{ url_for('tags.form_tag_edit', uuid=uuid) }}">{{ _('Edit') }}</a>
5474
<a href="{{ url_for('ui.form_watch_checknow', tag=uuid) }}" class="pure-button pure-button-primary" >{{ _('Recheck') }}</a>

changedetectionio/blueprint/ui/edit.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -352,7 +352,12 @@ def edit_page(uuid):
352352
'using_global_webdriver_wait': not default['webdriver_delay'],
353353
'uuid': uuid,
354354
'watch': watch,
355-
'capabilities': capabilities
355+
'capabilities': capabilities,
356+
'auto_applied_tags': {
357+
tag_uuid: tag
358+
for tag_uuid, tag in datastore.data['settings']['application']['tags'].items()
359+
if tag_uuid not in watch.get('tags', []) and tag.matches_url(watch.get('url', ''))
360+
},
356361
}
357362

358363
included_content = None

changedetectionio/blueprint/ui/templates/edit.html

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,14 @@
8282
<div class="pure-control-group">
8383
{{ render_field(form.tags) }}
8484
<span class="pure-form-message-inline">{{ _('Organisational tag/group name used in the main listing page') }}</span>
85+
{% if auto_applied_tags %}
86+
<span class="pure-form-message-inline">
87+
{{ _('Also automatically applied by URL pattern:') }}
88+
{% for tag_uuid, tag in auto_applied_tags.items() %}
89+
<a href="{{ url_for('tags.form_tag_edit', uuid=tag_uuid) }}" class="watch-tag-list tag-{{ tag.title|sanitize_tag_class }}">{{ tag.title }}</a>
90+
{% endfor %}
91+
</span>
92+
{% endif %}
8593
</div>
8694
<div class="pure-control-group inline-radio">
8795
{{ render_field(form.processor) }}

changedetectionio/blueprint/watchlist/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ def index():
9292
extra_classes='has-queue' if not update_q.empty() else '',
9393
form=form,
9494
generate_tag_colors=processors.generate_processor_badge_colors,
95+
wcag_text_color=processors.wcag_text_color,
9596
guid=datastore.data['app_guid'],
9697
has_proxies=proxy_list,
9798
hosted_sticky=os.getenv("SALTED_PASS", False) == False,

0 commit comments

Comments
 (0)