diff options
Diffstat (limited to 'app/assets/javascripts/pages')
67 files changed, 476 insertions, 509 deletions
diff --git a/app/assets/javascripts/pages/admin/admin.js b/app/assets/javascripts/pages/admin/admin.js index 88967d82b2f..038bbe392ba 100644 --- a/app/assets/javascripts/pages/admin/admin.js +++ b/app/assets/javascripts/pages/admin/admin.js @@ -1,13 +1,13 @@ import $ from 'jquery'; import { refreshCurrentPage } from '../../lib/utils/url_utility'; -function showBlacklistType() { - if ($('input[name="blacklist_type"]:checked').val() === 'file') { - $('.blacklist-file').show(); - $('.blacklist-raw').hide(); +function showDenylistType() { + if ($('input[name="denylist_type"]:checked').val() === 'file') { + $('.js-denylist-file').show(); + $('.js-denylist-raw').hide(); } else { - $('.blacklist-file').hide(); - $('.blacklist-raw').show(); + $('.js-denylist-file').hide(); + $('.js-denylist-raw').show(); } } @@ -60,6 +60,6 @@ export default function adminInit() { $('li.project_member, li.group_member').on('ajax:success', refreshCurrentPage); - $("input[name='blacklist_type']").on('click', showBlacklistType); - showBlacklistType(); + $("input[name='denylist_type']").on('click', showDenylistType); + showDenylistType(); } diff --git a/app/assets/javascripts/pages/admin/application_settings/general/index.js b/app/assets/javascripts/pages/admin/application_settings/general/index.js index 8183e81fb02..af1595398a8 100644 --- a/app/assets/javascripts/pages/admin/application_settings/general/index.js +++ b/app/assets/javascripts/pages/admin/application_settings/general/index.js @@ -1,3 +1,21 @@ +import Vue from 'vue'; import initUserInternalRegexPlaceholder from '../account_and_limits'; +import IntegrationHelpText from '~/vue_shared/components/integrations_help_text.vue'; -document.addEventListener('DOMContentLoaded', initUserInternalRegexPlaceholder()); +document.addEventListener('DOMContentLoaded', () => { + initUserInternalRegexPlaceholder(); + + const gitpodSettingEl = document.querySelector('#js-gitpod-settings-help-text'); + if (!gitpodSettingEl) { + return; + } + + // eslint-disable-next-line no-new + new Vue({ + el: gitpodSettingEl, + name: 'GitpodSettings', + components: { + IntegrationHelpText, + }, + }); +}); diff --git a/app/assets/javascripts/pages/admin/dev_ops_report/index.js b/app/assets/javascripts/pages/admin/dev_ops_report/index.js index 643497003ba..220fc049562 100644 --- a/app/assets/javascripts/pages/admin/dev_ops_report/index.js +++ b/app/assets/javascripts/pages/admin/dev_ops_report/index.js @@ -1,27 +1,5 @@ -import Vue from 'vue'; -import UserCallout from '~/user_callout'; -import UsagePingDisabled from '~/admin/dev_ops_report/components/usage_ping_disabled.vue'; +import initDevopAdoption from 'ee_else_ce/admin/dev_ops_report/devops_adoption'; +import initDevOpsScoreEmptyState from '~/admin/dev_ops_report/devops_score_empty_state'; -document.addEventListener('DOMContentLoaded', () => { - // eslint-disable-next-line no-new - new UserCallout(); - - const emptyStateContainer = document.getElementById('js-devops-empty-state'); - - if (!emptyStateContainer) return false; - - const { emptyStateSvgPath, enableUsagePingLink, docsLink, isAdmin } = emptyStateContainer.dataset; - - return new Vue({ - el: emptyStateContainer, - provide: { - isAdmin: Boolean(isAdmin), - svgPath: emptyStateSvgPath, - primaryButtonPath: enableUsagePingLink, - docsLink, - }, - render(h) { - return h(UsagePingDisabled); - }, - }); -}); +initDevOpsScoreEmptyState(); +initDevopAdoption(); diff --git a/app/assets/javascripts/pages/admin/jobs/index/components/stop_jobs_modal.vue b/app/assets/javascripts/pages/admin/jobs/index/components/stop_jobs_modal.vue index 120512bf15e..4b6f52c09be 100644 --- a/app/assets/javascripts/pages/admin/jobs/index/components/stop_jobs_modal.vue +++ b/app/assets/javascripts/pages/admin/jobs/index/components/stop_jobs_modal.vue @@ -1,13 +1,13 @@ <script> +import { GlModal } from '@gitlab/ui'; import axios from '~/lib/utils/axios_utils'; import { deprecatedCreateFlash as createFlash } from '~/flash'; -import DeprecatedModal2 from '~/vue_shared/components/deprecated_modal_2.vue'; import { redirectTo } from '~/lib/utils/url_utility'; -import { s__ } from '~/locale'; +import { __, s__ } from '~/locale'; export default { components: { - GlModal: DeprecatedModal2, + GlModal, }, props: { url: { @@ -36,17 +36,24 @@ export default { }); }, }, + primaryAction: { + text: s__('AdminArea|Stop jobs'), + attributes: [{ variant: 'danger' }], + }, + cancelAction: { + text: __('Cancel'), + }, }; </script> <template> <gl-modal - id="stop-jobs-modal" - :header-title-text="s__('AdminArea|Stop all jobs?')" - :footer-primary-button-text="s__('AdminArea|Stop jobs')" - footer-primary-button-variant="danger" - @submit="onSubmit" + modal-id="stop-jobs-modal" + :action-primary="$options.primaryAction" + :action-cancel="$options.cancelAction" + @primary="onSubmit" > + <template #modal-title>{{ s__('AdminArea|Stop all jobs?') }}</template> {{ text }} </gl-modal> </template> diff --git a/app/assets/javascripts/pages/admin/jobs/index/index.js b/app/assets/javascripts/pages/admin/jobs/index/index.js index 5a4f8c6e745..4df210debb5 100644 --- a/app/assets/javascripts/pages/admin/jobs/index/index.js +++ b/app/assets/javascripts/pages/admin/jobs/index/index.js @@ -5,19 +5,24 @@ import stopJobsModal from './components/stop_jobs_modal.vue'; Vue.use(Translate); document.addEventListener('DOMContentLoaded', () => { - const stopJobsButton = document.getElementById('stop-jobs-button'); + const buttonId = 'js-stop-jobs-button'; + const modalId = 'stop-jobs-modal'; + const stopJobsButton = document.getElementById(buttonId); if (stopJobsButton) { // eslint-disable-next-line no-new new Vue({ - el: '#stop-jobs-modal', + el: `#js-${modalId}`, components: { stopJobsModal, }, mounted() { stopJobsButton.classList.remove('disabled'); + stopJobsButton.addEventListener('click', () => { + this.$root.$emit('bv::show::modal', modalId, `#${buttonId}`); + }); }, render(createElement) { - return createElement('stop-jobs-modal', { + return createElement(modalId, { props: { url: stopJobsButton.dataset.url, }, diff --git a/app/assets/javascripts/pages/admin/runners/index.js b/app/assets/javascripts/pages/admin/runners/index.js index e60c6133c7c..104b7eeaf96 100644 --- a/app/assets/javascripts/pages/admin/runners/index.js +++ b/app/assets/javascripts/pages/admin/runners/index.js @@ -1,11 +1,12 @@ import initFilteredSearch from '~/pages/search/init_filtered_search'; import AdminRunnersFilteredSearchTokenKeys from '~/filtered_search/admin_runners_filtered_search_token_keys'; import { FILTERED_SEARCH } from '~/pages/constants'; +import { initInstallRunner } from '~/pages/shared/mount_runner_instructions'; -document.addEventListener('DOMContentLoaded', () => { - initFilteredSearch({ - page: FILTERED_SEARCH.ADMIN_RUNNERS, - filteredSearchTokenKeys: AdminRunnersFilteredSearchTokenKeys, - useDefaultState: true, - }); +initFilteredSearch({ + page: FILTERED_SEARCH.ADMIN_RUNNERS, + filteredSearchTokenKeys: AdminRunnersFilteredSearchTokenKeys, + useDefaultState: true, }); + +initInstallRunner(); diff --git a/app/assets/javascripts/pages/admin/users/index.js b/app/assets/javascripts/pages/admin/users/index.js index 86c4b4f4f48..5f3cdc0bfc6 100644 --- a/app/assets/javascripts/pages/admin/users/index.js +++ b/app/assets/javascripts/pages/admin/users/index.js @@ -5,12 +5,12 @@ import ModalManager from './components/user_modal_manager.vue'; import DeleteUserModal from './components/delete_user_modal.vue'; import UserOperationConfirmationModal from './components/user_operation_confirmation_modal.vue'; import csrf from '~/lib/utils/csrf'; +import initConfirmModal from '~/confirm_modal'; const MODAL_TEXTS_CONTAINER_SELECTOR = '#modal-texts'; const MODAL_MANAGER_SELECTOR = '#user-modal'; const ACTION_MODALS = { deactivate: UserOperationConfirmationModal, - block: UserOperationConfirmationModal, delete: DeleteUserModal, 'delete-with-contributions': DeleteUserModal, }; @@ -62,4 +62,6 @@ document.addEventListener('DOMContentLoaded', () => { }); }, }); + + initConfirmModal(); }); diff --git a/app/assets/javascripts/pages/groups/boards/index.js b/app/assets/javascripts/pages/groups/boards/index.js index 79c3be771d0..922f39627c9 100644 --- a/app/assets/javascripts/pages/groups/boards/index.js +++ b/app/assets/javascripts/pages/groups/boards/index.js @@ -2,8 +2,6 @@ import UsersSelect from '~/users_select'; import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation'; import initBoards from '~/boards'; -document.addEventListener('DOMContentLoaded', () => { - new UsersSelect(); // eslint-disable-line no-new - new ShortcutsNavigation(); // eslint-disable-line no-new - initBoards(); -}); +new UsersSelect(); // eslint-disable-line no-new +new ShortcutsNavigation(); // eslint-disable-line no-new +initBoards(); diff --git a/app/assets/javascripts/pages/groups/clusters/destroy/index.js b/app/assets/javascripts/pages/groups/clusters/destroy/index.js index 8001d2dd1da..487e7a14a16 100644 --- a/app/assets/javascripts/pages/groups/clusters/destroy/index.js +++ b/app/assets/javascripts/pages/groups/clusters/destroy/index.js @@ -1,5 +1,3 @@ import ClustersBundle from '~/clusters/clusters_bundle'; -document.addEventListener('DOMContentLoaded', () => { - new ClustersBundle(); // eslint-disable-line no-new -}); +new ClustersBundle(); // eslint-disable-line no-new diff --git a/app/assets/javascripts/pages/groups/clusters/edit/index.js b/app/assets/javascripts/pages/groups/clusters/edit/index.js index 8001d2dd1da..487e7a14a16 100644 --- a/app/assets/javascripts/pages/groups/clusters/edit/index.js +++ b/app/assets/javascripts/pages/groups/clusters/edit/index.js @@ -1,5 +1,3 @@ import ClustersBundle from '~/clusters/clusters_bundle'; -document.addEventListener('DOMContentLoaded', () => { - new ClustersBundle(); // eslint-disable-line no-new -}); +new ClustersBundle(); // eslint-disable-line no-new diff --git a/app/assets/javascripts/pages/groups/clusters/index.js b/app/assets/javascripts/pages/groups/clusters/index.js index 9f466e0d60a..3b92c244346 100644 --- a/app/assets/javascripts/pages/groups/clusters/index.js +++ b/app/assets/javascripts/pages/groups/clusters/index.js @@ -1,7 +1,5 @@ import initCreateCluster from '~/create_cluster/init_create_cluster'; import initIntegrationForm from '~/clusters/forms/show/index'; -document.addEventListener('DOMContentLoaded', () => { - initCreateCluster(document, gon); - initIntegrationForm(); -}); +initCreateCluster(document, gon); +initIntegrationForm(); diff --git a/app/assets/javascripts/pages/groups/clusters/index/index.js b/app/assets/javascripts/pages/groups/clusters/index/index.js index 744be65bfbe..3b71517f017 100644 --- a/app/assets/javascripts/pages/groups/clusters/index/index.js +++ b/app/assets/javascripts/pages/groups/clusters/index/index.js @@ -1,8 +1,6 @@ import PersistentUserCallout from '~/persistent_user_callout'; import initClustersListApp from '~/clusters_list'; -document.addEventListener('DOMContentLoaded', () => { - const callout = document.querySelector('.gcp-signup-offer'); - PersistentUserCallout.factory(callout); - initClustersListApp(); -}); +const callout = document.querySelector('.gcp-signup-offer'); +PersistentUserCallout.factory(callout); +initClustersListApp(); diff --git a/app/assets/javascripts/pages/groups/clusters/new/index.js b/app/assets/javascripts/pages/groups/clusters/new/index.js index 876bab0b339..de9ded87ef3 100644 --- a/app/assets/javascripts/pages/groups/clusters/new/index.js +++ b/app/assets/javascripts/pages/groups/clusters/new/index.js @@ -1,5 +1,3 @@ import initNewCluster from '~/clusters/new_cluster'; -document.addEventListener('DOMContentLoaded', () => { - initNewCluster(); -}); +initNewCluster(); diff --git a/app/assets/javascripts/pages/groups/clusters/show/index.js b/app/assets/javascripts/pages/groups/clusters/show/index.js index ccf631b2c53..5d202a8824f 100644 --- a/app/assets/javascripts/pages/groups/clusters/show/index.js +++ b/app/assets/javascripts/pages/groups/clusters/show/index.js @@ -1,7 +1,5 @@ import ClustersBundle from '~/clusters/clusters_bundle'; import initClusterHealth from '~/pages/projects/clusters/show/cluster_health'; -document.addEventListener('DOMContentLoaded', () => { - new ClustersBundle(); // eslint-disable-line no-new - initClusterHealth(); -}); +new ClustersBundle(); // eslint-disable-line no-new +initClusterHealth(); diff --git a/app/assets/javascripts/pages/groups/dependency_proxies/index.js b/app/assets/javascripts/pages/groups/dependency_proxies/index.js new file mode 100644 index 00000000000..77c885d3858 --- /dev/null +++ b/app/assets/javascripts/pages/groups/dependency_proxies/index.js @@ -0,0 +1,13 @@ +import $ from 'jquery'; +import initDependencyProxy from '~/dependency_proxy'; + +initDependencyProxy(); + +const form = document.querySelector('form.edit_dependency_proxy_group_setting'); +const toggleInput = $('input.js-project-feature-toggle-input'); + +if (form && toggleInput) { + toggleInput.on('trigger-change', () => { + form.submit(); + }); +} diff --git a/app/assets/javascripts/pages/groups/details/index.js b/app/assets/javascripts/pages/groups/details/index.js index 3bcaa0f0232..0417134f2a7 100644 --- a/app/assets/javascripts/pages/groups/details/index.js +++ b/app/assets/javascripts/pages/groups/details/index.js @@ -1,5 +1,3 @@ import initGroupDetails from '../shared/group_details'; -document.addEventListener('DOMContentLoaded', () => { - initGroupDetails('details'); -}); +initGroupDetails('details'); diff --git a/app/assets/javascripts/pages/groups/group_members/index.js b/app/assets/javascripts/pages/groups/group_members/index.js index dc647f5d3cb..009a3eee526 100644 --- a/app/assets/javascripts/pages/groups/group_members/index.js +++ b/app/assets/javascripts/pages/groups/group_members/index.js @@ -21,35 +21,36 @@ function mountRemoveMemberModal() { }); } -document.addEventListener('DOMContentLoaded', () => { - groupsSelect(); - memberExpirationDate(); - memberExpirationDate('.js-access-expiration-date-groups'); - mountRemoveMemberModal(); +const SHARED_FIELDS = ['account', 'expires', 'maxRole', 'expiration', 'actions']; +initGroupMembersApp( + document.querySelector('.js-group-members-list'), + SHARED_FIELDS.concat(['source', 'granted']), + { tr: { 'data-qa-selector': 'member_row' } }, + memberRequestFormatter, +); +initGroupMembersApp( + document.querySelector('.js-group-linked-list'), + SHARED_FIELDS.concat('granted'), + { table: { 'data-qa-selector': 'groups_list' }, tr: { 'data-qa-selector': 'group_row' } }, + groupLinkRequestFormatter, +); +initGroupMembersApp( + document.querySelector('.js-group-invited-members-list'), + SHARED_FIELDS.concat('invited'), + {}, + memberRequestFormatter, +); +initGroupMembersApp( + document.querySelector('.js-group-access-requests-list'), + SHARED_FIELDS.concat('requested'), + {}, + memberRequestFormatter, +); - const SHARED_FIELDS = ['account', 'expires', 'maxRole', 'expiration', 'actions']; +groupsSelect(); +memberExpirationDate(); +memberExpirationDate('.js-access-expiration-date-groups'); +mountRemoveMemberModal(); - initGroupMembersApp( - document.querySelector('.js-group-members-list'), - SHARED_FIELDS.concat(['source', 'granted']), - memberRequestFormatter, - ); - initGroupMembersApp( - document.querySelector('.js-group-linked-list'), - SHARED_FIELDS.concat('granted'), - groupLinkRequestFormatter, - ); - initGroupMembersApp( - document.querySelector('.js-group-invited-members-list'), - SHARED_FIELDS.concat('invited'), - memberRequestFormatter, - ); - initGroupMembersApp( - document.querySelector('.js-group-access-requests-list'), - SHARED_FIELDS.concat('requested'), - memberRequestFormatter, - ); - - new Members(); // eslint-disable-line no-new - new UsersSelect(); // eslint-disable-line no-new -}); +new Members(); // eslint-disable-line no-new +new UsersSelect(); // eslint-disable-line no-new diff --git a/app/assets/javascripts/pages/groups/labels/edit/index.js b/app/assets/javascripts/pages/groups/labels/edit/index.js index 83d6ac9fd14..2e8308fe084 100644 --- a/app/assets/javascripts/pages/groups/labels/edit/index.js +++ b/app/assets/javascripts/pages/groups/labels/edit/index.js @@ -1,3 +1,4 @@ import Labels from 'ee_else_ce/labels'; -document.addEventListener('DOMContentLoaded', () => new Labels()); +// eslint-disable-next-line no-new +new Labels(); diff --git a/app/assets/javascripts/pages/groups/labels/index/index.js b/app/assets/javascripts/pages/groups/labels/index/index.js index 6e45de2a724..87d522d7654 100644 --- a/app/assets/javascripts/pages/groups/labels/index/index.js +++ b/app/assets/javascripts/pages/groups/labels/index/index.js @@ -1,3 +1,3 @@ import initLabels from '~/init_labels'; -document.addEventListener('DOMContentLoaded', initLabels); +initLabels(); diff --git a/app/assets/javascripts/pages/groups/labels/new/index.js b/app/assets/javascripts/pages/groups/labels/new/index.js index 83d6ac9fd14..2e8308fe084 100644 --- a/app/assets/javascripts/pages/groups/labels/new/index.js +++ b/app/assets/javascripts/pages/groups/labels/new/index.js @@ -1,3 +1,4 @@ import Labels from 'ee_else_ce/labels'; -document.addEventListener('DOMContentLoaded', () => new Labels()); +// eslint-disable-next-line no-new +new Labels(); diff --git a/app/assets/javascripts/pages/groups/merge_requests/index.js b/app/assets/javascripts/pages/groups/merge_requests/index.js index 71c67ac74ed..2832cbed5ac 100644 --- a/app/assets/javascripts/pages/groups/merge_requests/index.js +++ b/app/assets/javascripts/pages/groups/merge_requests/index.js @@ -7,15 +7,13 @@ import { FILTERED_SEARCH } from '~/pages/constants'; const ISSUABLE_BULK_UPDATE_PREFIX = 'merge_request_'; -document.addEventListener('DOMContentLoaded', () => { - addExtraTokensForMergeRequests(IssuableFilteredSearchTokenKeys); - issuableInitBulkUpdateSidebar.init(ISSUABLE_BULK_UPDATE_PREFIX); +addExtraTokensForMergeRequests(IssuableFilteredSearchTokenKeys); +issuableInitBulkUpdateSidebar.init(ISSUABLE_BULK_UPDATE_PREFIX); - initFilteredSearch({ - page: FILTERED_SEARCH.MERGE_REQUESTS, - isGroupDecendent: true, - useDefaultState: true, - filteredSearchTokenKeys: IssuableFilteredSearchTokenKeys, - }); - projectSelect(); +initFilteredSearch({ + page: FILTERED_SEARCH.MERGE_REQUESTS, + isGroupDecendent: true, + useDefaultState: true, + filteredSearchTokenKeys: IssuableFilteredSearchTokenKeys, }); +projectSelect(); diff --git a/app/assets/javascripts/pages/groups/milestones/edit/index.js b/app/assets/javascripts/pages/groups/milestones/edit/index.js index ddd10fe5062..af0264c7992 100644 --- a/app/assets/javascripts/pages/groups/milestones/edit/index.js +++ b/app/assets/javascripts/pages/groups/milestones/edit/index.js @@ -1,3 +1,3 @@ import initForm from '../../../../shared/milestones/form'; -document.addEventListener('DOMContentLoaded', () => initForm(false)); +initForm(false); diff --git a/app/assets/javascripts/pages/groups/milestones/new/index.js b/app/assets/javascripts/pages/groups/milestones/new/index.js index ddd10fe5062..af0264c7992 100644 --- a/app/assets/javascripts/pages/groups/milestones/new/index.js +++ b/app/assets/javascripts/pages/groups/milestones/new/index.js @@ -1,3 +1,3 @@ import initForm from '../../../../shared/milestones/form'; -document.addEventListener('DOMContentLoaded', () => initForm(false)); +initForm(false); diff --git a/app/assets/javascripts/pages/groups/new/index.js b/app/assets/javascripts/pages/groups/new/index.js index 640e64b5d3e..7021473b380 100644 --- a/app/assets/javascripts/pages/groups/new/index.js +++ b/app/assets/javascripts/pages/groups/new/index.js @@ -4,13 +4,11 @@ import Group from '~/group'; import GroupPathValidator from './group_path_validator'; import initFilePickers from '~/file_pickers'; -document.addEventListener('DOMContentLoaded', () => { - const parentId = $('#group_parent_id'); - if (!parentId.val()) { - new GroupPathValidator(); // eslint-disable-line no-new - } - BindInOut.initAll(); - initFilePickers(); +const parentId = $('#group_parent_id'); +if (!parentId.val()) { + new GroupPathValidator(); // eslint-disable-line no-new +} +BindInOut.initAll(); +initFilePickers(); - return new Group(); -}); +new Group(); // eslint-disable-line no-new diff --git a/app/assets/javascripts/pages/groups/packages/index/index.js b/app/assets/javascripts/pages/groups/packages/index/index.js index 4836900aa28..1c4a10fd653 100644 --- a/app/assets/javascripts/pages/groups/packages/index/index.js +++ b/app/assets/javascripts/pages/groups/packages/index/index.js @@ -1,7 +1,5 @@ import initPackageList from '~/packages/list/packages_list_app_bundle'; -document.addEventListener('DOMContentLoaded', () => { - if (document.getElementById('js-vue-packages-list')) { - initPackageList(); - } -}); +if (document.getElementById('js-vue-packages-list')) { + initPackageList(); +} diff --git a/app/assets/javascripts/pages/groups/settings/ci_cd/show/index.js b/app/assets/javascripts/pages/groups/settings/ci_cd/show/index.js index 67eb09da5e0..3456048d718 100644 --- a/app/assets/javascripts/pages/groups/settings/ci_cd/show/index.js +++ b/app/assets/javascripts/pages/groups/settings/ci_cd/show/index.js @@ -1,35 +1,21 @@ import initSettingsPanels from '~/settings_panels'; -import AjaxVariableList from '~/ci_variable_list/ajax_variable_list'; import initVariableList from '~/ci_variable_list'; import initFilteredSearch from '~/pages/search/init_filtered_search'; import GroupRunnersFilteredSearchTokenKeys from '~/filtered_search/group_runners_filtered_search_token_keys'; import { FILTERED_SEARCH } from '~/pages/constants'; import initSharedRunnersForm from '~/group_settings/mount_shared_runners'; +import { initInstallRunner } from '~/pages/shared/mount_runner_instructions'; -document.addEventListener('DOMContentLoaded', () => { - // Initialize expandable settings panels - initSettingsPanels(); +// Initialize expandable settings panels +initSettingsPanels(); - initFilteredSearch({ - page: FILTERED_SEARCH.ADMIN_RUNNERS, - filteredSearchTokenKeys: GroupRunnersFilteredSearchTokenKeys, - anchor: FILTERED_SEARCH.GROUP_RUNNERS_ANCHOR, - useDefaultState: false, - }); - - if (gon.features.newVariablesUi) { - initVariableList(); - } else { - const variableListEl = document.querySelector('.js-ci-variable-list-section'); - // eslint-disable-next-line no-new - new AjaxVariableList({ - container: variableListEl, - saveButton: variableListEl.querySelector('.js-ci-variables-save-button'), - errorBox: variableListEl.querySelector('.js-ci-variable-error-box'), - saveEndpoint: variableListEl.dataset.saveEndpoint, - maskableRegex: variableListEl.dataset.maskableRegex, - }); - } - - initSharedRunnersForm(); +initFilteredSearch({ + page: FILTERED_SEARCH.ADMIN_RUNNERS, + filteredSearchTokenKeys: GroupRunnersFilteredSearchTokenKeys, + anchor: FILTERED_SEARCH.GROUP_RUNNERS_ANCHOR, + useDefaultState: false, }); + +initSharedRunnersForm(); +initVariableList(); +initInstallRunner(); diff --git a/app/assets/javascripts/pages/groups/shared/group_details.js b/app/assets/javascripts/pages/groups/shared/group_details.js index 8546b1f759f..8d956c694c0 100644 --- a/app/assets/javascripts/pages/groups/shared/group_details.js +++ b/app/assets/javascripts/pages/groups/shared/group_details.js @@ -2,7 +2,6 @@ import { getPagePath, getDashPath } from '~/lib/utils/common_utils'; import { ACTIVE_TAB_SHARED, ACTIVE_TAB_ARCHIVED } from '~/groups/constants'; -import NewGroupChild from '~/groups/new_group_child'; import notificationsDropdown from '~/notifications_dropdown'; import NotificationsForm from '~/notifications_form'; import ProjectsList from '~/projects_list'; @@ -11,7 +10,6 @@ import GroupTabs from './group_tabs'; import initInviteMembersBanner from '~/groups/init_invite_members_banner'; export default function initGroupDetails(actionName = 'show') { - const newGroupChildWrapper = document.querySelector('.js-new-project-subgroup'); const loadableActions = [ACTIVE_TAB_SHARED, ACTIVE_TAB_ARCHIVED]; const dashPath = getDashPath(); let action = loadableActions.includes(dashPath) ? dashPath : getPagePath(1); @@ -25,8 +23,5 @@ export default function initGroupDetails(actionName = 'show') { notificationsDropdown(); new ProjectsList(); - if (newGroupChildWrapper) { - new NewGroupChild(newGroupChildWrapper); - } initInviteMembersBanner(); } diff --git a/app/assets/javascripts/pages/profiles/preferences/show/index.js b/app/assets/javascripts/pages/profiles/preferences/show/index.js new file mode 100644 index 00000000000..d489ed80f46 --- /dev/null +++ b/app/assets/javascripts/pages/profiles/preferences/show/index.js @@ -0,0 +1,3 @@ +import initProfilePreferences from '~/profile/preferences/profile_preferences_bundle'; + +document.addEventListener('DOMContentLoaded', initProfilePreferences); diff --git a/app/assets/javascripts/pages/projects/alert_management/details/index.js b/app/assets/javascripts/pages/projects/alert_management/details/index.js index 0124795e1af..a20f6713c9d 100644 --- a/app/assets/javascripts/pages/projects/alert_management/details/index.js +++ b/app/assets/javascripts/pages/projects/alert_management/details/index.js @@ -1,5 +1,3 @@ import AlertDetails from '~/alert_management/details'; -document.addEventListener('DOMContentLoaded', () => { - AlertDetails('#js-alert_details'); -}); +AlertDetails('#js-alert_details'); diff --git a/app/assets/javascripts/pages/projects/alert_management/index/index.js b/app/assets/javascripts/pages/projects/alert_management/index/index.js index 1e98bcfd2eb..ed352f0ad7a 100644 --- a/app/assets/javascripts/pages/projects/alert_management/index/index.js +++ b/app/assets/javascripts/pages/projects/alert_management/index/index.js @@ -1,5 +1,3 @@ import AlertManagementList from '~/alert_management/list'; -document.addEventListener('DOMContentLoaded', () => { - AlertManagementList(); -}); +AlertManagementList(); diff --git a/app/assets/javascripts/pages/projects/blob/show/index.js b/app/assets/javascripts/pages/projects/blob/show/index.js index f2e8cb38ef5..1879e263ce7 100644 --- a/app/assets/javascripts/pages/projects/blob/show/index.js +++ b/app/assets/javascripts/pages/projects/blob/show/index.js @@ -7,7 +7,6 @@ import initWebIdeLink from '~/pages/projects/shared/web_ide_link'; import '~/sourcegraph/load'; import PipelineTourSuccessModal from '~/blob/pipeline_tour_success_modal.vue'; import { parseBoolean } from '~/lib/utils/common_utils'; -import { isExperimentEnabled } from '~/lib/utils/experimentation'; const createGitlabCiYmlVisualization = (containerId = '#js-blob-toggle-graph-preview') => { const el = document.querySelector(containerId); @@ -74,7 +73,7 @@ document.addEventListener('DOMContentLoaded', () => { ); } - if (isExperimentEnabled('suggestPipeline')) { + if (gon.features?.suggestPipeline) { const successPipelineEl = document.querySelector('.js-success-pipeline-modal'); if (successPipelineEl) { diff --git a/app/assets/javascripts/pages/projects/ci/lints/ci_lint_editor.js b/app/assets/javascripts/pages/projects/ci/lints/ci_lint_editor.js deleted file mode 100644 index df635522e94..00000000000 --- a/app/assets/javascripts/pages/projects/ci/lints/ci_lint_editor.js +++ /dev/null @@ -1,32 +0,0 @@ -import EditorLite from '~/editor/editor_lite'; - -export default class CILintEditor { - constructor() { - this.clearYml = document.querySelector('.clear-yml'); - this.clearYml.addEventListener('click', this.clear.bind(this)); - - return this.initEditorLite(); - } - - clear() { - this.editor.setValue(''); - } - - initEditorLite() { - const editorEl = document.getElementById('editor'); - const fileContentEl = document.getElementById('content'); - const form = document.querySelector('.js-ci-lint-form'); - - const rootEditor = new EditorLite(); - - this.editor = rootEditor.createInstance({ - el: editorEl, - blobPath: '.gitlab-ci.yml', - blobContent: editorEl.innerText, - }); - - form.addEventListener('submit', () => { - fileContentEl.value = this.editor.getValue(); - }); - } -} diff --git a/app/assets/javascripts/pages/projects/ci/lints/new/index.js b/app/assets/javascripts/pages/projects/ci/lints/new/index.js deleted file mode 100644 index 957801320c9..00000000000 --- a/app/assets/javascripts/pages/projects/ci/lints/new/index.js +++ /dev/null @@ -1,17 +0,0 @@ -import createFlash from '~/flash'; -import { __ } from '~/locale'; - -const ERROR = __('An error occurred while rendering the linter'); - -document.addEventListener('DOMContentLoaded', () => { - if (gon?.features?.ciLintVue) { - import(/* webpackChunkName: 'ciLintIndex' */ '~/ci_lint/index') - .then(module => module.default()) - .catch(() => createFlash(ERROR)); - } else { - import(/* webpackChunkName: 'ciLintEditor' */ '../ci_lint_editor') - // eslint-disable-next-line new-cap - .then(module => new module.default()) - .catch(() => createFlash(ERROR)); - } -}); diff --git a/app/assets/javascripts/pages/projects/ci/lints/show/index.js b/app/assets/javascripts/pages/projects/ci/lints/show/index.js index 957801320c9..6e1cdf557b5 100644 --- a/app/assets/javascripts/pages/projects/ci/lints/show/index.js +++ b/app/assets/javascripts/pages/projects/ci/lints/show/index.js @@ -1,17 +1,3 @@ -import createFlash from '~/flash'; -import { __ } from '~/locale'; +import initCiLint from '~/ci_lint'; -const ERROR = __('An error occurred while rendering the linter'); - -document.addEventListener('DOMContentLoaded', () => { - if (gon?.features?.ciLintVue) { - import(/* webpackChunkName: 'ciLintIndex' */ '~/ci_lint/index') - .then(module => module.default()) - .catch(() => createFlash(ERROR)); - } else { - import(/* webpackChunkName: 'ciLintEditor' */ '../ci_lint_editor') - // eslint-disable-next-line new-cap - .then(module => new module.default()) - .catch(() => createFlash(ERROR)); - } -}); +initCiLint(); diff --git a/app/assets/javascripts/pages/projects/ci/pipeline_editor/show/index.js b/app/assets/javascripts/pages/projects/ci/pipeline_editor/show/index.js new file mode 100644 index 00000000000..67d32648ce8 --- /dev/null +++ b/app/assets/javascripts/pages/projects/ci/pipeline_editor/show/index.js @@ -0,0 +1,3 @@ +import { initPipelineEditor } from '~/pipeline_editor'; + +initPipelineEditor(); diff --git a/app/assets/javascripts/pages/projects/commit/show/index.js b/app/assets/javascripts/pages/projects/commit/show/index.js index 32fb35f97e3..e0bd49bf6ef 100644 --- a/app/assets/javascripts/pages/projects/commit/show/index.js +++ b/app/assets/javascripts/pages/projects/commit/show/index.js @@ -40,7 +40,7 @@ document.addEventListener('DOMContentLoaded', () => { new Diff(); }) .catch(() => { - flash(__('An error occurred while retrieving diff files')); + flash({ message: __('An error occurred while retrieving diff files') }); }); } else { new Diff(); diff --git a/app/assets/javascripts/pages/projects/error_tracking/details/index.js b/app/assets/javascripts/pages/projects/error_tracking/details/index.js index 25d1c744e1b..a750b3bac87 100644 --- a/app/assets/javascripts/pages/projects/error_tracking/details/index.js +++ b/app/assets/javascripts/pages/projects/error_tracking/details/index.js @@ -1,5 +1,3 @@ import ErrorTrackingDetails from '~/error_tracking/details'; -document.addEventListener('DOMContentLoaded', () => { - ErrorTrackingDetails(); -}); +ErrorTrackingDetails(); diff --git a/app/assets/javascripts/pages/projects/error_tracking/index/index.js b/app/assets/javascripts/pages/projects/error_tracking/index/index.js index ead81cd5d2d..fda0a35de9c 100644 --- a/app/assets/javascripts/pages/projects/error_tracking/index/index.js +++ b/app/assets/javascripts/pages/projects/error_tracking/index/index.js @@ -1,5 +1,3 @@ import ErrorTrackingList from '~/error_tracking/list'; -document.addEventListener('DOMContentLoaded', () => { - ErrorTrackingList(); -}); +ErrorTrackingList(); diff --git a/app/assets/javascripts/pages/projects/graphs/charts/index.js b/app/assets/javascripts/pages/projects/graphs/charts/index.js index 74abd1f67a5..6cf36463bda 100644 --- a/app/assets/javascripts/pages/projects/graphs/charts/index.js +++ b/app/assets/javascripts/pages/projects/graphs/charts/index.js @@ -5,6 +5,8 @@ import { __ } from '~/locale'; import CodeCoverage from '../components/code_coverage.vue'; import SeriesDataMixin from './series_data_mixin'; +const seriesDataToBarData = raw => Object.entries(raw).map(([name, data]) => ({ name, data })); + document.addEventListener('DOMContentLoaded', () => { waitForCSSLoaded(() => { const languagesContainer = document.getElementById('js-languages-chart'); @@ -41,13 +43,13 @@ document.addEventListener('DOMContentLoaded', () => { }, computed: { seriesData() { - return { full: this.chartData.map(d => [d.label, d.value]) }; + return [{ name: 'full', data: this.chartData.map(d => [d.label, d.value]) }]; }, }, render(h) { return h(GlColumnChart, { props: { - data: this.seriesData, + bars: this.seriesData, xAxisTitle: __('Used programming language'), yAxisTitle: __('Percentage'), xAxisType: 'category', @@ -86,7 +88,7 @@ document.addEventListener('DOMContentLoaded', () => { render(h) { return h(GlColumnChart, { props: { - data: this.seriesData, + bars: seriesDataToBarData(this.seriesData), xAxisTitle: __('Day of month'), yAxisTitle: __('No. of commits'), xAxisType: 'category', @@ -113,13 +115,13 @@ document.addEventListener('DOMContentLoaded', () => { acc.push([key, weekDays[key]]); return acc; }, []); - return { full: data }; + return [{ name: 'full', data }]; }, }, render(h) { return h(GlColumnChart, { props: { - data: this.seriesData, + bars: this.seriesData, xAxisTitle: __('Weekday'), yAxisTitle: __('No. of commits'), xAxisType: 'category', @@ -143,7 +145,7 @@ document.addEventListener('DOMContentLoaded', () => { render(h) { return h(GlColumnChart, { props: { - data: this.seriesData, + bars: seriesDataToBarData(this.seriesData), xAxisTitle: __('Hour (UTC)'), yAxisTitle: __('No. of commits'), xAxisType: 'category', diff --git a/app/assets/javascripts/pages/projects/graphs/components/code_coverage.vue b/app/assets/javascripts/pages/projects/graphs/components/code_coverage.vue index a9079f91f50..6dd50958fa4 100644 --- a/app/assets/javascripts/pages/projects/graphs/components/code_coverage.vue +++ b/app/assets/javascripts/pages/projects/graphs/components/code_coverage.vue @@ -153,10 +153,10 @@ export default { :option="chartOptions" :format-tooltip-text="formatTooltipText" > - <template v-if="canShowData" #tooltipTitle> + <template v-if="canShowData" #tooltip-title> {{ tooltipTitle }} </template> - <template v-if="canShowData" #tooltipContent> + <template v-if="canShowData" #tooltip-content> <gl-sprintf :message="__('Code Coverage: %{coveragePercentage}%{percentSymbol}')"> <template #coveragePercentage> {{ coveragePercentage }} diff --git a/app/assets/javascripts/pages/projects/incidents/index/index.js b/app/assets/javascripts/pages/projects/incidents/index/index.js index c37ae862a85..bbae605b31f 100644 --- a/app/assets/javascripts/pages/projects/incidents/index/index.js +++ b/app/assets/javascripts/pages/projects/incidents/index/index.js @@ -1,5 +1,3 @@ import IncidentsList from '~/incidents/list'; -document.addEventListener('DOMContentLoaded', () => { - IncidentsList(); -}); +IncidentsList(); diff --git a/app/assets/javascripts/pages/projects/incidents/show/index.js b/app/assets/javascripts/pages/projects/incidents/show/index.js index 3324cfc0335..5b3f03cd57e 100644 --- a/app/assets/javascripts/pages/projects/incidents/show/index.js +++ b/app/assets/javascripts/pages/projects/incidents/show/index.js @@ -2,10 +2,8 @@ import initSidebarBundle from '~/sidebar/sidebar_bundle'; import initRelatedIssues from '~/related_issues'; import initShow from '../../issues/show'; -document.addEventListener('DOMContentLoaded', () => { - initShow(); - if (!gon.features?.vueIssuableSidebar) { - initSidebarBundle(); - } - initRelatedIssues(); -}); +initShow(); +if (!gon.features?.vueIssuableSidebar) { + initSidebarBundle(); +} +initRelatedIssues(); diff --git a/app/assets/javascripts/pages/projects/integrations/jira/issues/index/index.js b/app/assets/javascripts/pages/projects/integrations/jira/issues/index/index.js deleted file mode 100644 index 534614349bf..00000000000 --- a/app/assets/javascripts/pages/projects/integrations/jira/issues/index/index.js +++ /dev/null @@ -1,5 +0,0 @@ -import initIssuablesList from '~/issues_list'; - -document.addEventListener('DOMContentLoaded', () => { - initIssuablesList(); -}); diff --git a/app/assets/javascripts/pages/projects/issues/show.js b/app/assets/javascripts/pages/projects/issues/show.js index a58b5d3f37c..4b15e435f60 100644 --- a/app/assets/javascripts/pages/projects/issues/show.js +++ b/app/assets/javascripts/pages/projects/issues/show.js @@ -5,7 +5,7 @@ import ShortcutsIssuable from '~/behaviors/shortcuts/shortcuts_issuable'; import ZenMode from '~/zen_mode'; import '~/notes/index'; import { store } from '~/notes/stores'; -import initIssueApp from '~/issue_show/issue'; +import { initIssuableApp, initIssueHeaderActions } from '~/issue_show/issue'; import initIncidentApp from '~/issue_show/incident'; import initIssuableHeaderWarning from '~/vue_shared/components/issuable/init_issuable_header_warning'; import initSentryErrorStackTraceApp from '~/sentry_error_stack_trace'; @@ -24,13 +24,14 @@ export default function() { initIncidentApp(issuableData); break; case IssuableType.Issue: - initIssueApp(issuableData); + initIssuableApp(issuableData, store); break; default: break; } initIssuableHeaderWarning(store); + initIssueHeaderActions(store); initSentryErrorStackTraceApp(); initRelatedMergeRequestsApp(); diff --git a/app/assets/javascripts/pages/projects/labels/components/promote_label_modal.vue b/app/assets/javascripts/pages/projects/labels/components/promote_label_modal.vue index f58e4909a08..7b5e0f70b7b 100644 --- a/app/assets/javascripts/pages/projects/labels/components/promote_label_modal.vue +++ b/app/assets/javascripts/pages/projects/labels/components/promote_label_modal.vue @@ -1,15 +1,21 @@ <script> -import { GlSprintf } from '@gitlab/ui'; +import { GlSprintf, GlModal } from '@gitlab/ui'; import axios from '~/lib/utils/axios_utils'; import { deprecatedCreateFlash as createFlash } from '~/flash'; -import DeprecatedModal2 from '~/vue_shared/components/deprecated_modal_2.vue'; -import { s__, sprintf } from '~/locale'; +import { s__, __, sprintf } from '~/locale'; import { visitUrl } from '~/lib/utils/url_utility'; import eventHub from '../event_hub'; export default { + primaryProps: { + text: s__('Labels|Promote Label'), + attributes: [{ variant: 'warning' }, { category: 'primary' }], + }, + cancelProps: { + text: __('Cancel'), + }, components: { - GlModal: DeprecatedModal2, + GlModal, GlSprintf, }, props: { @@ -72,12 +78,12 @@ export default { </script> <template> <gl-modal - id="promote-label-modal" - :footer-primary-button-text="s__('Labels|Promote Label')" - footer-primary-button-variant="warning" - @submit="onSubmit" + modal-id="promote-label-modal" + :action-primary="$options.primaryProps" + :action-cancel="$options.cancelProps" + @primary="onSubmit" > - <div slot="title" class="modal-title-with-label"> + <div slot="modal-title" class="modal-title-with-label"> <gl-sprintf :message=" s__( diff --git a/app/assets/javascripts/pages/projects/labels/index/index.js b/app/assets/javascripts/pages/projects/labels/index/index.js index 36cf485f33d..ee129011f9a 100644 --- a/app/assets/javascripts/pages/projects/labels/index/index.js +++ b/app/assets/javascripts/pages/projects/labels/index/index.js @@ -27,71 +27,55 @@ const initLabelIndex = () => { eventHub.$once('promoteLabelModal.requestFinished', onRequestFinished); }; - const onDeleteButtonClick = event => { - const button = event.currentTarget; - const modalProps = { - labelTitle: button.dataset.labelTitle, - labelColor: button.dataset.labelColor, - labelTextColor: button.dataset.labelTextColor, - url: button.dataset.url, - groupName: button.dataset.groupName, - }; - eventHub.$once('promoteLabelModal.requestStarted', onRequestStarted); - eventHub.$emit('promoteLabelModal.props', modalProps); - }; - const promoteLabelButtons = document.querySelectorAll('.js-promote-project-label-button'); - promoteLabelButtons.forEach(button => { - button.addEventListener('click', onDeleteButtonClick); - }); - eventHub.$once('promoteLabelModal.mounted', () => { - promoteLabelButtons.forEach(button => { - button.removeAttribute('disabled'); - }); - }); + return new Vue({ + el: '#js-promote-label-modal', + data() { + return { + modalProps: { + labelTitle: '', + labelColor: '', + labelTextColor: '', + url: '', + groupName: '', + }, + }; + }, + mounted() { + eventHub.$on('promoteLabelModal.props', this.setModalProps); + eventHub.$emit('promoteLabelModal.mounted'); - const promoteLabelModal = document.getElementById('promote-label-modal'); - let promoteLabelModalComponent; + promoteLabelButtons.forEach(button => { + button.removeAttribute('disabled'); + button.addEventListener('click', () => { + this.$root.$emit('bv::show::modal', 'promote-label-modal'); + eventHub.$once('promoteLabelModal.requestStarted', onRequestStarted); - if (promoteLabelModal) { - promoteLabelModalComponent = new Vue({ - el: promoteLabelModal, - components: { - PromoteLabelModal, - }, - data() { - return { - modalProps: { - labelTitle: '', - labelColor: '', - labelTextColor: '', - url: '', - groupName: '', - }, - }; - }, - mounted() { - eventHub.$on('promoteLabelModal.props', this.setModalProps); - eventHub.$emit('promoteLabelModal.mounted'); - }, - beforeDestroy() { - eventHub.$off('promoteLabelModal.props', this.setModalProps); - }, - methods: { - setModalProps(modalProps) { - this.modalProps = modalProps; - }, - }, - render(createElement) { - return createElement('promote-label-modal', { - props: this.modalProps, + this.setModalProps({ + labelTitle: button.dataset.labelTitle, + labelColor: button.dataset.labelColor, + labelTextColor: button.dataset.labelTextColor, + url: button.dataset.url, + groupName: button.dataset.groupName, + }); }); + }); + }, + beforeDestroy() { + eventHub.$off('promoteLabelModal.props', this.setModalProps); + }, + methods: { + setModalProps(modalProps) { + this.modalProps = modalProps; }, - }); - } - - return promoteLabelModalComponent; + }, + render(createElement) { + return createElement(PromoteLabelModal, { + props: this.modalProps, + }); + }, + }); }; document.addEventListener('DOMContentLoaded', initLabelIndex); diff --git a/app/assets/javascripts/pages/projects/metrics_dashboard/index.js b/app/assets/javascripts/pages/projects/metrics_dashboard/index.js index d3028aec313..606439866ea 100644 --- a/app/assets/javascripts/pages/projects/metrics_dashboard/index.js +++ b/app/assets/javascripts/pages/projects/metrics_dashboard/index.js @@ -1,3 +1,3 @@ import monitoringApp from '~/monitoring/monitoring_app'; -document.addEventListener('DOMContentLoaded', monitoringApp); +monitoringApp(); diff --git a/app/assets/javascripts/pages/projects/pipeline_schedules/index/index.js b/app/assets/javascripts/pages/projects/pipeline_schedules/index/index.js index 6197dc8a9db..90d2df50d5a 100644 --- a/app/assets/javascripts/pages/projects/pipeline_schedules/index/index.js +++ b/app/assets/javascripts/pages/projects/pipeline_schedules/index/index.js @@ -1,16 +1,24 @@ import Vue from 'vue'; import PipelineSchedulesCallout from '../shared/components/pipeline_schedules_callout.vue'; -document.addEventListener( - 'DOMContentLoaded', - () => - new Vue({ - el: '#pipeline-schedules-callout', - components: { - 'pipeline-schedules-callout': PipelineSchedulesCallout, - }, - render(createElement) { - return createElement('pipeline-schedules-callout'); - }, - }), -); +document.addEventListener('DOMContentLoaded', () => { + const el = document.getElementById('pipeline-schedules-callout'); + + if (!el) { + return; + } + + const { docsUrl, illustrationUrl } = el.dataset; + + // eslint-disable-next-line no-new + new Vue({ + el, + render(createElement) { + return createElement(PipelineSchedulesCallout); + }, + provide: { + docsUrl, + illustrationUrl, + }, + }); +}); diff --git a/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/pipeline_schedules_callout.vue b/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/pipeline_schedules_callout.vue index a138a3a3425..8ee9d481466 100644 --- a/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/pipeline_schedules_callout.vue +++ b/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/pipeline_schedules_callout.vue @@ -1,7 +1,7 @@ <script> import Vue from 'vue'; import Cookies from 'js-cookie'; -import { GlIcon } from '@gitlab/ui'; +import { GlButton } from '@gitlab/ui'; import Translate from '../../../../../vue_shared/translate'; import { parseBoolean } from '~/lib/utils/common_utils'; @@ -12,12 +12,11 @@ const cookieKey = 'pipeline_schedules_callout_dismissed'; export default { name: 'PipelineSchedulesCallout', components: { - GlIcon, + GlButton, }, + inject: ['docsUrl', 'illustrationUrl'], data() { return { - docsUrl: document.getElementById('pipeline-schedules-callout').dataset.docsUrl, - imageUrl: document.getElementById('pipeline-schedules-callout').dataset.imageUrl, calloutDismissed: parseBoolean(Cookies.get(cookieKey)), }; }, @@ -31,12 +30,16 @@ export default { </script> <template> <div v-if="!calloutDismissed" class="pipeline-schedules-user-callout user-callout"> - <div class="bordered-box landing content-block"> - <button id="dismiss-callout-btn" class="btn btn-default close" @click="dismissCallout"> - <gl-icon name="close" aria-hidden="true" /> - </button> - <div class="svg-container"> - <img :src="imageUrl" /> + <div class="bordered-box landing content-block" data-testid="innerContent"> + <gl-button + category="tertiary" + icon="close" + :aria-label="__('Dismiss')" + class="gl-absolute gl-top-2 gl-right-2" + @click="dismissCallout" + /> + <div class="svg-content"> + <img :src="illustrationUrl" /> </div> <div class="user-callout-copy"> <h4>{{ __('Scheduling Pipelines') }}</h4> diff --git a/app/assets/javascripts/pages/projects/pipelines/show/index.js b/app/assets/javascripts/pages/projects/pipelines/show/index.js index 7a57e417b41..d3f46b7e025 100644 --- a/app/assets/javascripts/pages/projects/pipelines/show/index.js +++ b/app/assets/javascripts/pages/projects/pipelines/show/index.js @@ -1,7 +1,5 @@ import initPipelineDetails from '~/pipelines/pipeline_details_bundle'; import initPipelines from '../init_pipelines'; -document.addEventListener('DOMContentLoaded', () => { - initPipelines(); - initPipelineDetails(); -}); +initPipelines(); +initPipelineDetails(); diff --git a/app/assets/javascripts/pages/projects/project.js b/app/assets/javascripts/pages/projects/project.js index 2f27814a692..5317093c4cf 100644 --- a/app/assets/javascripts/pages/projects/project.js +++ b/app/assets/javascripts/pages/projects/project.js @@ -57,7 +57,7 @@ export default class Project { $('.project-refs-select').on('change', function() { return $(this) .parents('form') - .submit(); + .trigger('submit'); }); } @@ -156,11 +156,32 @@ export default class Project { }, clicked(options) { const { e } = options; - if (!shouldVisit) { - e.preventDefault(); + e.preventDefault(); + + // Since this page does not reload when changing directories in a repo + // the rendered links do not have the path to the current directory. + // This updates the path based on the current url and then opens + // the the url with the updated path parameter. + if (shouldVisit) { + const selectedUrl = new URL(e.target.href); + const loc = window.location.href; + + if (loc.includes('/-/')) { + const refs = this.fullData.Branches.concat(this.fullData.Tags); + const currentRef = refs.find(ref => loc.indexOf(ref) > -1); + if (currentRef) { + const targetPath = loc.split(currentRef)[1].slice(1); + selectedUrl.searchParams.set('path', targetPath); + } + } + + // Open in new window if "meta" key is pressed + if (e.metaKey) { + window.open(selectedUrl.href, '_blank'); + } else { + window.location.href = selectedUrl.href; + } } - /* The actual process is removed since `link.href` in `RenderRow` contains the full target. - * It makes the visitable link can be visited when opening on a new tab of browser */ }, }); }); diff --git a/app/assets/javascripts/pages/projects/settings/ci_cd/show/index.js b/app/assets/javascripts/pages/projects/settings/ci_cd/show/index.js index 40816420eef..5d4c1595342 100644 --- a/app/assets/javascripts/pages/projects/settings/ci_cd/show/index.js +++ b/app/assets/javascripts/pages/projects/settings/ci_cd/show/index.js @@ -1,48 +1,35 @@ import initSettingsPanels from '~/settings_panels'; import SecretValues from '~/behaviors/secret_values'; -import AjaxVariableList from '~/ci_variable_list/ajax_variable_list'; import registrySettingsApp from '~/registry/settings/registry_settings_bundle'; import initVariableList from '~/ci_variable_list'; import initDeployFreeze from '~/deploy_freeze'; import initSettingsPipelinesTriggers from '~/ci_settings_pipeline_triggers'; +import { initInstallRunner } from '~/pages/shared/mount_runner_instructions'; -document.addEventListener('DOMContentLoaded', () => { - // Initialize expandable settings panels - initSettingsPanels(); +// Initialize expandable settings panels +initSettingsPanels(); - const runnerToken = document.querySelector('.js-secret-runner-token'); - if (runnerToken) { - const runnerTokenSecretValue = new SecretValues({ - container: runnerToken, - }); - runnerTokenSecretValue.init(); - } - - if (gon.features.newVariablesUi) { - initVariableList(); - } else { - const variableListEl = document.querySelector('.js-ci-variable-list-section'); - // eslint-disable-next-line no-new - new AjaxVariableList({ - container: variableListEl, - saveButton: variableListEl.querySelector('.js-ci-variables-save-button'), - errorBox: variableListEl.querySelector('.js-ci-variable-error-box'), - saveEndpoint: variableListEl.dataset.saveEndpoint, - maskableRegex: variableListEl.dataset.maskableRegex, - }); - } - - // hide extra auto devops settings based checkbox state - const autoDevOpsExtraSettings = document.querySelector('.js-extra-settings'); - const instanceDefaultBadge = document.querySelector('.js-instance-default-badge'); - document.querySelector('.js-toggle-extra-settings').addEventListener('click', event => { - const { target } = event; - if (instanceDefaultBadge) instanceDefaultBadge.style.display = 'none'; - autoDevOpsExtraSettings.classList.toggle('hidden', !target.checked); +const runnerToken = document.querySelector('.js-secret-runner-token'); +if (runnerToken) { + const runnerTokenSecretValue = new SecretValues({ + container: runnerToken, }); + runnerTokenSecretValue.init(); +} - registrySettingsApp(); - initDeployFreeze(); +initVariableList(); - initSettingsPipelinesTriggers(); +// hide extra auto devops settings based checkbox state +const autoDevOpsExtraSettings = document.querySelector('.js-extra-settings'); +const instanceDefaultBadge = document.querySelector('.js-instance-default-badge'); +document.querySelector('.js-toggle-extra-settings').addEventListener('click', event => { + const { target } = event; + if (instanceDefaultBadge) instanceDefaultBadge.style.display = 'none'; + autoDevOpsExtraSettings.classList.toggle('hidden', !target.checked); }); + +registrySettingsApp(); +initDeployFreeze(); + +initSettingsPipelinesTriggers(); +initInstallRunner(); diff --git a/app/assets/javascripts/pages/projects/settings/integrations/show/index.js b/app/assets/javascripts/pages/projects/settings/integrations/show/index.js index f2cf2eb9b28..bf9ccdbf9a8 100644 --- a/app/assets/javascripts/pages/projects/settings/integrations/show/index.js +++ b/app/assets/javascripts/pages/projects/settings/integrations/show/index.js @@ -1,6 +1,4 @@ import PersistentUserCallout from '~/persistent_user_callout'; -document.addEventListener('DOMContentLoaded', () => { - const callout = document.querySelector('.js-webhooks-moved-alert'); - PersistentUserCallout.factory(callout); -}); +const callout = document.querySelector('.js-webhooks-moved-alert'); +PersistentUserCallout.factory(callout); diff --git a/app/assets/javascripts/pages/projects/settings/operations/show/index.js b/app/assets/javascripts/pages/projects/settings/operations/show/index.js index 1b9ec44ed4a..153ccffd472 100644 --- a/app/assets/javascripts/pages/projects/settings/operations/show/index.js +++ b/app/assets/javascripts/pages/projects/settings/operations/show/index.js @@ -5,13 +5,11 @@ import mountGrafanaIntegration from '~/grafana_integration'; import initSettingsPanels from '~/settings_panels'; import initIncidentsSettings from '~/incidents_settings'; -document.addEventListener('DOMContentLoaded', () => { - initIncidentsSettings(); - mountErrorTrackingForm(); - mountOperationSettings(); - mountGrafanaIntegration(); - if (!IS_EE) { - initSettingsPanels(); - } - mountAlertsSettings(document.querySelector('.js-alerts-settings')); -}); +initIncidentsSettings(); +mountErrorTrackingForm(); +mountOperationSettings(); +mountGrafanaIntegration(); +if (!IS_EE) { + initSettingsPanels(); +} +mountAlertsSettings(document.querySelector('.js-alerts-settings')); diff --git a/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue b/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue index bcf82e264d1..e50add3b0a4 100644 --- a/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue +++ b/app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue @@ -68,6 +68,11 @@ export default { required: false, default: false, }, + requirementsAvailable: { + type: Boolean, + required: false, + default: false, + }, visibilityHelpPath: { type: String, required: false, @@ -132,6 +137,7 @@ export default { snippetsAccessLevel: featureAccessLevel.EVERYONE, pagesAccessLevel: featureAccessLevel.EVERYONE, metricsDashboardAccessLevel: featureAccessLevel.PROJECT_MEMBERS, + requirementsAccessLevel: featureAccessLevel.EVERYONE, containerRegistryEnabled: true, lfsEnabled: true, requestAccessEnabled: true, @@ -234,6 +240,10 @@ export default { featureAccessLevel.PROJECT_MEMBERS, this.metricsDashboardAccessLevel, ); + this.requirementsAccessLevel = Math.min( + featureAccessLevel.PROJECT_MEMBERS, + this.requirementsAccessLevel, + ); if (this.pagesAccessLevel === featureAccessLevel.EVERYONE) { // When from Internal->Private narrow access for only members this.pagesAccessLevel = featureAccessLevel.PROJECT_MEMBERS; @@ -257,6 +267,9 @@ export default { this.pagesAccessLevel = featureAccessLevel.EVERYONE; if (this.metricsDashboardAccessLevel === featureAccessLevel.PROJECT_MEMBERS) this.metricsDashboardAccessLevel = featureAccessLevel.EVERYONE; + if (this.requirementsAccessLevel === featureAccessLevel.PROJECT_MEMBERS) + this.requirementsAccessLevel = featureAccessLevel.EVERYONE; + this.highlightChanges(); } }, @@ -482,6 +495,18 @@ export default { </project-setting-row> </div> <project-setting-row + v-if="requirementsAvailable" + ref="requirements-settings" + :label="s__('ProjectSettings|Requirements')" + :help-text="s__('ProjectSettings|Requirements management system for this project')" + > + <project-feature-setting + v-model="requirementsAccessLevel" + :options="featureAccessLevelOptions" + name="project[project_feature_attributes][requirements_access_level]" + /> + </project-setting-row> + <project-setting-row ref="wiki-settings" :label="s__('ProjectSettings|Wiki')" :help-text="s__('ProjectSettings|Pages for project documentation')" diff --git a/app/assets/javascripts/pages/projects/shared/permissions/mixins/settings_pannel_mixin.js b/app/assets/javascripts/pages/projects/shared/permissions/mixins/settings_pannel_mixin.js index f69ca6e27b3..ae0936417ad 100644 --- a/app/assets/javascripts/pages/projects/shared/permissions/mixins/settings_pannel_mixin.js +++ b/app/assets/javascripts/pages/projects/shared/permissions/mixins/settings_pannel_mixin.js @@ -2,6 +2,7 @@ export default { data() { return { packagesEnabled: false, + requirementsEnabled: false, }; }, watch: { diff --git a/app/assets/javascripts/pages/projects/show/index.js b/app/assets/javascripts/pages/projects/show/index.js index dd8141d34c7..413b2d01621 100644 --- a/app/assets/javascripts/pages/projects/show/index.js +++ b/app/assets/javascripts/pages/projects/show/index.js @@ -10,6 +10,8 @@ import leaveByUrl from '~/namespaces/leave_by_url'; import Star from '../../../star'; import notificationsDropdown from '../../../notifications_dropdown'; import { showLearnGitLabProjectPopover } from '~/onboarding_issues'; +import initInviteMembersTrigger from '~/invite_members/init_invite_members_trigger'; +import initInviteMembersModal from '~/invite_members/init_invite_members_modal'; initReadMore(); new Star(); // eslint-disable-line no-new @@ -42,3 +44,6 @@ showLearnGitLabProjectPopover(); notificationsDropdown(); new ShortcutsNavigation(); // eslint-disable-line no-new + +initInviteMembersTrigger(); +initInviteMembersModal(); diff --git a/app/assets/javascripts/pages/projects/terraform/index/index.js b/app/assets/javascripts/pages/projects/terraform/index/index.js new file mode 100644 index 00000000000..6f9f820f8e1 --- /dev/null +++ b/app/assets/javascripts/pages/projects/terraform/index/index.js @@ -0,0 +1,3 @@ +import loadTerraformVues from '~/terraform'; + +loadTerraformVues(); diff --git a/app/assets/javascripts/pages/search/show/highlight_blob_search_result.js b/app/assets/javascripts/pages/search/show/highlight_blob_search_result.js deleted file mode 100644 index e17c87735b4..00000000000 --- a/app/assets/javascripts/pages/search/show/highlight_blob_search_result.js +++ /dev/null @@ -1,15 +0,0 @@ -export default () => { - const highlightLineClass = 'hll'; - const contentBody = document.getElementById('content-body'); - const searchTerm = contentBody.querySelector('.js-search-input').value.toLowerCase(); - const blobs = contentBody.querySelectorAll('.blob-result'); - - blobs.forEach(blob => { - const lines = blob.querySelectorAll('.line'); - lines.forEach(line => { - if (line.textContent.toLowerCase().includes(searchTerm)) { - line.classList.add(highlightLineClass); - } - }); - }); -}; diff --git a/app/assets/javascripts/pages/search/show/index.js b/app/assets/javascripts/pages/search/show/index.js index 721219874cf..88f2f30aad9 100644 --- a/app/assets/javascripts/pages/search/show/index.js +++ b/app/assets/javascripts/pages/search/show/index.js @@ -1,7 +1,7 @@ import Search from './search'; -import initSearchApp from '~/search'; +import { initSearchApp } from '~/search'; document.addEventListener('DOMContentLoaded', () => { initSearchApp(); - return new Search(); + return new Search(); // Deprecated Dropdown (Projects) }); diff --git a/app/assets/javascripts/pages/search/show/search.js b/app/assets/javascripts/pages/search/show/search.js index 2cd333f26e1..03675f1ce66 100644 --- a/app/assets/javascripts/pages/search/show/search.js +++ b/app/assets/javascripts/pages/search/show/search.js @@ -1,52 +1,26 @@ import $ from 'jquery'; +import setHighlightClass from 'ee_else_ce/search/highlight_blob_search_result'; import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown'; import { deprecatedCreateFlash as Flash } from '~/flash'; import Api from '~/api'; import { __ } from '~/locale'; import Project from '~/pages/projects/project'; -import { visitUrl } from '~/lib/utils/url_utility'; +import { visitUrl, queryToObject } from '~/lib/utils/url_utility'; import refreshCounts from './refresh_counts'; -import setHighlightClass from './highlight_blob_search_result'; export default class Search { constructor() { - setHighlightClass(); - const $groupDropdown = $('.js-search-group-dropdown'); + setHighlightClass(); // Code Highlighting const $projectDropdown = $('.js-search-project-dropdown'); this.searchInput = '.js-search-input'; this.searchClear = '.js-search-clear'; - this.groupId = $groupDropdown.data('groupId'); + const query = queryToObject(window.location.search); + this.groupId = query?.group_id; this.eventListeners(); refreshCounts(); - initDeprecatedJQueryDropdown($groupDropdown, { - selectable: true, - filterable: true, - filterRemote: true, - fieldName: 'group_id', - search: { - fields: ['full_name'], - }, - data(term, callback) { - return Api.groups(term, {}, data => { - data.unshift({ - full_name: __('Any'), - }); - data.splice(1, 0, { type: 'divider' }); - return callback(data); - }); - }, - id(obj) { - return obj.id; - }, - text(obj) { - return obj.full_name; - }, - clicked: () => Search.submitSearch(), - }); - initDeprecatedJQueryDropdown($projectDropdown, { selectable: true, filterable: true, diff --git a/app/assets/javascripts/pages/shared/mount_runner_instructions.js b/app/assets/javascripts/pages/shared/mount_runner_instructions.js new file mode 100644 index 00000000000..b7662155339 --- /dev/null +++ b/app/assets/javascripts/pages/shared/mount_runner_instructions.js @@ -0,0 +1,32 @@ +import Vue from 'vue'; +import VueApollo from 'vue-apollo'; +import createDefaultClient from '~/lib/graphql'; +import InstallRunnerInstructions from '~/vue_shared/components/runner_instructions/runner_instructions.vue'; + +Vue.use(VueApollo); + +export function initInstallRunner(componentId = 'js-install-runner') { + const installRunnerEl = document.getElementById(componentId); + const { projectPath, groupPath } = installRunnerEl?.dataset; + + if (installRunnerEl) { + const defaultClient = createDefaultClient(); + + const apolloProvider = new VueApollo({ + defaultClient, + }); + + // eslint-disable-next-line no-new + new Vue({ + el: installRunnerEl, + apolloProvider, + provide: { + projectPath, + groupPath, + }, + render(createElement) { + return createElement(InstallRunnerInstructions); + }, + }); + } +} diff --git a/app/assets/javascripts/pages/shared/wikis/components/delete_wiki_modal.vue b/app/assets/javascripts/pages/shared/wikis/components/delete_wiki_modal.vue index 653aad3d2f5..3792dad376b 100644 --- a/app/assets/javascripts/pages/shared/wikis/components/delete_wiki_modal.vue +++ b/app/assets/javascripts/pages/shared/wikis/components/delete_wiki_modal.vue @@ -1,7 +1,7 @@ <script> import { GlButton, GlModal, GlModalDirective } from '@gitlab/ui'; import { escape } from 'lodash'; -import { s__, sprintf } from '~/locale'; +import { s__, __, sprintf } from '~/locale'; export default { components: { @@ -29,12 +29,6 @@ export default { }, }, computed: { - modalId() { - return 'delete-wiki-modal'; - }, - message() { - return s__('WikiPageConfirmDelete|Are you sure you want to delete this page?'); - }, title() { return sprintf( s__('WikiPageConfirmDelete|Delete page %{pageTitle}?'), @@ -44,6 +38,21 @@ export default { false, ); }, + primaryProps() { + return { + text: this.$options.i18n.deletePageText, + attributes: { + variant: 'danger', + 'data-qa-selector': 'confirm_deletion_button', + 'data-testid': 'confirm_deletion_button', + }, + }; + }, + cancelProps() { + return { + text: this.$options.i18n.cancelButtonText, + }; + }, }, methods: { onSubmit() { @@ -51,30 +60,36 @@ export default { this.$refs.form.submit(); }, }, + i18n: { + deletePageText: s__('WikiPageConfirmDelete|Delete page'), + modalBody: s__('WikiPageConfirmDelete|Are you sure you want to delete this page?'), + cancelButtonText: __('Cancel'), + }, + modal: { + modalId: 'delete-wiki-modal', + }, }; </script> <template> <div class="d-inline-block"> <gl-button - v-gl-modal="modalId" - category="primary" + v-gl-modal="$options.modal.modalId" + category="secondary" variant="danger" data-qa-selector="delete_button" > - {{ __('Delete') }} + {{ $options.i18n.deletePageText }} </gl-button> <gl-modal :title="title" - :action-primary="{ - text: s__('WikiPageConfirmDelete|Delete page'), - attributes: { variant: 'danger', 'data-qa-selector': 'confirm_deletion_button' }, - }" - :modal-id="modalId" - title-tag="h4" + :action-primary="primaryProps" + :action-cancel="cancelProps" + :modal-id="$options.modal.modalId" + size="sm" @ok="onSubmit" > - {{ message }} + {{ $options.i18n.modalBody }} <form ref="form" :action="deleteWikiUrl" method="post" class="js-requires-input"> <input ref="method" type="hidden" name="_method" value="delete" /> <input :value="csrfToken" type="hidden" name="authenticity_token" /> diff --git a/app/assets/javascripts/pages/shared/wikis/wikis.js b/app/assets/javascripts/pages/shared/wikis/wikis.js index ab948fd106f..fe9caba351e 100644 --- a/app/assets/javascripts/pages/shared/wikis/wikis.js +++ b/app/assets/javascripts/pages/shared/wikis/wikis.js @@ -1,6 +1,7 @@ import { GlBreakpointInstance as bp } from '@gitlab/ui/dist/utils'; import { s__, sprintf } from '~/locale'; import Tracking from '~/tracking'; +import showToast from '~/vue_shared/plugins/global_toast'; const MARKDOWN_LINK_TEXT = { markdown: '[Link Title](page-slug)', @@ -63,6 +64,7 @@ export default class Wikis { } Wikis.trackPageView(); + Wikis.showToasts(); } handleWikiTitleChange(e) { @@ -116,4 +118,9 @@ export default class Wikis { }, }); } + + static showToasts() { + const toasts = document.querySelectorAll('.js-toast-message'); + toasts.forEach(toast => showToast(toast.dataset.message)); + } } diff --git a/app/assets/javascripts/pages/users/activity_calendar.js b/app/assets/javascripts/pages/users/activity_calendar.js index eb0a5efe75c..54666af540e 100644 --- a/app/assets/javascripts/pages/users/activity_calendar.js +++ b/app/assets/javascripts/pages/users/activity_calendar.js @@ -125,9 +125,6 @@ export default class ActivityCalendar { this.renderMonths(); this.renderDayTitles(); this.renderKey(); - - // Init tooltips - $(`${container} .js-tooltip`).tooltip({ html: true }); } // Add extra padding for the last month label if it is also the last column @@ -191,7 +188,8 @@ export default class ActivityCalendar { stamp.count !== 0 ? this.color(Math.min(stamp.count, 40)) : '#ededed', ) .attr('title', stamp => formatTooltipText(stamp)) - .attr('class', 'user-contrib-cell js-tooltip') + .attr('class', 'user-contrib-cell has-tooltip') + .attr('data-html', true) .attr('data-container', 'body') .on('click', this.clickDay); } @@ -279,9 +277,10 @@ export default class ActivityCalendar { .attr('x', (color, i) => this.daySizeWithSpace * i) .attr('y', 0) .attr('fill', color => color) - .attr('class', 'js-tooltip') + .attr('class', 'has-tooltip') .attr('title', (color, i) => keyValues[i]) - .attr('data-container', 'body'); + .attr('data-container', 'body') + .attr('data-html', true); } initColor() { diff --git a/app/assets/javascripts/pages/users/index.js b/app/assets/javascripts/pages/users/index.js index cfc6dc61f9f..8adbc2a8168 100644 --- a/app/assets/javascripts/pages/users/index.js +++ b/app/assets/javascripts/pages/users/index.js @@ -4,11 +4,6 @@ import UserCallout from '~/user_callout'; import UserTabs from './user_tabs'; function initUserProfile(action) { - // place profile avatars to top - $('.profile-groups-avatars').tooltip({ - placement: 'top', - }); - // eslint-disable-next-line no-new new UserTabs({ parentEl: '.user-profile', action }); diff --git a/app/assets/javascripts/pages/users/user_tabs.js b/app/assets/javascripts/pages/users/user_tabs.js index 9d66c784750..2485853afc7 100644 --- a/app/assets/javascripts/pages/users/user_tabs.js +++ b/app/assets/javascripts/pages/users/user_tabs.js @@ -5,7 +5,6 @@ import Activities from '~/activities'; import { localTimeAgo } from '~/lib/utils/datetime_utility'; import AjaxCache from '~/lib/utils/ajax_cache'; import { __ } from '~/locale'; -import { deprecatedCreateFlash as flash } from '~/flash'; import ActivityCalendar from './activity_calendar'; import UserOverviewBlock from './user_overview_block'; @@ -63,9 +62,9 @@ import UserOverviewBlock from './user_overview_block'; */ const CALENDAR_TEMPLATE = ` - <div class="clearfix calendar"> + <div class="calendar"> <div class="js-contrib-calendar"></div> - <div class="calendar-hint bottom-right"></div> + <div class="calendar-hint"></div> </div> `; @@ -214,7 +213,17 @@ export default class UserTabs { AjaxCache.retrieve(calendarPath) .then(data => UserTabs.renderActivityCalendar(data, $calendarWrap)) - .catch(() => flash(__('There was an error loading users activity calendar.'))); + .catch(() => { + const cWrap = $calendarWrap[0]; + cWrap.querySelector('.spinner').classList.add('invisible'); + cWrap.querySelector('.user-calendar-error').classList.remove('invisible'); + cWrap.querySelector('.user-calendar-error .js-retry-load').addEventListener('click', e => { + e.preventDefault(); + cWrap.querySelector('.user-calendar-error').classList.add('invisible'); + cWrap.querySelector('.spinner').classList.remove('invisible'); + this.loadActivityCalendar(); + }); + }); } static renderActivityCalendar(data, $calendarWrap) { |