mirror of
https://github.com/opf/openproject.git
synced 2026-06-14 03:30:14 +00:00
[#68734] Migrate webhooks form jQuery to Stimulus
Replaces jQuery-based enable/disable logic in the webhooks admin form with a new Stimulus controller `disable-when-value-selected`. This change was originally deferred from PR #20884 as it was planned to be addressed in Work Package #69436 / PR #21227. Since that work has been put on hold and jQuery removal is progressing, this commit completes the migration now. Changes: - Add DisableWhenValueSelectedController for declarative form toggling - Add toggleEnabled/enableElement/disableElement helpers to dom-helpers - Remove jQuery code from webhooks admin form - Apply Stimulus controller to project selection fieldset Related to opf/openproject#20884 https://community.openproject.org/wp/68734
This commit is contained in:
@@ -243,3 +243,35 @@ export function attributeTokenList(element:HTMLElement, attribute:string):DOMTok
|
||||
return list as DOMTokenList;
|
||||
}
|
||||
/* eslint-enable */
|
||||
|
||||
/**
|
||||
* Toggles the enabled/disabled state of form elements.
|
||||
* For fieldsets, recursively applies to all child elements.
|
||||
*
|
||||
* @param element the element to toggle
|
||||
* @param value force state (optional): `true` to enable/`false` to disable
|
||||
*/
|
||||
export function toggleEnabled(element:HTMLElement, value?:boolean) {
|
||||
if (
|
||||
element instanceof HTMLInputElement ||
|
||||
element instanceof HTMLSelectElement ||
|
||||
element instanceof HTMLTextAreaElement ||
|
||||
element instanceof HTMLButtonElement ||
|
||||
element instanceof HTMLFieldSetElement
|
||||
) {
|
||||
if (typeof value === 'undefined') {
|
||||
element.disabled = !element.disabled;
|
||||
} else {
|
||||
element.disabled = !value;
|
||||
}
|
||||
}
|
||||
|
||||
if (element instanceof HTMLFieldSetElement) {
|
||||
Array.from(element.elements).forEach((child) => {
|
||||
toggleEnabled(child as HTMLElement, !element.disabled);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export const enableElement = (element:HTMLElement) => toggleEnabled(element, true);
|
||||
export const disableElement = (element:HTMLElement) => toggleEnabled(element, false);
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* -- copyright
|
||||
* OpenProject is an open source project management software.
|
||||
* Copyright (C) the OpenProject GmbH
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 3.
|
||||
*
|
||||
* OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
|
||||
* Copyright (C) 2006-2013 Jean-Philippe Lang
|
||||
* Copyright (C) 2010-2013 the ChiliProject Team
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* See COPYRIGHT and LICENSE files for more details.
|
||||
* ++
|
||||
*/
|
||||
|
||||
import { toggleEnabled } from 'core-app/shared/helpers/dom-helpers';
|
||||
import { ApplicationController } from 'stimulus-use';
|
||||
|
||||
export default class OpDisableWhenValueSelectedController extends ApplicationController {
|
||||
static targets = ['cause', 'effect'];
|
||||
|
||||
declare readonly effectTargets:(HTMLInputElement|HTMLFieldSetElement)[];
|
||||
|
||||
private boundListener = this.toggleDisabled.bind(this);
|
||||
|
||||
causeTargetConnected(target:HTMLElement) {
|
||||
target.addEventListener('change', this.boundListener);
|
||||
}
|
||||
|
||||
causeTargetDisconnected(target:HTMLElement) {
|
||||
target.removeEventListener('change', this.boundListener);
|
||||
}
|
||||
|
||||
private toggleDisabled(evt:Event):void {
|
||||
const input = evt.target as HTMLInputElement;
|
||||
const targetName = input.dataset.targetName;
|
||||
|
||||
this
|
||||
.effectTargets
|
||||
.filter((el) => targetName === el.dataset.targetName)
|
||||
.forEach((el) => {
|
||||
const disabled = this.willDisable(el, input.value);
|
||||
toggleEnabled(el, !disabled);
|
||||
});
|
||||
}
|
||||
|
||||
private willDisable(el:HTMLElement, value:string):boolean {
|
||||
if (el.dataset.notValue) {
|
||||
return el.dataset.notValue === value;
|
||||
}
|
||||
|
||||
return !(el.dataset.value === value);
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ import { environment } from '../environments/environment';
|
||||
import { OpApplicationController } from './controllers/op-application.controller';
|
||||
import MainMenuController from './controllers/dynamic/menus/main.controller';
|
||||
import OpDisableWhenCheckedController from './controllers/disable-when-checked.controller';
|
||||
import OpDisableWhenValueSelectedController from './controllers/disable-when-value-selected.controller';
|
||||
import PrintController from './controllers/print.controller';
|
||||
import RefreshOnFormChangesController from './controllers/refresh-on-form-changes.controller';
|
||||
import FormPreviewController from './controllers/form-preview.controller';
|
||||
@@ -57,6 +58,7 @@ OpenProjectStimulusApplication.preregister('application', OpApplicationControlle
|
||||
OpenProjectStimulusApplication.preregister('async-dialog', AsyncDialogController);
|
||||
OpenProjectStimulusApplication.preregister('disable-when-checked', OpDisableWhenCheckedController);
|
||||
OpenProjectStimulusApplication.preregister('disable-when-clicked', DisableWhenClickedController);
|
||||
OpenProjectStimulusApplication.preregister('disable-when-value-selected', OpDisableWhenValueSelectedController);
|
||||
OpenProjectStimulusApplication.preregister('flash', FlashController);
|
||||
OpenProjectStimulusApplication.preregister('menus--main', MainMenuController);
|
||||
OpenProjectStimulusApplication.preregister('require-password-confirmation', RequirePasswordConfirmationController);
|
||||
|
||||
@@ -70,7 +70,7 @@
|
||||
<% end %>
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="form--fieldset">
|
||||
<fieldset class="form--fieldset" data-controller="disable-when-value-selected">
|
||||
<legend class="form--fieldset-legend">
|
||||
<%= t "webhooks.outgoing.form.project_ids.title" %>
|
||||
</legend>
|
||||
@@ -80,14 +80,22 @@
|
||||
"all",
|
||||
checked: @webhook.all_projects?,
|
||||
label: t("webhooks.outgoing.form.project_ids.all"),
|
||||
container_class: "-wide" %>
|
||||
container_class: "-wide",
|
||||
data: {
|
||||
disable_when_value_selected_target: "cause",
|
||||
target_name: "webhook_project_ids"
|
||||
} %>
|
||||
</div>
|
||||
<div class="form--field">
|
||||
<%= f.radio_button :project_ids,
|
||||
"selection",
|
||||
checked: !@webhook.all_projects?,
|
||||
label: t("webhooks.outgoing.form.project_ids.selected"),
|
||||
container_class: "-wide" %>
|
||||
container_class: "-wide",
|
||||
data: {
|
||||
disable_when_value_selected_target: "cause",
|
||||
target_name: "webhook_project_ids"
|
||||
} %>
|
||||
</div>
|
||||
|
||||
<div class="form--field">
|
||||
@@ -99,23 +107,15 @@
|
||||
id,
|
||||
!@webhook.all_projects? && @webhook.project_ids.include?(id),
|
||||
disabled: @webhook.all_projects?,
|
||||
class: "webhooks--selected-project-ids" -%>
|
||||
class: "webhooks--selected-project-ids",
|
||||
data: {
|
||||
disable_when_value_selected_target: "effect",
|
||||
target_name: "webhook_project_ids",
|
||||
value: "selection"
|
||||
} -%>
|
||||
<%= name %>
|
||||
</label>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<%= nonced_javascript_tag do %>
|
||||
(function($) {
|
||||
// Toggle selector for new/edit webhooks projects
|
||||
$('input[name="webhook[project_ids]"]').change(function(){
|
||||
$('.webhooks--selected-project-ids').prop('disabled', $(this).val() === 'all');
|
||||
});
|
||||
|
||||
$('input[name="webhook[type_ids]"]').change(function(){
|
||||
$('.webhooks--selected-type-ids').prop('disabled', $(this).val() === 'all');
|
||||
});
|
||||
}(jQuery));
|
||||
<% end %>
|
||||
|
||||
Reference in New Issue
Block a user