diff options
Diffstat (limited to 'app/assets/javascripts/toggle_buttons.js')
-rw-r--r-- | app/assets/javascripts/toggle_buttons.js | 61 |
1 files changed, 61 insertions, 0 deletions
diff --git a/app/assets/javascripts/toggle_buttons.js b/app/assets/javascripts/toggle_buttons.js new file mode 100644 index 00000000000..974dc3ee052 --- /dev/null +++ b/app/assets/javascripts/toggle_buttons.js @@ -0,0 +1,61 @@ +import $ from 'jquery'; +import Flash from './flash'; +import { __ } from './locale'; +import { convertPermissionToBoolean } from './lib/utils/common_utils'; + +/* + example HAML: + ``` + %button.js-project-feature-toggle.project-feature-toggle{ type: "button", + class: "#{'is-checked' if enabled?}", + 'aria-label': _('Toggle Cluster') } + %input{ type: "hidden", class: 'js-project-feature-toggle-input', value: enabled? } + ``` +*/ + +function updatetoggle(toggle, isOn) { + toggle.classList.toggle('is-checked', isOn); +} + +function onToggleClicked(toggle, input, clickCallback) { + const previousIsOn = convertPermissionToBoolean(input.value); + + // Visually change the toggle and start loading + updatetoggle(toggle, !previousIsOn); + toggle.setAttribute('disabled', true); + toggle.classList.toggle('is-loading', true); + + Promise.resolve(clickCallback(!previousIsOn, toggle)) + .then(() => { + // Actually change the input value + input.setAttribute('value', !previousIsOn); + }) + .catch(() => { + // Revert the visuals if something goes wrong + updatetoggle(toggle, previousIsOn); + }) + .then(() => { + // Remove the loading indicator in any case + toggle.removeAttribute('disabled'); + toggle.classList.toggle('is-loading', false); + + $(input).trigger('trigger-change'); + }) + .catch(() => { + Flash(__('Something went wrong when toggling the button')); + }); +} + +export default function setupToggleButtons(container, clickCallback = () => {}) { + const toggles = container.querySelectorAll('.js-project-feature-toggle'); + + toggles.forEach((toggle) => { + const input = toggle.querySelector('.js-project-feature-toggle-input'); + const isOn = convertPermissionToBoolean(input.value); + + // Get the visible toggle in sync with the hidden input + updatetoggle(toggle, isOn); + + toggle.addEventListener('click', onToggleClicked.bind(null, toggle, input, clickCallback)); + }); +} |