Commit 67149ad1 authored by Mark Florian's avatar Mark Florian

Merge branch 'switch-to-rails-ujs' into 'master'

Switch to rails-ujs

Closes #219253

See merge request gitlab-org/gitlab!27394
parents 6ae80d0e c13d9c11
import './polyfills'; import './polyfills';
import './jquery';
import './bootstrap'; import './bootstrap';
import './vue'; import './vue';
import '../lib/utils/axios_utils'; import '../lib/utils/axios_utils';
......
import 'jquery';
// common jQuery plugins
import 'jquery-ujs';
import $ from 'jquery'; import $ from 'jquery';
import { Rails } from '~/lib/utils/rails_ujs';
import { rstrip } from './lib/utils/common_utils'; import { rstrip } from './lib/utils/common_utils';
function openConfirmDangerModal($form, $modal, text) { function openConfirmDangerModal($form, $modal, text) {
...@@ -21,9 +22,16 @@ function openConfirmDangerModal($form, $modal, text) { ...@@ -21,9 +22,16 @@ function openConfirmDangerModal($form, $modal, text) {
$submit.disable(); $submit.disable();
} }
}); });
$('.js-confirm-danger-submit', $modal) $('.js-confirm-danger-submit', $modal)
.off('click') .off('click')
.on('click', () => $form.submit()); .on('click', () => {
if ($form.data('remote')) {
Rails.fire($form[0], 'submit');
} else {
$form.submit();
}
});
} }
function getModal($btn) { function getModal($btn) {
......
import $ from 'jquery';
/* /*
This module provides easy access to the CSRF token and caches This module provides easy access to the CSRF token and caches
it for re-use. It also exposes some values commonly used in relation it for re-use. It also exposes some values commonly used in relation
...@@ -20,7 +18,6 @@ If you need to compose a headers object, use the spread operator: ...@@ -20,7 +18,6 @@ If you need to compose a headers object, use the spread operator:
see also http://guides.rubyonrails.org/security.html#cross-site-request-forgery-csrf see also http://guides.rubyonrails.org/security.html#cross-site-request-forgery-csrf
and https://github.com/rails/jquery-rails/blob/v4.3.1/vendor/assets/javascripts/jquery_ujs.js#L59-L62 and https://github.com/rails/jquery-rails/blob/v4.3.1/vendor/assets/javascripts/jquery_ujs.js#L59-L62
*/ */
const csrf = { const csrf = {
init() { init() {
const tokenEl = document.querySelector('meta[name=csrf-token]'); const tokenEl = document.querySelector('meta[name=csrf-token]');
...@@ -52,9 +49,4 @@ const csrf = { ...@@ -52,9 +49,4 @@ const csrf = {
csrf.init(); csrf.init();
// use our cached token for any $.rails-generated AJAX requests
if ($.rails) {
$.rails.csrfToken = () => csrf.token;
}
export default csrf; export default csrf;
import Rails from '@rails/ujs';
export const initRails = () => {
// eslint-disable-next-line no-underscore-dangle
if (!window._rails_loaded) {
Rails.start();
// Count XHR requests for tests. See spec/support/helpers/wait_for_requests.rb
window.pendingRailsUJSRequests = 0;
document.body.addEventListener('ajax:complete', () => {
window.pendingRailsUJSRequests -= 1;
});
document.body.addEventListener('ajax:beforeSend', () => {
window.pendingRailsUJSRequests += 1;
});
}
};
export { Rails };
...@@ -11,6 +11,7 @@ import './behaviors'; ...@@ -11,6 +11,7 @@ import './behaviors';
// lib/utils // lib/utils
import applyGitLabUIConfig from '@gitlab/ui/dist/config'; import applyGitLabUIConfig from '@gitlab/ui/dist/config';
import { GlBreakpointInstance as bp } from '@gitlab/ui/dist/utils'; import { GlBreakpointInstance as bp } from '@gitlab/ui/dist/utils';
import { initRails } from '~/lib/utils/rails_ujs';
import { import {
handleLocationHash, handleLocationHash,
addSelectOnFocusBehaviour, addSelectOnFocusBehaviour,
...@@ -169,6 +170,8 @@ function deferredInitialisation() { ...@@ -169,6 +170,8 @@ function deferredInitialisation() {
// Adding a helper class to activate animations only after all is rendered // Adding a helper class to activate animations only after all is rendered
setTimeout(() => $body.addClass('page-initialised'), 1000); setTimeout(() => $body.addClass('page-initialised'), 1000);
initRails();
} }
document.addEventListener('DOMContentLoaded', () => { document.addEventListener('DOMContentLoaded', () => {
......
import $ from 'jquery'; import $ from 'jquery';
import { Rails } from '~/lib/utils/rails_ujs';
import { disableButtonIfEmptyField } from '~/lib/utils/common_utils'; import { disableButtonIfEmptyField } from '~/lib/utils/common_utils';
import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown'; import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
...@@ -54,8 +55,9 @@ export default class Members { ...@@ -54,8 +55,9 @@ export default class Members {
formSubmit(e, $el = null) { formSubmit(e, $el = null) {
const $this = e ? $(e.currentTarget) : $el; const $this = e ? $(e.currentTarget) : $el;
const { $toggle, $dateInput } = this.getMemberListItems($this); const { $toggle, $dateInput } = this.getMemberListItems($this);
const formEl = $this.closest('form').get(0);
$this.closest('form').trigger('submit.rails'); Rails.fire(formEl, 'submit');
$toggle.disable(); $toggle.disable();
$dateInput.disable(); $dateInput.disable();
......
import { initRails } from '~/lib/utils/rails_ujs';
import { deprecatedCreateFlash as Flash } from '~/flash'; import { deprecatedCreateFlash as Flash } from '~/flash';
import { __, sprintf } from '~/locale'; import { __, sprintf } from '~/locale';
import { getParameterByName } from '~/lib/utils/common_utils'; import { getParameterByName } from '~/lib/utils/common_utils';
...@@ -11,6 +12,8 @@ export default function leaveByUrl(namespaceType) { ...@@ -11,6 +12,8 @@ export default function leaveByUrl(namespaceType) {
const param = getParameterByName(PARAMETER_NAME); const param = getParameterByName(PARAMETER_NAME);
if (!param) return; if (!param) return;
initRails();
const leaveLink = document.querySelector(LEAVE_LINK_SELECTOR); const leaveLink = document.querySelector(LEAVE_LINK_SELECTOR);
if (leaveLink) { if (leaveLink) {
leaveLink.click(); leaveLink.click();
......
import $ from 'jquery'; import $ from 'jquery';
import { Rails } from '~/lib/utils/rails_ujs';
import { deprecatedCreateFlash as Flash } from './flash'; import { deprecatedCreateFlash as Flash } from './flash';
import { __ } from '~/locale'; import { __ } from '~/locale';
...@@ -21,10 +22,12 @@ export default function notificationsDropdown() { ...@@ -21,10 +22,12 @@ export default function notificationsDropdown() {
form.find('.js-notifications-icon').toggleClass('hidden'); form.find('.js-notifications-icon').toggleClass('hidden');
} }
form.find('#notification_setting_level').val(notificationLevel); form.find('#notification_setting_level').val(notificationLevel);
form.submit(); Rails.fire(form[0], 'submit');
}); });
$(document).on('ajax:success', '.notification-form', (e, data) => { $(document).on('ajax:success', '.notification-form', e => {
const data = e.detail[0];
if (data.saved) { if (data.saved) {
$(e.currentTarget) $(e.currentTarget)
.closest('.js-notification-dropdown') .closest('.js-notification-dropdown')
......
...@@ -26,11 +26,14 @@ export default { ...@@ -26,11 +26,14 @@ export default {
methods: { methods: {
listenForQuickActions() { listenForQuickActions() {
$(document).on('ajax:success', '.gfm-form', this.quickActionListened); $(document).on('ajax:success', '.gfm-form', this.quickActionListened);
eventHub.$on('timeTrackingUpdated', data => { eventHub.$on('timeTrackingUpdated', data => {
this.quickActionListened(null, data); this.quickActionListened({ detail: [data] });
}); });
}, },
quickActionListened(e, data) { quickActionListened(e) {
const data = e.detail[0];
const subscribedCommands = ['spend_time', 'time_estimate']; const subscribedCommands = ['spend_time', 'time_estimate'];
let changedCommands; let changedCommands;
if (data !== undefined) { if (data !== undefined) {
......
...@@ -9,20 +9,14 @@ module QA ...@@ -9,20 +9,14 @@ module QA
def wait_for_requests(skip_finished_loading_check: false) def wait_for_requests(skip_finished_loading_check: false)
Waiter.wait_until(log: false) do Waiter.wait_until(log: false) do
finished_all_ajax_requests? && finished_all_axios_requests? && (!skip_finished_loading_check ? finished_loading?(wait: 1) : true) finished_all_ajax_requests? && (!skip_finished_loading_check ? finished_loading?(wait: 1) : true)
end end
rescue Repeater::WaitExceededError rescue Repeater::WaitExceededError
raise $!, 'Page did not fully load. This could be due to an unending async request or loading icon.' raise $!, 'Page did not fully load. This could be due to an unending async request or loading icon.'
end end
def finished_all_axios_requests?
Capybara.page.evaluate_script('window.pendingRequests || 0').zero? # rubocop:disable Style/NumericPredicate
end
def finished_all_ajax_requests? def finished_all_ajax_requests?
return true if Capybara.page.evaluate_script('typeof jQuery === "undefined"') Capybara.page.evaluate_script('window.pendingRequests || window.pendingRailsUJSRequests || 0').zero? # rubocop:disable Style/NumericPredicate
Capybara.page.evaluate_script('jQuery.active').zero? # rubocop:disable Style/NumericPredicate
end end
def finished_loading?(wait: DEFAULT_MAX_WAIT_TIME) def finished_loading?(wait: DEFAULT_MAX_WAIT_TIME)
......
...@@ -3,7 +3,6 @@ ...@@ -3,7 +3,6 @@
describe QA::Support::WaitForRequests do describe QA::Support::WaitForRequests do
describe '.wait_for_requests' do describe '.wait_for_requests' do
before do before do
allow(subject).to receive(:finished_all_axios_requests?).and_return(true)
allow(subject).to receive(:finished_all_ajax_requests?).and_return(true) allow(subject).to receive(:finished_all_ajax_requests?).and_return(true)
allow(subject).to receive(:finished_loading?).and_return(true) allow(subject).to receive(:finished_loading?).and_return(true)
end end
......
...@@ -18,7 +18,9 @@ RSpec.describe 'Projects > Show > User manages notifications', :js do ...@@ -18,7 +18,9 @@ RSpec.describe 'Projects > Show > User manages notifications', :js do
click_notifications_button click_notifications_button
click_link 'On mention' click_link 'On mention'
wait_for_requests page.within('.notification-dropdown') do
expect(page).not_to have_css('.gl-spinner')
end
click_notifications_button click_notifications_button
expect(find('.update-notification.is-active')).to have_content('On mention') expect(find('.update-notification.is-active')).to have_content('On mention')
...@@ -30,7 +32,9 @@ RSpec.describe 'Projects > Show > User manages notifications', :js do ...@@ -30,7 +32,9 @@ RSpec.describe 'Projects > Show > User manages notifications', :js do
click_notifications_button click_notifications_button
click_link 'Disabled' click_link 'Disabled'
wait_for_requests page.within('.notification-dropdown') do
expect(page).not_to have_css('.gl-spinner')
end
expect(page).to have_css('.notifications-icon[data-testid="notifications-off-icon"]') expect(page).to have_css('.notifications-icon[data-testid="notifications-off-icon"]')
end end
......
import Vue from 'vue'; import Vue from 'vue';
import 'jquery';
import * as jqueryMatchers from 'custom-jquery-matchers'; import * as jqueryMatchers from 'custom-jquery-matchers';
import { config as testUtilsConfig } from '@vue/test-utils'; import { config as testUtilsConfig } from '@vue/test-utils';
import Translate from '~/vue_shared/translate'; import Translate from '~/vue_shared/translate';
...@@ -9,7 +11,6 @@ import customMatchers from './matchers'; ...@@ -9,7 +11,6 @@ import customMatchers from './matchers';
import './helpers/dom_shims'; import './helpers/dom_shims';
import './helpers/jquery'; import './helpers/jquery';
import '~/commons/jquery';
import '~/commons/bootstrap'; import '~/commons/bootstrap';
process.on('unhandledRejection', global.promiseRejectionHandler); process.on('unhandledRejection', global.promiseRejectionHandler);
......
...@@ -48,17 +48,10 @@ module WaitForRequests ...@@ -48,17 +48,10 @@ module WaitForRequests
def finished_all_js_requests? def finished_all_js_requests?
return true unless javascript_test? return true unless javascript_test?
finished_all_ajax_requests? && finished_all_ajax_requests?
finished_all_axios_requests?
end
def finished_all_axios_requests?
Capybara.page.evaluate_script('window.pendingRequests || 0').zero? # rubocop:disable Style/NumericPredicate
end end
def finished_all_ajax_requests? def finished_all_ajax_requests?
return true if Capybara.page.evaluate_script('typeof jQuery === "undefined"') Capybara.page.evaluate_script('window.pendingRequests || window.pendingRailsUJSRequests || 0').zero? # rubocop:disable Style/NumericPredicate
Capybara.page.evaluate_script('jQuery.active').zero? # rubocop:disable Style/NumericPredicate
end end
end end
...@@ -1076,6 +1076,11 @@ ...@@ -1076,6 +1076,11 @@
resolved "https://registry.yarnpkg.com/@rails/actioncable/-/actioncable-6.0.3-1.tgz#9b9eb8858a6507162911007d355d9a206e1c5caa" resolved "https://registry.yarnpkg.com/@rails/actioncable/-/actioncable-6.0.3-1.tgz#9b9eb8858a6507162911007d355d9a206e1c5caa"
integrity sha512-szFhWD+V5TAxVNVIG16klgq+ypqA5k5AecLarTTrXgOG8cawVbQdOAwLbCmzkwiQ60rGSxAFoC1u2LrzxSK2Aw== integrity sha512-szFhWD+V5TAxVNVIG16klgq+ypqA5k5AecLarTTrXgOG8cawVbQdOAwLbCmzkwiQ60rGSxAFoC1u2LrzxSK2Aw==
"@rails/ujs@^6.0.3-2":
version "6.0.3-2"
resolved "https://registry.yarnpkg.com/@rails/ujs/-/ujs-6.0.3-2.tgz#e14c1f29086858215ce7ccd9ad6d8888c458b4a3"
integrity sha512-WcpIEftNCfGDEgk6KerOugiet75Mir5q/HT1yt3dDhpBI91BaZ15lfSQIsZwMw2nyeDz9A9QBz8dAFAd4gXIzg==
"@sentry/browser@^5.22.3": "@sentry/browser@^5.22.3":
version "5.22.3" version "5.22.3"
resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-5.22.3.tgz#7a64bd1cf01bf393741a3e4bf35f82aa927f5b4e" resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-5.22.3.tgz#7a64bd1cf01bf393741a3e4bf35f82aa927f5b4e"
...@@ -7068,13 +7073,6 @@ jmespath@0.15.0: ...@@ -7068,13 +7073,6 @@ jmespath@0.15.0:
resolved "https://registry.yarnpkg.com/jmespath/-/jmespath-0.15.0.tgz#a3f222a9aae9f966f5d27c796510e28091764217" resolved "https://registry.yarnpkg.com/jmespath/-/jmespath-0.15.0.tgz#a3f222a9aae9f966f5d27c796510e28091764217"
integrity sha1-o/Iiqarp+Wb10nx5ZRDigJF2Qhc= integrity sha1-o/Iiqarp+Wb10nx5ZRDigJF2Qhc=
jquery-ujs@1.2.2:
version "1.2.2"
resolved "https://registry.yarnpkg.com/jquery-ujs/-/jquery-ujs-1.2.2.tgz#6a8ef1020e6b6dda385b90a4bddc128c21c56397"
integrity sha1-ao7xAg5rbdo4W5CkvdwSjCHFY5c=
dependencies:
jquery ">=1.8.0"
jquery.caret@^0.3.1: jquery.caret@^0.3.1:
version "0.3.1" version "0.3.1"
resolved "https://registry.yarnpkg.com/jquery.caret/-/jquery.caret-0.3.1.tgz#9c093318faf327eff322e826ca9f3241368bc7b8" resolved "https://registry.yarnpkg.com/jquery.caret/-/jquery.caret-0.3.1.tgz#9c093318faf327eff322e826ca9f3241368bc7b8"
...@@ -7085,7 +7083,7 @@ jquery.waitforimages@^2.2.0: ...@@ -7085,7 +7083,7 @@ jquery.waitforimages@^2.2.0:
resolved "https://registry.yarnpkg.com/jquery.waitforimages/-/jquery.waitforimages-2.2.0.tgz#63f23131055a1b060dc913e6d874bcc9b9e6b16b" resolved "https://registry.yarnpkg.com/jquery.waitforimages/-/jquery.waitforimages-2.2.0.tgz#63f23131055a1b060dc913e6d874bcc9b9e6b16b"
integrity sha1-Y/IxMQVaGwYNyRPm2HS8ybnmsWs= integrity sha1-Y/IxMQVaGwYNyRPm2HS8ybnmsWs=
"jquery@>= 1.9.1", jquery@>=1.8.0, jquery@^3.5.0: "jquery@>= 1.9.1", jquery@^3.5.0:
version "3.5.1" version "3.5.1"
resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.5.1.tgz#d7b4d08e1bfdb86ad2f1a3d039ea17304717abb5" resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.5.1.tgz#d7b4d08e1bfdb86ad2f1a3d039ea17304717abb5"
integrity sha512-XwIBPqcMn57FxfT+Go5pzySnm4KWkT1Tv7gjrpT1srtf8Weynl6R273VJ5GjkRb51IzMp5nbaPjJXMWeju2MKg== integrity sha512-XwIBPqcMn57FxfT+Go5pzySnm4KWkT1Tv7gjrpT1srtf8Weynl6R273VJ5GjkRb51IzMp5nbaPjJXMWeju2MKg==
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment