diff --git a/assets/controllers/update_confirm_controller.js b/assets/controllers/update_confirm_controller.js new file mode 100644 index 00000000..c30a433e --- /dev/null +++ b/assets/controllers/update_confirm_controller.js @@ -0,0 +1,81 @@ +/* + * This file is part of Part-DB (https://github.com/Part-DB/Part-DB-symfony). + * + * Copyright (C) 2019 - 2025 Jan Böhmer (https://github.com/jbtronics) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +import { Controller } from '@hotwired/stimulus'; + +/** + * Stimulus controller for update/downgrade confirmation dialogs. + * Intercepts form submission and shows a confirmation dialog before proceeding. + */ +export default class extends Controller { + static values = { + isDowngrade: { type: Boolean, default: false }, + targetVersion: { type: String, default: '' }, + confirmUpdate: { type: String, default: 'Are you sure you want to update Part-DB?' }, + confirmDowngrade: { type: String, default: 'Are you sure you want to downgrade Part-DB?' }, + downgradeWarning: { type: String, default: 'WARNING: This version does not include the Update Manager.' }, + minUpdateManagerVersion: { type: String, default: '2.6.0' }, + }; + + connect() { + this.element.addEventListener('submit', this.handleSubmit.bind(this)); + } + + handleSubmit(event) { + // Always prevent default first + event.preventDefault(); + + const targetClean = this.targetVersionValue.replace(/^v/, ''); + let message; + + if (this.isDowngradeValue) { + // Check if downgrading to a version without Update Manager + if (this.compareVersions(targetClean, this.minUpdateManagerVersionValue) < 0) { + message = this.confirmDowngradeValue + '\n\n⚠️ ' + this.downgradeWarningValue; + } else { + message = this.confirmDowngradeValue; + } + } else { + message = this.confirmUpdateValue; + } + + // Only submit if user confirms + if (confirm(message)) { + // Remove the event listener to prevent infinite loop, then submit + this.element.removeEventListener('submit', this.handleSubmit.bind(this)); + this.element.submit(); + } + } + + /** + * Compare two version strings (e.g., "2.5.0" vs "2.6.0") + * Returns -1 if v1 < v2, 0 if equal, 1 if v1 > v2 + */ + compareVersions(v1, v2) { + const parts1 = v1.split('.').map(Number); + const parts2 = v2.split('.').map(Number); + for (let i = 0; i < Math.max(parts1.length, parts2.length); i++) { + const p1 = parts1[i] || 0; + const p2 = parts2[i] || 0; + if (p1 < p2) return -1; + if (p1 > p2) return 1; + } + return 0; + } +} diff --git a/templates/admin/update_manager/index.html.twig b/templates/admin/update_manager/index.html.twig index d9dccbcf..1ab6c89e 100644 --- a/templates/admin/update_manager/index.html.twig +++ b/templates/admin/update_manager/index.html.twig @@ -133,7 +133,13 @@ {% if status.update_available and status.can_auto_update and validation.valid %} -
+ @@ -237,7 +243,12 @@ {% if release.version != status.current_version and status.can_auto_update and validation.valid %} + data-controller="update-confirm" + data-update-confirm-is-downgrade-value="{{ release.version < status.current_version ? 'true' : 'false' }}" + data-update-confirm-target-version-value="{{ release.tag }}" + data-update-confirm-confirm-update-value="{{ 'update_manager.confirm_update'|trans }}" + data-update-confirm-confirm-downgrade-value="{{ 'update_manager.confirm_downgrade'|trans }}" + data-update-confirm-downgrade-warning-value="{{ 'update_manager.downgrade_removes_update_manager'|trans }}"> @@ -371,37 +382,4 @@ {% endif %} - - {% endblock %}