form edit tweaks

This commit is contained in:
dgtlmoon
2026-03-24 14:56:48 +01:00
parent e8c8be94e6
commit 64aa0917bf
3 changed files with 51 additions and 40 deletions
@@ -13,9 +13,7 @@ def construct_blueprint(datastore: ChangeDetectionStore):
template_folder="templates"
)
@settings_browser_profile_blueprint.route("", methods=['GET'])
@login_optionally_required
def index():
def _render_index(browser_profile_form=None, editing_machine_name=None):
from changedetectionio import forms
from changedetectionio import content_fetchers as cf
from changedetectionio.model.browser_profile import (
@@ -23,10 +21,10 @@ def construct_blueprint(datastore: ChangeDetectionStore):
)
fetcher_choices = [(name[len('html_'):], desc) for name, desc in cf.available_fetchers()]
browser_profile_form = forms.BrowserProfileForm()
if browser_profile_form is None:
browser_profile_form = forms.BrowserProfileForm()
browser_profile_form.fetch_backend.choices = fetcher_choices
# Map clean fetcher name → supports_screenshots so the template can hide viewport options
fetcher_supports_screenshots = {}
for name, _desc in cf.available_fetchers():
clean_name = name[len('html_'):]
@@ -51,8 +49,34 @@ def construct_blueprint(datastore: ChangeDetectionStore):
fetcher_choices=fetcher_choices,
fetcher_supports_screenshots=fetcher_supports_screenshots,
current_default_profile=current_default,
editing_machine_name=editing_machine_name,
)
@settings_browser_profile_blueprint.route("", methods=['GET'])
@login_optionally_required
def index():
return _render_index()
@settings_browser_profile_blueprint.route("/<string:machine_name>/edit", methods=['GET'])
@login_optionally_required
def edit(machine_name):
from changedetectionio import forms
from changedetectionio.model.browser_profile import get_builtin_profiles, BrowserProfile, RESERVED_MACHINE_NAMES
if machine_name in RESERVED_MACHINE_NAMES:
flash(gettext("Built-in browser profiles cannot be edited."), 'error')
return redirect(url_for('settings_browsers.index'))
store_profiles = datastore.data['settings']['application'].get('browser_profiles', {})
raw = store_profiles.get(machine_name)
if raw is None:
flash(gettext("Browser profile not found."), 'error')
return redirect(url_for('settings_browsers.index'))
profile = BrowserProfile(**raw) if isinstance(raw, dict) else raw
form = forms.BrowserProfileForm(data=profile.model_dump())
return _render_index(browser_profile_form=form, editing_machine_name=machine_name)
@settings_browser_profile_blueprint.route("/save", methods=['POST'])
@login_optionally_required
def save():
@@ -49,8 +49,8 @@
</td>
<td style="white-space:nowrap;">
{% if not profile.is_builtin %}
<button type="button" class="pure-button button-small"
onclick="browserProfileEdit({{ profile.model_dump()|tojson }}, {{ machine_name|tojson }})">{{ _('Edit') }}</button>
<a href="{{ url_for('settings_browsers.edit', machine_name=machine_name) }}"
class="pure-button button-small">{{ _('Edit') }}</a>
<a href="{{ url_for('settings_browsers.delete', machine_name=machine_name) }}"
class="pure-button button-small button-error"
onclick="return confirm('{{ _('Delete this browser profile?') }}')">{{ _('Delete') }}</a>
@@ -63,13 +63,13 @@
</tbody>
</table>
<h3 id="profile-form-heading">{{ _('Add new browser profile') }}</h3>
<h3 id="profile-form-heading">{{ _('Edit browser profile') if editing_machine_name else _('Add new browser profile') }}</h3>
<form class="pure-form pure-form-stacked"
id="browser-profile-form"
action="{{ url_for('settings_browsers.save') }}"
method="POST">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
<input type="hidden" name="original_machine_name" id="original_machine_name" value="">
<input type="hidden" name="original_machine_name" id="original_machine_name" value="{{ editing_machine_name or '' }}">
<fieldset>
<div class="pure-control-group">
{{ render_field(browser_profile_form.name) }}
@@ -107,8 +107,9 @@
</div>
<div class="pure-control-group">
<button type="submit" class="pure-button pure-button-primary" id="profile-submit-btn">{{ _('Save profile') }}</button>
<button type="button" class="pure-button button-cancel" id="profile-cancel-btn" style="display:none;"
onclick="cancelEdit()">{{ _('Cancel') }}</button>
{% if editing_machine_name %}
<a href="{{ url_for('settings_browsers.index') }}" class="pure-button button-cancel">{{ _('Cancel') }}</a>
{% endif %}
<a href="{{ url_for('settings.settings_page') }}" class="pure-button button-cancel">{{ _('Back to Settings') }}</a>
</div>
</fieldset>
@@ -140,33 +141,10 @@ document.addEventListener('DOMContentLoaded', function() {
}
});
function browserProfileEdit(profile, machineName) {
document.getElementById('profile-form-heading').textContent = {{ _('Edit browser profile')|tojson }};
document.getElementById('original_machine_name').value = machineName;
const form = document.getElementById('browser-profile-form');
form.querySelector('[name="name"]').value = profile.name || '';
form.querySelector('[name="fetch_backend"]').value = profile.fetch_backend || '';
form.querySelector('[name="browser_connection_url"]').value = profile.browser_connection_url || '';
form.querySelector('[name="viewport_width"]').value = profile.viewport_width || 1280;
form.querySelector('[name="viewport_height"]').value = profile.viewport_height || 1000;
form.querySelector('[name="block_images"]').checked = !!profile.block_images;
form.querySelector('[name="block_fonts"]').checked = !!profile.block_fonts;
form.querySelector('[name="ignore_https_errors"]').checked = !!profile.ignore_https_errors;
form.querySelector('[name="user_agent"]').value = profile.user_agent || '';
form.querySelector('[name="locale"]').value = profile.locale || '';
updateBrowserFieldVisibility();
document.getElementById('profile-cancel-btn').style.display = '';
form.scrollIntoView({behavior: 'smooth'});
}
function cancelEdit() {
document.getElementById('profile-form-heading').textContent = {{ _('Add new browser profile')|tojson }};
document.getElementById('original_machine_name').value = '';
document.getElementById('browser-profile-form').reset();
updateBrowserFieldVisibility();
document.getElementById('profile-cancel-btn').style.display = 'none';
}
{% if editing_machine_name %}
document.addEventListener('DOMContentLoaded', function() {
document.getElementById('browser-profile-form').scrollIntoView({behavior: 'smooth'});
});
{% endif %}
</script>
{% endblock %}
@@ -132,7 +132,16 @@
{% if capabilities.supports_request_type %}
<div class="tab-pane-inner" id="request">
<div class="pure-control-group inline-radio">
{{ render_field(form.browser_profile, class="fetch-backend") }}
<div><label for="browser_profile">{{ form.browser_profile.label.text }}</label></div>
<div><ul class="fetch-backend" id="browser_profile">
{%- for subfield in form.browser_profile %}
<li>
{{ subfield() }}
{{ browser_profile_fetchers.get(subfield.data, '')|fetcher_status_icons }}
<label for="{{ subfield.id }}">{{ subfield.label.text }}</label>
</li>
{%- endfor %}
</ul></div>
<span class="pure-form-message-inline">
<p>{{ _('Choose how this watch fetches its target URL. \'System settings default\' inherits the global setting.') }}</p>
<p>{{ _('Manage browser profiles in') }} <a href="{{ url_for('settings_browsers.index') }}">{{ _('Settings → Browsers') }}</a>.</p>