summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/toggle_buttons.js
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets/javascripts/toggle_buttons.js')
-rw-r--r--app/assets/javascripts/toggle_buttons.js61
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));
+ });
+}