summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/pages
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets/javascripts/pages')
-rw-r--r--app/assets/javascripts/pages/admin/abuse_reports/abuse_reports.js12
-rw-r--r--app/assets/javascripts/pages/admin/abuse_reports/index.js2
-rw-r--r--app/assets/javascripts/pages/admin/admin.js4
-rw-r--r--app/assets/javascripts/pages/admin/broadcast_messages/broadcast_message.js6
-rw-r--r--app/assets/javascripts/pages/admin/broadcast_messages/index.js2
-rw-r--r--app/assets/javascripts/pages/admin/cohorts/index.js2
-rw-r--r--app/assets/javascripts/pages/admin/conversational_development_index/show/index.js4
-rw-r--r--app/assets/javascripts/pages/admin/groups/edit/index.js4
-rw-r--r--app/assets/javascripts/pages/admin/groups/new/index.js4
-rw-r--r--app/assets/javascripts/pages/admin/groups/show/index.js2
-rw-r--r--app/assets/javascripts/pages/admin/impersonation_tokens/index.js4
-rw-r--r--app/assets/javascripts/pages/admin/index.js2
-rw-r--r--app/assets/javascripts/pages/admin/jobs/index/components/stop_jobs_modal.vue26
-rw-r--r--app/assets/javascripts/pages/admin/jobs/index/index.js43
-rw-r--r--app/assets/javascripts/pages/admin/labels/edit/index.js2
-rw-r--r--app/assets/javascripts/pages/admin/labels/new/index.js2
-rw-r--r--app/assets/javascripts/pages/admin/projects/index.js4
-rw-r--r--app/assets/javascripts/pages/admin/projects/index/index.js4
-rw-r--r--app/assets/javascripts/pages/admin/users/components/delete_user_modal.vue (renamed from app/assets/javascripts/pages/admin/users/shared/components/delete_user_modal.vue)0
-rw-r--r--app/assets/javascripts/pages/admin/users/index.js (renamed from app/assets/javascripts/pages/admin/users/shared/index.js)4
-rw-r--r--app/assets/javascripts/pages/ci/lints/ci_lint_editor.js7
-rw-r--r--app/assets/javascripts/pages/ci/lints/create/index.js3
-rw-r--r--app/assets/javascripts/pages/ci/lints/index.js3
-rw-r--r--app/assets/javascripts/pages/ci/lints/show/index.js3
-rw-r--r--app/assets/javascripts/pages/dashboard/activity/index.js2
-rw-r--r--app/assets/javascripts/pages/dashboard/groups/index/index.js6
-rw-r--r--app/assets/javascripts/pages/dashboard/issues/index.js4
-rw-r--r--app/assets/javascripts/pages/dashboard/merge_requests/index.js4
-rw-r--r--app/assets/javascripts/pages/dashboard/milestones/show/index.js6
-rw-r--r--app/assets/javascripts/pages/dashboard/projects/index.js2
-rw-r--r--app/assets/javascripts/pages/dashboard/todos/index/index.js2
-rw-r--r--app/assets/javascripts/pages/explore/groups/index.js4
-rw-r--r--app/assets/javascripts/pages/explore/projects/index.js2
-rw-r--r--app/assets/javascripts/pages/groups/activity/index.js2
-rw-r--r--app/assets/javascripts/pages/groups/edit/index.js4
-rw-r--r--app/assets/javascripts/pages/groups/group_members/index/index.js4
-rw-r--r--app/assets/javascripts/pages/groups/issues/index.js4
-rw-r--r--app/assets/javascripts/pages/groups/labels/edit/index.js2
-rw-r--r--app/assets/javascripts/pages/groups/labels/index/index.js2
-rw-r--r--app/assets/javascripts/pages/groups/labels/new/index.js2
-rw-r--r--app/assets/javascripts/pages/groups/merge_requests/index.js4
-rw-r--r--app/assets/javascripts/pages/groups/milestones/edit/index.js2
-rw-r--r--app/assets/javascripts/pages/groups/milestones/new/index.js2
-rw-r--r--app/assets/javascripts/pages/groups/milestones/show/index.js2
-rw-r--r--app/assets/javascripts/pages/groups/new/index.js4
-rw-r--r--app/assets/javascripts/pages/groups/settings/ci_cd/show/index.js4
-rw-r--r--app/assets/javascripts/pages/groups/show/index.js2
-rw-r--r--app/assets/javascripts/pages/help/index.js3
-rw-r--r--app/assets/javascripts/pages/help/index/index.js7
-rw-r--r--app/assets/javascripts/pages/help/show/index.js3
-rw-r--r--app/assets/javascripts/pages/help/ui/index.js3
-rw-r--r--app/assets/javascripts/pages/import/fogbugz/new_user_map/index.js4
-rw-r--r--app/assets/javascripts/pages/import/gitlab_projects/new/index.js3
-rw-r--r--app/assets/javascripts/pages/milestones/shared/init_milestones_show.js2
-rw-r--r--app/assets/javascripts/pages/omniauth_callbacks/index.js4
-rw-r--r--app/assets/javascripts/pages/profiles/accounts/show/index.js3
-rw-r--r--app/assets/javascripts/pages/profiles/index/index.js4
-rw-r--r--app/assets/javascripts/pages/profiles/personal_access_tokens/index.js4
-rw-r--r--app/assets/javascripts/pages/projects/activity/index.js4
-rw-r--r--app/assets/javascripts/pages/projects/artifacts/browse/index.js4
-rw-r--r--app/assets/javascripts/pages/projects/artifacts/file/index.js4
-rw-r--r--app/assets/javascripts/pages/projects/blame/show/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/blob/edit/index.js3
-rw-r--r--app/assets/javascripts/pages/projects/blob/new/index.js3
-rw-r--r--app/assets/javascripts/pages/projects/blob/show/index.js4
-rw-r--r--app/assets/javascripts/pages/projects/boards/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/branches/index/index.js4
-rw-r--r--app/assets/javascripts/pages/projects/branches/new/index.js4
-rw-r--r--app/assets/javascripts/pages/projects/clusters/destroy/index.js5
-rw-r--r--app/assets/javascripts/pages/projects/clusters/index/index.js4
-rw-r--r--app/assets/javascripts/pages/projects/clusters/show/index.js4
-rw-r--r--app/assets/javascripts/pages/projects/clusters/update/index.js5
-rw-r--r--app/assets/javascripts/pages/projects/commit/pipelines/index.js6
-rw-r--r--app/assets/javascripts/pages/projects/commit/show/index.js4
-rw-r--r--app/assets/javascripts/pages/projects/commits/show/index.js6
-rw-r--r--app/assets/javascripts/pages/projects/compare/index.js4
-rw-r--r--app/assets/javascripts/pages/projects/compare/show/index.js4
-rw-r--r--app/assets/javascripts/pages/projects/edit/index.js4
-rw-r--r--app/assets/javascripts/pages/projects/environments/folder/index.js3
-rw-r--r--app/assets/javascripts/pages/projects/environments/metrics/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/find_file/show/index.js4
-rw-r--r--app/assets/javascripts/pages/projects/forks/new/index.js4
-rw-r--r--app/assets/javascripts/pages/projects/graphs/charts/index.js61
-rw-r--r--app/assets/javascripts/pages/projects/graphs/show/index.js23
-rw-r--r--app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors.js125
-rw-r--r--app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors_graph.js294
-rw-r--r--app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors_util.js138
-rw-r--r--app/assets/javascripts/pages/projects/imports/show/index.js4
-rw-r--r--app/assets/javascripts/pages/projects/index.js4
-rw-r--r--app/assets/javascripts/pages/projects/init_blob.js3
-rw-r--r--app/assets/javascripts/pages/projects/issues/edit/index.js4
-rw-r--r--app/assets/javascripts/pages/projects/issues/new/index.js4
-rw-r--r--app/assets/javascripts/pages/projects/issues/show/index.js10
-rw-r--r--app/assets/javascripts/pages/projects/jobs/show/index.js3
-rw-r--r--app/assets/javascripts/pages/projects/labels/edit/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/labels/index/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/labels/new/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/merge_requests/creations/index.js (renamed from app/assets/javascripts/pages/projects/merge_requests/creations/diffs/index.js)2
-rw-r--r--app/assets/javascripts/pages/projects/merge_requests/creations/new/index.js6
-rw-r--r--app/assets/javascripts/pages/projects/merge_requests/edit/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/merge_requests/show/index.js30
-rw-r--r--app/assets/javascripts/pages/projects/milestones/edit/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/milestones/index/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/milestones/new/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/milestones/show/index.js4
-rw-r--r--app/assets/javascripts/pages/projects/new/index.js4
-rw-r--r--app/assets/javascripts/pages/projects/pipeline_schedules/create/index.js3
-rw-r--r--app/assets/javascripts/pages/projects/pipeline_schedules/edit/index.js3
-rw-r--r--app/assets/javascripts/pages/projects/pipeline_schedules/index/index.js12
-rw-r--r--app/assets/javascripts/pages/projects/pipeline_schedules/new/index.js3
-rw-r--r--app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/interval_pattern_input.vue160
-rw-r--r--app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/pipeline_schedules_callout.vue67
-rw-r--r--app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/target_branch_dropdown.js52
-rw-r--r--app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/timezone_dropdown.js66
-rw-r--r--app/assets/javascripts/pages/projects/pipeline_schedules/shared/icons/intro_illustration.svg1
-rw-r--r--app/assets/javascripts/pages/projects/pipeline_schedules/shared/init_form.js49
-rw-r--r--app/assets/javascripts/pages/projects/pipeline_schedules/update/index.js3
-rw-r--r--app/assets/javascripts/pages/projects/pipelines/builds/index.js17
-rw-r--r--app/assets/javascripts/pages/projects/pipelines/charts/index.js56
-rw-r--r--app/assets/javascripts/pages/projects/pipelines/failures/index.js3
-rw-r--r--app/assets/javascripts/pages/projects/pipelines/init_pipelines.js16
-rw-r--r--app/assets/javascripts/pages/projects/pipelines/new/index.js6
-rw-r--r--app/assets/javascripts/pages/projects/pipelines/show/index.js3
-rw-r--r--app/assets/javascripts/pages/projects/project.js8
-rw-r--r--app/assets/javascripts/pages/projects/project_members/index.js4
-rw-r--r--app/assets/javascripts/pages/projects/releases/edit/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/services/edit/index.js13
-rw-r--r--app/assets/javascripts/pages/projects/settings/ci_cd/show/index.js4
-rw-r--r--app/assets/javascripts/pages/projects/settings/repository/show/index.js6
-rw-r--r--app/assets/javascripts/pages/projects/snippets/edit/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/snippets/new/index.js2
-rw-r--r--app/assets/javascripts/pages/projects/snippets/show/index.js4
-rw-r--r--app/assets/javascripts/pages/projects/tags/new/index.js4
-rw-r--r--app/assets/javascripts/pages/projects/tree/show/index.js9
-rw-r--r--app/assets/javascripts/pages/projects/wikis/index.js4
-rw-r--r--app/assets/javascripts/pages/search/init_filtered_search.js6
-rw-r--r--app/assets/javascripts/pages/search/show/index.js2
-rw-r--r--app/assets/javascripts/pages/search/show/search.js6
-rw-r--r--app/assets/javascripts/pages/sessions/index.js4
-rw-r--r--app/assets/javascripts/pages/snippets/edit/index.js2
-rw-r--r--app/assets/javascripts/pages/snippets/new/index.js2
-rw-r--r--app/assets/javascripts/pages/snippets/show/index.js11
-rw-r--r--app/assets/javascripts/pages/users/activity_calendar.js242
-rw-r--r--app/assets/javascripts/pages/users/index.js27
-rw-r--r--app/assets/javascripts/pages/users/show/index.js3
-rw-r--r--app/assets/javascripts/pages/users/user_tabs.js199
146 files changed, 1931 insertions, 242 deletions
diff --git a/app/assets/javascripts/pages/admin/abuse_reports/abuse_reports.js b/app/assets/javascripts/pages/admin/abuse_reports/abuse_reports.js
index d87e6304a24..66702ec4ca0 100644
--- a/app/assets/javascripts/pages/admin/abuse_reports/abuse_reports.js
+++ b/app/assets/javascripts/pages/admin/abuse_reports/abuse_reports.js
@@ -15,21 +15,21 @@ export default class AbuseReports {
const $messageCellElement = $(this);
const reportMessage = $messageCellElement.text();
if (reportMessage.length > MAX_MESSAGE_LENGTH) {
- $messageCellElement.data('original-message', reportMessage);
- $messageCellElement.data('message-truncated', 'true');
+ $messageCellElement.data('originalMessage', reportMessage);
+ $messageCellElement.data('messageTruncated', 'true');
$messageCellElement.text(truncate(reportMessage, MAX_MESSAGE_LENGTH));
}
}
toggleMessageTruncation() {
const $messageCellElement = $(this);
- const originalMessage = $messageCellElement.data('original-message');
+ const originalMessage = $messageCellElement.data('originalMessage');
if (!originalMessage) return;
- if ($messageCellElement.data('message-truncated') === 'true') {
- $messageCellElement.data('message-truncated', 'false');
+ if ($messageCellElement.data('messageTruncated') === 'true') {
+ $messageCellElement.data('messageTruncated', 'false');
$messageCellElement.text(originalMessage);
} else {
- $messageCellElement.data('message-truncated', 'true');
+ $messageCellElement.data('messageTruncated', 'true');
$messageCellElement.text(`${originalMessage.substr(0, (MAX_MESSAGE_LENGTH - 3))}...`);
}
}
diff --git a/app/assets/javascripts/pages/admin/abuse_reports/index.js b/app/assets/javascripts/pages/admin/abuse_reports/index.js
index c0b6e8d4095..d76b1f174fc 100644
--- a/app/assets/javascripts/pages/admin/abuse_reports/index.js
+++ b/app/assets/javascripts/pages/admin/abuse_reports/index.js
@@ -1,3 +1,3 @@
import AbuseReports from './abuse_reports';
-export default () => new AbuseReports();
+document.addEventListener('DOMContentLoaded', () => new AbuseReports());
diff --git a/app/assets/javascripts/pages/admin/admin.js b/app/assets/javascripts/pages/admin/admin.js
index 135c15c346b..45e05f111a7 100644
--- a/app/assets/javascripts/pages/admin/admin.js
+++ b/app/assets/javascripts/pages/admin/admin.js
@@ -16,9 +16,9 @@ export default function adminInit() {
$('input#user_force_random_password').on('change', function randomPasswordClick() {
const $elems = $('#user_password, #user_password_confirmation');
if ($(this).attr('checked')) {
- $elems.val('').attr('disabled', true);
+ $elems.val('').prop('disabled', true);
} else {
- $elems.removeAttr('disabled');
+ $elems.prop('disabled', false);
}
});
diff --git a/app/assets/javascripts/pages/admin/broadcast_messages/broadcast_message.js b/app/assets/javascripts/pages/admin/broadcast_messages/broadcast_message.js
index 885acfac6d0..f92450cbaa7 100644
--- a/app/assets/javascripts/pages/admin/broadcast_messages/broadcast_message.js
+++ b/app/assets/javascripts/pages/admin/broadcast_messages/broadcast_message.js
@@ -3,7 +3,7 @@ import axios from '~/lib/utils/axios_utils';
import flash from '~/flash';
import { __ } from '~/locale';
-export default function initBroadcastMessagesForm() {
+export default () => {
$('input#broadcast_message_color').on('input', function onMessageColorInput() {
const previewColor = $(this).val();
$('div.broadcast-message-preview').css('background-color', previewColor);
@@ -14,7 +14,7 @@ export default function initBroadcastMessagesForm() {
$('div.broadcast-message-preview').css('color', previewColor);
});
- const previewPath = $('textarea#broadcast_message_message').data('preview-path');
+ const previewPath = $('textarea#broadcast_message_message').data('previewPath');
$('textarea#broadcast_message_message').on('input', _.debounce(function onMessageInput() {
const message = $(this).val();
@@ -32,4 +32,4 @@ export default function initBroadcastMessagesForm() {
.catch(() => flash(__('An error occurred while rendering preview broadcast message')));
}
}, 250));
-}
+};
diff --git a/app/assets/javascripts/pages/admin/broadcast_messages/index.js b/app/assets/javascripts/pages/admin/broadcast_messages/index.js
index b548c48282a..d6cc6a850eb 100644
--- a/app/assets/javascripts/pages/admin/broadcast_messages/index.js
+++ b/app/assets/javascripts/pages/admin/broadcast_messages/index.js
@@ -1,3 +1,3 @@
import initBroadcastMessagesForm from './broadcast_message';
-export default () => initBroadcastMessagesForm();
+document.addEventListener('DOMContentLoaded', initBroadcastMessagesForm);
diff --git a/app/assets/javascripts/pages/admin/cohorts/index.js b/app/assets/javascripts/pages/admin/cohorts/index.js
index 42ef9d38ef7..2d5020dbef4 100644
--- a/app/assets/javascripts/pages/admin/cohorts/index.js
+++ b/app/assets/javascripts/pages/admin/cohorts/index.js
@@ -1,3 +1,3 @@
import initUsagePing from './usage_ping';
-export default () => initUsagePing();
+document.addEventListener('DOMContentLoaded', initUsagePing);
diff --git a/app/assets/javascripts/pages/admin/conversational_development_index/show/index.js b/app/assets/javascripts/pages/admin/conversational_development_index/show/index.js
index 6e66ef69fe1..c1056537f90 100644
--- a/app/assets/javascripts/pages/admin/conversational_development_index/show/index.js
+++ b/app/assets/javascripts/pages/admin/conversational_development_index/show/index.js
@@ -1,3 +1,3 @@
-import UserCallout from '../../../../user_callout';
+import UserCallout from '~/user_callout';
-export default () => new UserCallout();
+document.addEventListener('DOMContentLoaded', () => new UserCallout());
diff --git a/app/assets/javascripts/pages/admin/groups/edit/index.js b/app/assets/javascripts/pages/admin/groups/edit/index.js
index ff9ef8d2449..d3d125a1859 100644
--- a/app/assets/javascripts/pages/admin/groups/edit/index.js
+++ b/app/assets/javascripts/pages/admin/groups/edit/index.js
@@ -1,3 +1,3 @@
-import groupAvatar from '../../../../group_avatar';
+import groupAvatar from '~/group_avatar';
-export default () => groupAvatar();
+document.addEventListener('DOMContentLoaded', groupAvatar);
diff --git a/app/assets/javascripts/pages/admin/groups/new/index.js b/app/assets/javascripts/pages/admin/groups/new/index.js
index fb5c46e4729..21f1ce222ac 100644
--- a/app/assets/javascripts/pages/admin/groups/new/index.js
+++ b/app/assets/javascripts/pages/admin/groups/new/index.js
@@ -2,8 +2,8 @@ import BindInOut from '../../../../behaviors/bind_in_out';
import Group from '../../../../group';
import groupAvatar from '../../../../group_avatar';
-export default () => {
+document.addEventListener('DOMContentLoaded', () => {
BindInOut.initAll();
new Group(); // eslint-disable-line no-new
groupAvatar();
-};
+});
diff --git a/app/assets/javascripts/pages/admin/groups/show/index.js b/app/assets/javascripts/pages/admin/groups/show/index.js
index 5defea104d4..b0cdad627a6 100644
--- a/app/assets/javascripts/pages/admin/groups/show/index.js
+++ b/app/assets/javascripts/pages/admin/groups/show/index.js
@@ -1,3 +1,3 @@
import UsersSelect from '../../../../users_select';
-export default () => new UsersSelect();
+document.addEventListener('DOMContentLoaded', () => new UsersSelect());
diff --git a/app/assets/javascripts/pages/admin/impersonation_tokens/index.js b/app/assets/javascripts/pages/admin/impersonation_tokens/index.js
index 030328a1363..78a5c4c27be 100644
--- a/app/assets/javascripts/pages/admin/impersonation_tokens/index.js
+++ b/app/assets/javascripts/pages/admin/impersonation_tokens/index.js
@@ -1,3 +1,3 @@
-import DueDateSelectors from '../../../due_date_select';
+import DueDateSelectors from '~/due_date_select';
-export default () => new DueDateSelectors();
+document.addEventListener('DOMContentLoaded', () => new DueDateSelectors());
diff --git a/app/assets/javascripts/pages/admin/index.js b/app/assets/javascripts/pages/admin/index.js
index 8b843037d85..e50b61f09e2 100644
--- a/app/assets/javascripts/pages/admin/index.js
+++ b/app/assets/javascripts/pages/admin/index.js
@@ -1,3 +1,3 @@
import initAdmin from './admin';
-export default () => initAdmin();
+document.addEventListener('DOMContentLoaded', initAdmin);
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 555725cbe12..ba1d8e4d8db 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 axios from '~/lib/utils/axios_utils';
- import Flash from '~/flash';
- import modal from '~/vue_shared/components/modal.vue';
- import { s__ } from '~/locale';
+ import createFlash from '~/flash';
+ import GlModal from '~/vue_shared/components/gl_modal.vue';
import { redirectTo } from '~/lib/utils/url_utility';
+ import { s__ } from '~/locale';
export default {
components: {
- modal,
+ GlModal,
},
props: {
url: {
@@ -17,7 +17,7 @@
},
computed: {
text() {
- return s__('AdminArea|You’re about to stop all jobs. This will halt all current jobs that are running.');
+ return s__('AdminArea|You’re about to stop all jobs.This will halt all current jobs that are running.');
},
},
methods: {
@@ -28,7 +28,7 @@
redirectTo(response.request.responseURL);
})
.catch((error) => {
- Flash(s__('AdminArea|Stopping jobs failed'));
+ createFlash(s__('AdminArea|Stopping jobs failed'));
throw error;
});
},
@@ -37,11 +37,13 @@
</script>
<template>
- <modal
+ <gl-modal
id="stop-jobs-modal"
- :title="s__('AdminArea|Stop all jobs?')"
- :text="text"
- kind="danger"
- :primary-button-label="s__('AdminArea|Stop jobs')"
- @submit="onSubmit" />
+ :header-title-text="s__('AdminArea|Stop all jobs?')"
+ footer-primary-button-variant="danger"
+ :footer-primary-button-text="s__('AdminArea|Stop jobs')"
+ @submit="onSubmit"
+ >
+ {{ 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 0e004bd9174..5a4f8c6e745 100644
--- a/app/assets/javascripts/pages/admin/jobs/index/index.js
+++ b/app/assets/javascripts/pages/admin/jobs/index/index.js
@@ -1,29 +1,28 @@
import Vue from 'vue';
-
import Translate from '~/vue_shared/translate';
-
import stopJobsModal from './components/stop_jobs_modal.vue';
Vue.use(Translate);
-export default () => {
+document.addEventListener('DOMContentLoaded', () => {
const stopJobsButton = document.getElementById('stop-jobs-button');
-
- // eslint-disable-next-line no-new
- new Vue({
- el: '#stop-jobs-modal',
- components: {
- stopJobsModal,
- },
- mounted() {
- stopJobsButton.classList.remove('disabled');
- },
- render(createElement) {
- return createElement('stop-jobs-modal', {
- props: {
- url: stopJobsButton.dataset.url,
- },
- });
- },
- });
-};
+ if (stopJobsButton) {
+ // eslint-disable-next-line no-new
+ new Vue({
+ el: '#stop-jobs-modal',
+ components: {
+ stopJobsModal,
+ },
+ mounted() {
+ stopJobsButton.classList.remove('disabled');
+ },
+ render(createElement) {
+ return createElement('stop-jobs-modal', {
+ props: {
+ url: stopJobsButton.dataset.url,
+ },
+ });
+ },
+ });
+ }
+});
diff --git a/app/assets/javascripts/pages/admin/labels/edit/index.js b/app/assets/javascripts/pages/admin/labels/edit/index.js
index d7ec6e47f67..5de1d4d6344 100644
--- a/app/assets/javascripts/pages/admin/labels/edit/index.js
+++ b/app/assets/javascripts/pages/admin/labels/edit/index.js
@@ -1,3 +1,3 @@
import Labels from '../../../../labels';
-export default () => new Labels();
+document.addEventListener('DOMContentLoaded', () => new Labels());
diff --git a/app/assets/javascripts/pages/admin/labels/new/index.js b/app/assets/javascripts/pages/admin/labels/new/index.js
index d7ec6e47f67..5de1d4d6344 100644
--- a/app/assets/javascripts/pages/admin/labels/new/index.js
+++ b/app/assets/javascripts/pages/admin/labels/new/index.js
@@ -1,3 +1,3 @@
import Labels from '../../../../labels';
-export default () => new Labels();
+document.addEventListener('DOMContentLoaded', () => new Labels());
diff --git a/app/assets/javascripts/pages/admin/projects/index.js b/app/assets/javascripts/pages/admin/projects/index.js
index 71e0ddcd7b6..31c96eb87af 100644
--- a/app/assets/javascripts/pages/admin/projects/index.js
+++ b/app/assets/javascripts/pages/admin/projects/index.js
@@ -1,9 +1,9 @@
import ProjectsList from '../../../projects_list';
import NamespaceSelect from '../../../namespace_select';
-export default () => {
+document.addEventListener('DOMContentLoaded', () => {
new ProjectsList(); // eslint-disable-line no-new
document.querySelectorAll('.js-namespace-select')
.forEach(dropdown => new NamespaceSelect({ dropdown }));
-};
+});
diff --git a/app/assets/javascripts/pages/admin/projects/index/index.js b/app/assets/javascripts/pages/admin/projects/index/index.js
index a87b27090a8..3c597a1093e 100644
--- a/app/assets/javascripts/pages/admin/projects/index/index.js
+++ b/app/assets/javascripts/pages/admin/projects/index/index.js
@@ -5,7 +5,7 @@ import csrf from '~/lib/utils/csrf';
import deleteProjectModal from './components/delete_project_modal.vue';
-export default () => {
+document.addEventListener('DOMContentLoaded', () => {
Vue.use(Translate);
const deleteProjectModalEl = document.getElementById('delete-project-modal');
@@ -34,4 +34,4 @@ export default () => {
deleteModal.projectName = buttonProps.projectName;
}
});
-};
+});
diff --git a/app/assets/javascripts/pages/admin/users/shared/components/delete_user_modal.vue b/app/assets/javascripts/pages/admin/users/components/delete_user_modal.vue
index 7b5e333011e..7b5e333011e 100644
--- a/app/assets/javascripts/pages/admin/users/shared/components/delete_user_modal.vue
+++ b/app/assets/javascripts/pages/admin/users/components/delete_user_modal.vue
diff --git a/app/assets/javascripts/pages/admin/users/shared/index.js b/app/assets/javascripts/pages/admin/users/index.js
index d2a0f82fa2b..4f5d6b55031 100644
--- a/app/assets/javascripts/pages/admin/users/shared/index.js
+++ b/app/assets/javascripts/pages/admin/users/index.js
@@ -5,7 +5,7 @@ import csrf from '~/lib/utils/csrf';
import deleteUserModal from './components/delete_user_modal.vue';
-export default () => {
+document.addEventListener('DOMContentLoaded', () => {
Vue.use(Translate);
const deleteUserModalEl = document.getElementById('delete-user-modal');
@@ -40,4 +40,4 @@ export default () => {
deleteModal.username = buttonProps.username;
}
});
-};
+});
diff --git a/app/assets/javascripts/pages/ci/lints/ci_lint_editor.js b/app/assets/javascripts/pages/ci/lints/ci_lint_editor.js
index b9469e5b7cb..9ab73be80a0 100644
--- a/app/assets/javascripts/pages/ci/lints/ci_lint_editor.js
+++ b/app/assets/javascripts/pages/ci/lints/ci_lint_editor.js
@@ -2,11 +2,18 @@ export default class CILintEditor {
constructor() {
this.editor = window.ace.edit('ci-editor');
this.textarea = document.querySelector('#content');
+ this.clearYml = document.querySelector('.clear-yml');
this.editor.getSession().setMode('ace/mode/yaml');
this.editor.on('input', () => {
const content = this.editor.getSession().getValue();
this.textarea.value = content;
});
+
+ this.clearYml.addEventListener('click', this.clear.bind(this));
+ }
+
+ clear() {
+ this.editor.setValue('');
}
}
diff --git a/app/assets/javascripts/pages/ci/lints/create/index.js b/app/assets/javascripts/pages/ci/lints/create/index.js
new file mode 100644
index 00000000000..8e8a843da0b
--- /dev/null
+++ b/app/assets/javascripts/pages/ci/lints/create/index.js
@@ -0,0 +1,3 @@
+import CILintEditor from '../ci_lint_editor';
+
+document.addEventListener('DOMContentLoaded', () => new CILintEditor());
diff --git a/app/assets/javascripts/pages/ci/lints/index.js b/app/assets/javascripts/pages/ci/lints/index.js
deleted file mode 100644
index 5cc66546109..00000000000
--- a/app/assets/javascripts/pages/ci/lints/index.js
+++ /dev/null
@@ -1,3 +0,0 @@
-import CILintEditor from './ci_lint_editor';
-
-export default () => new CILintEditor();
diff --git a/app/assets/javascripts/pages/ci/lints/show/index.js b/app/assets/javascripts/pages/ci/lints/show/index.js
new file mode 100644
index 00000000000..8e8a843da0b
--- /dev/null
+++ b/app/assets/javascripts/pages/ci/lints/show/index.js
@@ -0,0 +1,3 @@
+import CILintEditor from '../ci_lint_editor';
+
+document.addEventListener('DOMContentLoaded', () => new CILintEditor());
diff --git a/app/assets/javascripts/pages/dashboard/activity/index.js b/app/assets/javascripts/pages/dashboard/activity/index.js
index 95faf1f1e98..1b887cad496 100644
--- a/app/assets/javascripts/pages/dashboard/activity/index.js
+++ b/app/assets/javascripts/pages/dashboard/activity/index.js
@@ -1,3 +1,3 @@
import Activities from '~/activities';
-export default () => new Activities();
+document.addEventListener('DOMContentLoaded', () => new Activities());
diff --git a/app/assets/javascripts/pages/dashboard/groups/index/index.js b/app/assets/javascripts/pages/dashboard/groups/index/index.js
index 8a2aae706c0..79987642796 100644
--- a/app/assets/javascripts/pages/dashboard/groups/index/index.js
+++ b/app/assets/javascripts/pages/dashboard/groups/index/index.js
@@ -1,5 +1,3 @@
-import initGroupsList from '../../../../groups';
+import initGroupsList from '~/groups';
-export default () => {
- initGroupsList();
-};
+document.addEventListener('DOMContentLoaded', initGroupsList);
diff --git a/app/assets/javascripts/pages/dashboard/issues/index.js b/app/assets/javascripts/pages/dashboard/issues/index.js
index b7353669e65..c4901dd1cb6 100644
--- a/app/assets/javascripts/pages/dashboard/issues/index.js
+++ b/app/assets/javascripts/pages/dashboard/issues/index.js
@@ -1,7 +1,7 @@
import projectSelect from '~/project_select';
import initLegacyFilters from '~/init_legacy_filters';
-export default () => {
+document.addEventListener('DOMContentLoaded', () => {
projectSelect();
initLegacyFilters();
-};
+});
diff --git a/app/assets/javascripts/pages/dashboard/merge_requests/index.js b/app/assets/javascripts/pages/dashboard/merge_requests/index.js
index b7353669e65..c4901dd1cb6 100644
--- a/app/assets/javascripts/pages/dashboard/merge_requests/index.js
+++ b/app/assets/javascripts/pages/dashboard/merge_requests/index.js
@@ -1,7 +1,7 @@
import projectSelect from '~/project_select';
import initLegacyFilters from '~/init_legacy_filters';
-export default () => {
+document.addEventListener('DOMContentLoaded', () => {
projectSelect();
initLegacyFilters();
-};
+});
diff --git a/app/assets/javascripts/pages/dashboard/milestones/show/index.js b/app/assets/javascripts/pages/dashboard/milestones/show/index.js
index 2e7a08a369c..397149aaa9e 100644
--- a/app/assets/javascripts/pages/dashboard/milestones/show/index.js
+++ b/app/assets/javascripts/pages/dashboard/milestones/show/index.js
@@ -1,7 +1,9 @@
import Milestone from '~/milestone';
import Sidebar from '~/right_sidebar';
+import MountMilestoneSidebar from '~/sidebar/mount_milestone_sidebar';
-export default () => {
+document.addEventListener('DOMContentLoaded', () => {
new Milestone(); // eslint-disable-line no-new
new Sidebar(); // eslint-disable-line no-new
-};
+ new MountMilestoneSidebar(); // eslint-disable-line no-new
+});
diff --git a/app/assets/javascripts/pages/dashboard/projects/index.js b/app/assets/javascripts/pages/dashboard/projects/index.js
index c88cbf1a6ba..0c585e162cb 100644
--- a/app/assets/javascripts/pages/dashboard/projects/index.js
+++ b/app/assets/javascripts/pages/dashboard/projects/index.js
@@ -1,3 +1,3 @@
import ProjectsList from '~/projects_list';
-export default () => new ProjectsList();
+document.addEventListener('DOMContentLoaded', () => new ProjectsList());
diff --git a/app/assets/javascripts/pages/dashboard/todos/index/index.js b/app/assets/javascripts/pages/dashboard/todos/index/index.js
index 77c23685943..9d2c2f2994f 100644
--- a/app/assets/javascripts/pages/dashboard/todos/index/index.js
+++ b/app/assets/javascripts/pages/dashboard/todos/index/index.js
@@ -1,3 +1,3 @@
import Todos from './todos';
-export default () => new Todos();
+document.addEventListener('DOMContentLoaded', () => new Todos());
diff --git a/app/assets/javascripts/pages/explore/groups/index.js b/app/assets/javascripts/pages/explore/groups/index.js
index e59c38b8bc4..3c7edbdd7c7 100644
--- a/app/assets/javascripts/pages/explore/groups/index.js
+++ b/app/assets/javascripts/pages/explore/groups/index.js
@@ -2,7 +2,7 @@ import GroupsList from '~/groups_list';
import Landing from '~/landing';
import initGroupsList from '../../../groups';
-export default function () {
+document.addEventListener('DOMContentLoaded', () => {
new GroupsList(); // eslint-disable-line no-new
initGroupsList();
const landingElement = document.querySelector('.js-explore-groups-landing');
@@ -13,4 +13,4 @@ export default function () {
'explore_groups_landing_dismissed',
);
exploreGroupsLanding.toggle();
-}
+});
diff --git a/app/assets/javascripts/pages/explore/projects/index.js b/app/assets/javascripts/pages/explore/projects/index.js
index c88cbf1a6ba..0c585e162cb 100644
--- a/app/assets/javascripts/pages/explore/projects/index.js
+++ b/app/assets/javascripts/pages/explore/projects/index.js
@@ -1,3 +1,3 @@
import ProjectsList from '~/projects_list';
-export default () => new ProjectsList();
+document.addEventListener('DOMContentLoaded', () => new ProjectsList());
diff --git a/app/assets/javascripts/pages/groups/activity/index.js b/app/assets/javascripts/pages/groups/activity/index.js
index 95faf1f1e98..1b887cad496 100644
--- a/app/assets/javascripts/pages/groups/activity/index.js
+++ b/app/assets/javascripts/pages/groups/activity/index.js
@@ -1,3 +1,3 @@
import Activities from '~/activities';
-export default () => new Activities();
+document.addEventListener('DOMContentLoaded', () => new Activities());
diff --git a/app/assets/javascripts/pages/groups/edit/index.js b/app/assets/javascripts/pages/groups/edit/index.js
index 1aeec55a4be..d44874c8741 100644
--- a/app/assets/javascripts/pages/groups/edit/index.js
+++ b/app/assets/javascripts/pages/groups/edit/index.js
@@ -1,7 +1,7 @@
import groupAvatar from '~/group_avatar';
import TransferDropdown from '~/groups/transfer_dropdown';
-export default () => {
+document.addEventListener('DOMContentLoaded', () => {
groupAvatar();
new TransferDropdown(); // eslint-disable-line no-new
-};
+});
diff --git a/app/assets/javascripts/pages/groups/group_members/index/index.js b/app/assets/javascripts/pages/groups/group_members/index/index.js
index 29319b97ae2..c22a164cd4e 100644
--- a/app/assets/javascripts/pages/groups/group_members/index/index.js
+++ b/app/assets/javascripts/pages/groups/group_members/index/index.js
@@ -4,8 +4,8 @@ import memberExpirationDate from '~/member_expiration_date';
import Members from '~/members';
import UsersSelect from '~/users_select';
-export default () => {
+document.addEventListener('DOMContentLoaded', () => {
memberExpirationDate();
new Members();
new UsersSelect();
-};
+});
diff --git a/app/assets/javascripts/pages/groups/issues/index.js b/app/assets/javascripts/pages/groups/issues/index.js
index fbdfabd1e95..d149b307e7f 100644
--- a/app/assets/javascripts/pages/groups/issues/index.js
+++ b/app/assets/javascripts/pages/groups/issues/index.js
@@ -2,9 +2,9 @@ import projectSelect from '~/project_select';
import initFilteredSearch from '~/pages/search/init_filtered_search';
import { FILTERED_SEARCH } from '~/pages/constants';
-export default () => {
+document.addEventListener('DOMContentLoaded', () => {
initFilteredSearch({
page: FILTERED_SEARCH.ISSUES,
});
projectSelect();
-};
+});
diff --git a/app/assets/javascripts/pages/groups/labels/edit/index.js b/app/assets/javascripts/pages/groups/labels/edit/index.js
index 72c5e4744ac..fa81ad914ba 100644
--- a/app/assets/javascripts/pages/groups/labels/edit/index.js
+++ b/app/assets/javascripts/pages/groups/labels/edit/index.js
@@ -1,3 +1,3 @@
import Labels from '~/labels';
-export default () => new Labels();
+document.addEventListener('DOMContentLoaded', () => 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 018345fa112..6e45de2a724 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';
-export default initLabels;
+document.addEventListener('DOMContentLoaded', initLabels);
diff --git a/app/assets/javascripts/pages/groups/labels/new/index.js b/app/assets/javascripts/pages/groups/labels/new/index.js
index 72c5e4744ac..fa81ad914ba 100644
--- a/app/assets/javascripts/pages/groups/labels/new/index.js
+++ b/app/assets/javascripts/pages/groups/labels/new/index.js
@@ -1,3 +1,3 @@
import Labels from '~/labels';
-export default () => new Labels();
+document.addEventListener('DOMContentLoaded', () => 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 f6d284bf9ef..a5cc1f34b63 100644
--- a/app/assets/javascripts/pages/groups/merge_requests/index.js
+++ b/app/assets/javascripts/pages/groups/merge_requests/index.js
@@ -2,9 +2,9 @@ import projectSelect from '~/project_select';
import initFilteredSearch from '~/pages/search/init_filtered_search';
import { FILTERED_SEARCH } from '~/pages/constants';
-export default () => {
+document.addEventListener('DOMContentLoaded', () => {
initFilteredSearch({
page: FILTERED_SEARCH.MERGE_REQUESTS,
});
projectSelect();
-};
+});
diff --git a/app/assets/javascripts/pages/groups/milestones/edit/index.js b/app/assets/javascripts/pages/groups/milestones/edit/index.js
index 5c99c90e24d..ddd10fe5062 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';
-export default () => initForm(false);
+document.addEventListener('DOMContentLoaded', () => 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 5c99c90e24d..ddd10fe5062 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';
-export default () => initForm(false);
+document.addEventListener('DOMContentLoaded', () => initForm(false));
diff --git a/app/assets/javascripts/pages/groups/milestones/show/index.js b/app/assets/javascripts/pages/groups/milestones/show/index.js
index c9a18353f2e..88f40b5278e 100644
--- a/app/assets/javascripts/pages/groups/milestones/show/index.js
+++ b/app/assets/javascripts/pages/groups/milestones/show/index.js
@@ -1,3 +1,3 @@
import initMilestonesShow from '~/pages/milestones/shared/init_milestones_show';
-export default initMilestonesShow;
+document.addEventListener('DOMContentLoaded', initMilestonesShow);
diff --git a/app/assets/javascripts/pages/groups/new/index.js b/app/assets/javascripts/pages/groups/new/index.js
index 7850b90d3d2..b2f275dc5ea 100644
--- a/app/assets/javascripts/pages/groups/new/index.js
+++ b/app/assets/javascripts/pages/groups/new/index.js
@@ -2,8 +2,8 @@ import BindInOut from '~/behaviors/bind_in_out';
import Group from '~/group';
import groupAvatar from '~/group_avatar';
-export default () => {
+document.addEventListener('DOMContentLoaded', () => {
BindInOut.initAll();
new Group(); // eslint-disable-line no-new
groupAvatar();
-};
+});
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 ad79f7e09ac..04a0d8117cc 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,6 +1,6 @@
import AjaxVariableList from '~/ci_variable_list/ajax_variable_list';
-export default () => {
+document.addEventListener('DOMContentLoaded', () => {
const variableListEl = document.querySelector('.js-ci-variable-list-section');
// eslint-disable-next-line no-new
new AjaxVariableList({
@@ -9,4 +9,4 @@ export default () => {
errorBox: variableListEl.querySelector('.js-ci-variable-error-box'),
saveEndpoint: variableListEl.dataset.saveEndpoint,
});
-};
+});
diff --git a/app/assets/javascripts/pages/groups/show/index.js b/app/assets/javascripts/pages/groups/show/index.js
index 5c763986da3..d7b35d2b26b 100644
--- a/app/assets/javascripts/pages/groups/show/index.js
+++ b/app/assets/javascripts/pages/groups/show/index.js
@@ -5,7 +5,7 @@ import notificationsDropdown from '~/notifications_dropdown';
import NotificationsForm from '~/notifications_form';
import ProjectsList from '~/projects_list';
import ShortcutsNavigation from '~/shortcuts_navigation';
-import initGroupsList from '../../../groups';
+import initGroupsList from '~/groups';
document.addEventListener('DOMContentLoaded', () => {
const newGroupChildWrapper = document.querySelector('.js-new-project-subgroup');
diff --git a/app/assets/javascripts/pages/help/index.js b/app/assets/javascripts/pages/help/index.js
deleted file mode 100644
index 4cf8afc4b7e..00000000000
--- a/app/assets/javascripts/pages/help/index.js
+++ /dev/null
@@ -1,3 +0,0 @@
-import VersionCheckImage from '../../version_check_image';
-
-export default () => VersionCheckImage.bindErrorEvent($('img.js-version-status-badge'));
diff --git a/app/assets/javascripts/pages/help/index/index.js b/app/assets/javascripts/pages/help/index/index.js
new file mode 100644
index 00000000000..05c81fc618b
--- /dev/null
+++ b/app/assets/javascripts/pages/help/index/index.js
@@ -0,0 +1,7 @@
+import VersionCheckImage from '~/version_check_image';
+import docs from '~/docs/docs_bundle';
+
+document.addEventListener('DOMContentLoaded', () => {
+ docs();
+ VersionCheckImage.bindErrorEvent($('img.js-version-status-badge'));
+});
diff --git a/app/assets/javascripts/pages/help/show/index.js b/app/assets/javascripts/pages/help/show/index.js
new file mode 100644
index 00000000000..ec426a850b6
--- /dev/null
+++ b/app/assets/javascripts/pages/help/show/index.js
@@ -0,0 +1,3 @@
+import initHelp from '~/help/help';
+
+document.addEventListener('DOMContentLoaded', initHelp);
diff --git a/app/assets/javascripts/pages/help/ui/index.js b/app/assets/javascripts/pages/help/ui/index.js
new file mode 100644
index 00000000000..709ca2f3828
--- /dev/null
+++ b/app/assets/javascripts/pages/help/ui/index.js
@@ -0,0 +1,3 @@
+import initUIKit from '~/ui_development_kit';
+
+document.addEventListener('DOMContentLoaded', initUIKit);
diff --git a/app/assets/javascripts/pages/import/fogbugz/new_user_map/index.js b/app/assets/javascripts/pages/import/fogbugz/new_user_map/index.js
index 5defea104d4..68d4c1f049f 100644
--- a/app/assets/javascripts/pages/import/fogbugz/new_user_map/index.js
+++ b/app/assets/javascripts/pages/import/fogbugz/new_user_map/index.js
@@ -1,3 +1,3 @@
-import UsersSelect from '../../../../users_select';
+import UsersSelect from '~/users_select';
-export default () => new UsersSelect();
+document.addEventListener('DOMContentLoaded', () => new UsersSelect());
diff --git a/app/assets/javascripts/pages/import/gitlab_projects/new/index.js b/app/assets/javascripts/pages/import/gitlab_projects/new/index.js
new file mode 100644
index 00000000000..bb86f72b95b
--- /dev/null
+++ b/app/assets/javascripts/pages/import/gitlab_projects/new/index.js
@@ -0,0 +1,3 @@
+import initGitLabImportProject from '~/projects/project_import_gitlab_project';
+
+document.addEventListener('DOMContentLoaded', initGitLabImportProject);
diff --git a/app/assets/javascripts/pages/milestones/shared/init_milestones_show.js b/app/assets/javascripts/pages/milestones/shared/init_milestones_show.js
index 7aa5be0d5b9..b2a896a3265 100644
--- a/app/assets/javascripts/pages/milestones/shared/init_milestones_show.js
+++ b/app/assets/javascripts/pages/milestones/shared/init_milestones_show.js
@@ -2,8 +2,10 @@
import Milestone from '~/milestone';
import Sidebar from '~/right_sidebar';
+import MountMilestoneSidebar from '~/sidebar/mount_milestone_sidebar';
export default () => {
new Milestone();
new Sidebar();
+ new MountMilestoneSidebar();
};
diff --git a/app/assets/javascripts/pages/omniauth_callbacks/index.js b/app/assets/javascripts/pages/omniauth_callbacks/index.js
index 54f4e56359a..c2c069d1ca8 100644
--- a/app/assets/javascripts/pages/omniauth_callbacks/index.js
+++ b/app/assets/javascripts/pages/omniauth_callbacks/index.js
@@ -1,5 +1,3 @@
import initU2F from '../../shared/sessions/u2f';
-export default () => {
- initU2F();
-};
+document.addEventListener('DOMContentLoaded', initU2F);
diff --git a/app/assets/javascripts/pages/profiles/accounts/show/index.js b/app/assets/javascripts/pages/profiles/accounts/show/index.js
new file mode 100644
index 00000000000..96c3d725780
--- /dev/null
+++ b/app/assets/javascripts/pages/profiles/accounts/show/index.js
@@ -0,0 +1,3 @@
+import initProfileAccount from '~/profile/account';
+
+document.addEventListener('DOMContentLoaded', initProfileAccount);
diff --git a/app/assets/javascripts/pages/profiles/index/index.js b/app/assets/javascripts/pages/profiles/index/index.js
index 90eed38777a..9bd430f4f11 100644
--- a/app/assets/javascripts/pages/profiles/index/index.js
+++ b/app/assets/javascripts/pages/profiles/index/index.js
@@ -1,7 +1,7 @@
import NotificationsForm from '../../../notifications_form';
import notificationsDropdown from '../../../notifications_dropdown';
-export default () => {
+document.addEventListener('DOMContentLoaded', () => {
new NotificationsForm(); // eslint-disable-line no-new
notificationsDropdown();
-};
+});
diff --git a/app/assets/javascripts/pages/profiles/personal_access_tokens/index.js b/app/assets/javascripts/pages/profiles/personal_access_tokens/index.js
index 030328a1363..78a5c4c27be 100644
--- a/app/assets/javascripts/pages/profiles/personal_access_tokens/index.js
+++ b/app/assets/javascripts/pages/profiles/personal_access_tokens/index.js
@@ -1,3 +1,3 @@
-import DueDateSelectors from '../../../due_date_select';
+import DueDateSelectors from '~/due_date_select';
-export default () => new DueDateSelectors();
+document.addEventListener('DOMContentLoaded', () => new DueDateSelectors());
diff --git a/app/assets/javascripts/pages/projects/activity/index.js b/app/assets/javascripts/pages/projects/activity/index.js
index 7af95127fd5..5543ad82428 100644
--- a/app/assets/javascripts/pages/projects/activity/index.js
+++ b/app/assets/javascripts/pages/projects/activity/index.js
@@ -1,7 +1,7 @@
import Activities from '~/activities';
import ShortcutsNavigation from '~/shortcuts_navigation';
-export default function () {
+document.addEventListener('DOMContentLoaded', () => {
new Activities(); // eslint-disable-line no-new
new ShortcutsNavigation(); // eslint-disable-line no-new
-}
+});
diff --git a/app/assets/javascripts/pages/projects/artifacts/browse/index.js b/app/assets/javascripts/pages/projects/artifacts/browse/index.js
index 02456071086..ea7458fe9b8 100644
--- a/app/assets/javascripts/pages/projects/artifacts/browse/index.js
+++ b/app/assets/javascripts/pages/projects/artifacts/browse/index.js
@@ -1,7 +1,7 @@
import BuildArtifacts from '~/build_artifacts';
import ShortcutsNavigation from '~/shortcuts_navigation';
-export default function () {
+document.addEventListener('DOMContentLoaded', () => {
new ShortcutsNavigation(); // eslint-disable-line no-new
new BuildArtifacts(); // eslint-disable-line no-new
-}
+});
diff --git a/app/assets/javascripts/pages/projects/artifacts/file/index.js b/app/assets/javascripts/pages/projects/artifacts/file/index.js
index 4cd67ac76e3..8484e5e9848 100644
--- a/app/assets/javascripts/pages/projects/artifacts/file/index.js
+++ b/app/assets/javascripts/pages/projects/artifacts/file/index.js
@@ -1,7 +1,7 @@
import BlobViewer from '~/blob/viewer/index';
import ShortcutsNavigation from '~/shortcuts_navigation';
-export default function () {
+document.addEventListener('DOMContentLoaded', () => {
new ShortcutsNavigation(); // eslint-disable-line no-new
new BlobViewer(); // eslint-disable-line no-new
-}
+});
diff --git a/app/assets/javascripts/pages/projects/blame/show/index.js b/app/assets/javascripts/pages/projects/blame/show/index.js
index 480357a309c..80d0bff92fa 100644
--- a/app/assets/javascripts/pages/projects/blame/show/index.js
+++ b/app/assets/javascripts/pages/projects/blame/show/index.js
@@ -1,3 +1,3 @@
import initBlob from '~/pages/projects/init_blob';
-export default initBlob;
+document.addEventListener('DOMContentLoaded', initBlob);
diff --git a/app/assets/javascripts/pages/projects/blob/edit/index.js b/app/assets/javascripts/pages/projects/blob/edit/index.js
new file mode 100644
index 00000000000..189053f3ed7
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/blob/edit/index.js
@@ -0,0 +1,3 @@
+import initBlobBundle from '~/blob_edit/blob_bundle';
+
+document.addEventListener('DOMContentLoaded', initBlobBundle);
diff --git a/app/assets/javascripts/pages/projects/blob/new/index.js b/app/assets/javascripts/pages/projects/blob/new/index.js
new file mode 100644
index 00000000000..189053f3ed7
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/blob/new/index.js
@@ -0,0 +1,3 @@
+import initBlobBundle from '~/blob_edit/blob_bundle';
+
+document.addEventListener('DOMContentLoaded', initBlobBundle);
diff --git a/app/assets/javascripts/pages/projects/blob/show/index.js b/app/assets/javascripts/pages/projects/blob/show/index.js
index a3eeb1cefb6..26cbb279d4a 100644
--- a/app/assets/javascripts/pages/projects/blob/show/index.js
+++ b/app/assets/javascripts/pages/projects/blob/show/index.js
@@ -1,7 +1,7 @@
import BlobViewer from '~/blob/viewer/index';
import initBlob from '~/pages/projects/init_blob';
-export default () => {
+document.addEventListener('DOMContentLoaded', () => {
new BlobViewer(); // eslint-disable-line no-new
initBlob();
-};
+});
diff --git a/app/assets/javascripts/pages/projects/boards/index.js b/app/assets/javascripts/pages/projects/boards/index.js
index 3aeeedbb45d..5cfe8723204 100644
--- a/app/assets/javascripts/pages/projects/boards/index.js
+++ b/app/assets/javascripts/pages/projects/boards/index.js
@@ -1,7 +1,9 @@
import UsersSelect from '~/users_select';
import ShortcutsNavigation from '~/shortcuts_navigation';
+import initBoards from '~/boards';
document.addEventListener('DOMContentLoaded', () => {
new UsersSelect(); // eslint-disable-line no-new
new ShortcutsNavigation(); // eslint-disable-line no-new
+ initBoards();
});
diff --git a/app/assets/javascripts/pages/projects/branches/index/index.js b/app/assets/javascripts/pages/projects/branches/index/index.js
index cee0f19bf2a..8fa266a37ce 100644
--- a/app/assets/javascripts/pages/projects/branches/index/index.js
+++ b/app/assets/javascripts/pages/projects/branches/index/index.js
@@ -1,7 +1,7 @@
import AjaxLoadingSpinner from '~/ajax_loading_spinner';
import DeleteModal from '~/branches/branches_delete_modal';
-export default () => {
+document.addEventListener('DOMContentLoaded', () => {
AjaxLoadingSpinner.init();
new DeleteModal(); // eslint-disable-line no-new
-};
+});
diff --git a/app/assets/javascripts/pages/projects/branches/new/index.js b/app/assets/javascripts/pages/projects/branches/new/index.js
index ae5e033e97e..d32d5c6cb29 100644
--- a/app/assets/javascripts/pages/projects/branches/new/index.js
+++ b/app/assets/javascripts/pages/projects/branches/new/index.js
@@ -1,3 +1,5 @@
import NewBranchForm from '~/new_branch_form';
-export default () => new NewBranchForm($('.js-create-branch-form'), JSON.parse(document.getElementById('availableRefs').innerHTML));
+document.addEventListener('DOMContentLoaded', () => (
+ new NewBranchForm($('.js-create-branch-form'), JSON.parse(document.getElementById('availableRefs').innerHTML))
+));
diff --git a/app/assets/javascripts/pages/projects/clusters/destroy/index.js b/app/assets/javascripts/pages/projects/clusters/destroy/index.js
new file mode 100644
index 00000000000..8001d2dd1da
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/clusters/destroy/index.js
@@ -0,0 +1,5 @@
+import ClustersBundle from '~/clusters/clusters_bundle';
+
+document.addEventListener('DOMContentLoaded', () => {
+ new ClustersBundle(); // eslint-disable-line no-new
+});
diff --git a/app/assets/javascripts/pages/projects/clusters/index/index.js b/app/assets/javascripts/pages/projects/clusters/index/index.js
index d531ab81dc7..e4b8baede58 100644
--- a/app/assets/javascripts/pages/projects/clusters/index/index.js
+++ b/app/assets/javascripts/pages/projects/clusters/index/index.js
@@ -1,5 +1,5 @@
import ClustersIndex from '~/clusters/clusters_index';
-export default () => {
+document.addEventListener('DOMContentLoaded', () => {
new ClustersIndex(); // eslint-disable-line no-new
-};
+});
diff --git a/app/assets/javascripts/pages/projects/clusters/show/index.js b/app/assets/javascripts/pages/projects/clusters/show/index.js
index 0458c02a66f..8001d2dd1da 100644
--- a/app/assets/javascripts/pages/projects/clusters/show/index.js
+++ b/app/assets/javascripts/pages/projects/clusters/show/index.js
@@ -1,5 +1,5 @@
import ClustersBundle from '~/clusters/clusters_bundle';
-export default () => {
+document.addEventListener('DOMContentLoaded', () => {
new ClustersBundle(); // eslint-disable-line no-new
-};
+});
diff --git a/app/assets/javascripts/pages/projects/clusters/update/index.js b/app/assets/javascripts/pages/projects/clusters/update/index.js
new file mode 100644
index 00000000000..8001d2dd1da
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/clusters/update/index.js
@@ -0,0 +1,5 @@
+import ClustersBundle from '~/clusters/clusters_bundle';
+
+document.addEventListener('DOMContentLoaded', () => {
+ new ClustersBundle(); // eslint-disable-line no-new
+});
diff --git a/app/assets/javascripts/pages/projects/commit/pipelines/index.js b/app/assets/javascripts/pages/projects/commit/pipelines/index.js
index 523ad567021..cd923f13ce8 100644
--- a/app/assets/javascripts/pages/projects/commit/pipelines/index.js
+++ b/app/assets/javascripts/pages/projects/commit/pipelines/index.js
@@ -1,8 +1,10 @@
import MiniPipelineGraph from '~/mini_pipeline_graph_dropdown';
+import initPipelines from '~/commit/pipelines/pipelines_bundle';
-export default () => {
+document.addEventListener('DOMContentLoaded', () => {
new MiniPipelineGraph({
container: '.js-commit-pipeline-graph',
}).bindEvents();
$('.commit-info.branches').load(document.querySelector('.js-commit-box').dataset.commitPath);
-};
+ initPipelines();
+});
diff --git a/app/assets/javascripts/pages/projects/commit/show/index.js b/app/assets/javascripts/pages/projects/commit/show/index.js
index 5ac38e6f278..460a54ab504 100644
--- a/app/assets/javascripts/pages/projects/commit/show/index.js
+++ b/app/assets/javascripts/pages/projects/commit/show/index.js
@@ -7,7 +7,7 @@ import initNotes from '~/init_notes';
import initChangesDropdown from '~/init_changes_dropdown';
import { fetchCommitMergeRequests } from '~/commit_merge_requests';
-export default () => {
+document.addEventListener('DOMContentLoaded', () => {
new Diff();
new ZenMode();
new ShortcutsNavigation();
@@ -19,4 +19,4 @@ export default () => {
initChangesDropdown(document.querySelector('.navbar-gitlab').offsetHeight - stickyBarPaddingTop);
$('.commit-info.branches').load(document.querySelector('.js-commit-box').dataset.commitPath);
fetchCommitMergeRequests();
-};
+});
diff --git a/app/assets/javascripts/pages/projects/commits/show/index.js b/app/assets/javascripts/pages/projects/commits/show/index.js
index 90b5882a24f..3682020579b 100644
--- a/app/assets/javascripts/pages/projects/commits/show/index.js
+++ b/app/assets/javascripts/pages/projects/commits/show/index.js
@@ -2,8 +2,8 @@ import CommitsList from '~/commits';
import GpgBadges from '~/gpg_badges';
import ShortcutsNavigation from '~/shortcuts_navigation';
-export default () => {
- CommitsList.init(document.querySelector('.js-project-commits-show').dataset.commitsLimit);
+document.addEventListener('DOMContentLoaded', () => {
+ new CommitsList(document.querySelector('.js-project-commits-show').dataset.commitsLimit); // eslint-disable-line no-new
new ShortcutsNavigation(); // eslint-disable-line no-new
GpgBadges.fetch();
-};
+});
diff --git a/app/assets/javascripts/pages/projects/compare/index.js b/app/assets/javascripts/pages/projects/compare/index.js
index 890062eeee6..d1c78bd61db 100644
--- a/app/assets/javascripts/pages/projects/compare/index.js
+++ b/app/assets/javascripts/pages/projects/compare/index.js
@@ -1,5 +1,3 @@
import initCompareAutocomplete from '~/compare_autocomplete';
-export default () => {
- initCompareAutocomplete();
-};
+document.addEventListener('DOMContentLoaded', initCompareAutocomplete);
diff --git a/app/assets/javascripts/pages/projects/compare/show/index.js b/app/assets/javascripts/pages/projects/compare/show/index.js
index 6b8d4503568..2b4fd3c47c0 100644
--- a/app/assets/javascripts/pages/projects/compare/show/index.js
+++ b/app/assets/javascripts/pages/projects/compare/show/index.js
@@ -1,8 +1,8 @@
import Diff from '~/diff';
import initChangesDropdown from '~/init_changes_dropdown';
-export default () => {
+document.addEventListener('DOMContentLoaded', () => {
new Diff(); // eslint-disable-line no-new
const paddingTop = 16;
initChangesDropdown(document.querySelector('.navbar-gitlab').offsetHeight - paddingTop);
-};
+});
diff --git a/app/assets/javascripts/pages/projects/edit/index.js b/app/assets/javascripts/pages/projects/edit/index.js
index 9edf36d66b1..064de22dfd6 100644
--- a/app/assets/javascripts/pages/projects/edit/index.js
+++ b/app/assets/javascripts/pages/projects/edit/index.js
@@ -4,11 +4,11 @@ import ProjectNew from '../shared/project_new';
import projectAvatar from '../shared/project_avatar';
import initProjectPermissionsSettings from '../shared/permissions';
-export default () => {
+document.addEventListener('DOMContentLoaded', () => {
new ProjectNew(); // eslint-disable-line no-new
setupProjectEdit();
// Initialize expandable settings panels
initSettingsPanels();
projectAvatar();
initProjectPermissionsSettings();
-};
+});
diff --git a/app/assets/javascripts/pages/projects/environments/folder/index.js b/app/assets/javascripts/pages/projects/environments/folder/index.js
new file mode 100644
index 00000000000..5feaf944038
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/environments/folder/index.js
@@ -0,0 +1,3 @@
+import initEnvironmentsFolderBundle from '~/environments/folder/environments_folder_bundle';
+
+document.addEventListener('DOMContentLoaded', initEnvironmentsFolderBundle);
diff --git a/app/assets/javascripts/pages/projects/environments/metrics/index.js b/app/assets/javascripts/pages/projects/environments/metrics/index.js
index f4760cb2720..0b644780ad4 100644
--- a/app/assets/javascripts/pages/projects/environments/metrics/index.js
+++ b/app/assets/javascripts/pages/projects/environments/metrics/index.js
@@ -1,3 +1,3 @@
import monitoringBundle from '~/monitoring/monitoring_bundle';
-export default monitoringBundle;
+document.addEventListener('DOMContentLoaded', monitoringBundle);
diff --git a/app/assets/javascripts/pages/projects/find_file/show/index.js b/app/assets/javascripts/pages/projects/find_file/show/index.js
index 42bde0ff779..23d857d69ec 100644
--- a/app/assets/javascripts/pages/projects/find_file/show/index.js
+++ b/app/assets/javascripts/pages/projects/find_file/show/index.js
@@ -1,7 +1,7 @@
import ProjectFindFile from '~/project_find_file';
import ShortcutsFindFile from '~/shortcuts_find_file';
-export default () => {
+document.addEventListener('DOMContentLoaded', () => {
const findElement = document.querySelector('.js-file-finder');
const projectFindFile = new ProjectFindFile($('.file-finder-holder'), {
url: findElement.dataset.fileFindUrl,
@@ -9,4 +9,4 @@ export default () => {
blobUrlTemplate: findElement.dataset.blobUrlTemplate,
});
new ShortcutsFindFile(projectFindFile); // eslint-disable-line no-new
-};
+});
diff --git a/app/assets/javascripts/pages/projects/forks/new/index.js b/app/assets/javascripts/pages/projects/forks/new/index.js
index 7825eb01949..d80e27e9156 100644
--- a/app/assets/javascripts/pages/projects/forks/new/index.js
+++ b/app/assets/javascripts/pages/projects/forks/new/index.js
@@ -1,5 +1,3 @@
import ProjectFork from '~/project_fork';
-export default () => {
- new ProjectFork(); // eslint-disable-line no-new
-};
+document.addEventListener('DOMContentLoaded', () => new ProjectFork());
diff --git a/app/assets/javascripts/pages/projects/graphs/charts/index.js b/app/assets/javascripts/pages/projects/graphs/charts/index.js
new file mode 100644
index 00000000000..42df19c2968
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/graphs/charts/index.js
@@ -0,0 +1,61 @@
+import Chart from 'chart.js';
+import _ from 'underscore';
+
+document.addEventListener('DOMContentLoaded', () => {
+ const projectChartData = JSON.parse(document.getElementById('projectChartData').innerHTML);
+
+ const responsiveChart = (selector, data) => {
+ const options = {
+ scaleOverlay: true,
+ responsive: true,
+ pointHitDetectionRadius: 2,
+ maintainAspectRatio: false,
+ };
+ // get selector by context
+ const ctx = selector.get(0).getContext('2d');
+ // pointing parent container to make chart.js inherit its width
+ const container = $(selector).parent();
+ const generateChart = () => {
+ selector.attr('width', $(container).width());
+ if (window.innerWidth < 768) {
+ // Scale fonts if window width lower than 768px (iPad portrait)
+ options.scaleFontSize = 8;
+ }
+ return new Chart(ctx).Bar(data, options);
+ };
+ // enabling auto-resizing
+ $(window).resize(generateChart);
+ return generateChart();
+ };
+
+ const chartData = data => ({
+ labels: Object.keys(data),
+ datasets: [{
+ fillColor: 'rgba(220,220,220,0.5)',
+ strokeColor: 'rgba(220,220,220,1)',
+ barStrokeWidth: 1,
+ barValueSpacing: 1,
+ barDatasetSpacing: 1,
+ data: _.values(data),
+ }],
+ });
+
+ const hourData = chartData(projectChartData.hour);
+ responsiveChart($('#hour-chart'), hourData);
+
+ const dayData = chartData(projectChartData.weekDays);
+ responsiveChart($('#weekday-chart'), dayData);
+
+ const monthData = chartData(projectChartData.month);
+ responsiveChart($('#month-chart'), monthData);
+
+ const data = projectChartData.languages;
+ const ctx = $('#languages-chart').get(0).getContext('2d');
+ const options = {
+ scaleOverlay: true,
+ responsive: true,
+ maintainAspectRatio: false,
+ };
+
+ new Chart(ctx).Pie(data, options);
+});
diff --git a/app/assets/javascripts/pages/projects/graphs/show/index.js b/app/assets/javascripts/pages/projects/graphs/show/index.js
new file mode 100644
index 00000000000..f516ff20995
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/graphs/show/index.js
@@ -0,0 +1,23 @@
+import flash from '~/flash';
+import { __ } from '~/locale';
+import axios from '~/lib/utils/axios_utils';
+import ContributorsStatGraph from './stat_graph_contributors';
+
+document.addEventListener('DOMContentLoaded', () => {
+ const url = document.querySelector('.js-graphs-show').dataset.projectGraphPath;
+
+ axios.get(url)
+ .then(({ data }) => {
+ const graph = new ContributorsStatGraph();
+ graph.init(data);
+
+ $('#brush_change').change(() => {
+ graph.change_date_header();
+ graph.redraw_authors();
+ });
+
+ $('.stat-graph').fadeIn();
+ $('.loading-graph').hide();
+ })
+ .catch(() => flash(__('Error fetching contributors data.')));
+});
diff --git a/app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors.js b/app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors.js
new file mode 100644
index 00000000000..9ac0b4c07e5
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors.js
@@ -0,0 +1,125 @@
+/* eslint-disable func-names, space-before-function-paren, wrap-iife, no-var, one-var, camelcase, one-var-declaration-per-line, quotes, no-param-reassign, quote-props, comma-dangle, prefer-template, max-len, no-return-assign, no-shadow */
+
+import _ from 'underscore';
+import { n__, s__, createDateTimeFormat, sprintf } from '~/locale';
+import { ContributorsGraph, ContributorsAuthorGraph, ContributorsMasterGraph } from './stat_graph_contributors_graph';
+import ContributorsStatGraphUtil from './stat_graph_contributors_util';
+
+export default (function() {
+ function ContributorsStatGraph() {
+ this.dateFormat = createDateTimeFormat({ year: 'numeric', month: 'long', day: 'numeric' });
+ }
+
+ ContributorsStatGraph.prototype.init = function(log) {
+ var author_commits, total_commits;
+ this.parsed_log = ContributorsStatGraphUtil.parse_log(log);
+ this.set_current_field("commits");
+ total_commits = ContributorsStatGraphUtil.get_total_data(this.parsed_log, this.field);
+ author_commits = ContributorsStatGraphUtil.get_author_data(this.parsed_log, this.field);
+ this.add_master_graph(total_commits);
+ this.add_authors_graph(author_commits);
+ return this.change_date_header();
+ };
+
+ ContributorsStatGraph.prototype.add_master_graph = function(total_data) {
+ this.master_graph = new ContributorsMasterGraph(total_data);
+ return this.master_graph.draw();
+ };
+
+ ContributorsStatGraph.prototype.add_authors_graph = function(author_data) {
+ var limited_author_data;
+ this.authors = [];
+ limited_author_data = author_data.slice(0, 100);
+ return _.each(limited_author_data, (function(_this) {
+ return function(d) {
+ var author_graph, author_header;
+ author_header = _this.create_author_header(d);
+ $(".contributors-list").append(author_header);
+ _this.authors[d.author_name] = author_graph = new ContributorsAuthorGraph(d.dates);
+ return author_graph.draw();
+ };
+ })(this));
+ };
+
+ ContributorsStatGraph.prototype.format_author_commit_info = function(author) {
+ var commits;
+ commits = $('<span/>', {
+ "class": 'graph-author-commits-count'
+ });
+ commits.text(n__('%d commit', '%d commits', author.commits));
+ return $('<span/>').append(commits);
+ };
+
+ ContributorsStatGraph.prototype.create_author_header = function(author) {
+ var author_commit_info, author_commit_info_span, author_email, author_name, list_item;
+ list_item = $('<li/>', {
+ "class": 'person',
+ style: 'display: block;'
+ });
+ author_name = $('<h4>' + author.author_name + '</h4>');
+ author_email = $('<p class="graph-author-email">' + author.author_email + '</p>');
+ author_commit_info_span = $('<span/>', {
+ "class": 'commits'
+ });
+ author_commit_info = this.format_author_commit_info(author);
+ author_commit_info_span.html(author_commit_info);
+ list_item.append(author_name);
+ list_item.append(author_email);
+ list_item.append(author_commit_info_span);
+ return list_item;
+ };
+
+ ContributorsStatGraph.prototype.redraw_master = function() {
+ var total_data;
+ total_data = ContributorsStatGraphUtil.get_total_data(this.parsed_log, this.field);
+ this.master_graph.set_data(total_data);
+ return this.master_graph.redraw();
+ };
+
+ ContributorsStatGraph.prototype.redraw_authors = function() {
+ var author_commits, x_domain;
+ $("ol").html("");
+ x_domain = ContributorsGraph.prototype.x_domain;
+ author_commits = ContributorsStatGraphUtil.get_author_data(this.parsed_log, this.field, x_domain);
+ return _.each(author_commits, (function(_this) {
+ return function(d) {
+ _this.redraw_author_commit_info(d);
+ if (_this.authors[d.author_name] != null) {
+ $(_this.authors[d.author_name].list_item).appendTo("ol");
+ _this.authors[d.author_name].set_data(d.dates);
+ return _this.authors[d.author_name].redraw();
+ }
+ return '';
+ };
+ })(this));
+ };
+
+ ContributorsStatGraph.prototype.set_current_field = function(field) {
+ return this.field = field;
+ };
+
+ ContributorsStatGraph.prototype.change_date_header = function() {
+ const x_domain = ContributorsGraph.prototype.x_domain;
+ const formattedDateRange = sprintf(
+ s__('ContributorsPage|%{startDate} – %{endDate}'),
+ {
+ startDate: this.dateFormat.format(new Date(x_domain[0])),
+ endDate: this.dateFormat.format(new Date(x_domain[1])),
+ },
+ );
+ return $('#date_header').text(formattedDateRange);
+ };
+
+ ContributorsStatGraph.prototype.redraw_author_commit_info = function(author) {
+ var author_commit_info, author_list_item, $author;
+ $author = this.authors[author.author_name];
+ if ($author != null) {
+ author_list_item = $(this.authors[author.author_name].list_item);
+ author_commit_info = this.format_author_commit_info(author);
+ return author_list_item.find("span").html(author_commit_info);
+ }
+ return '';
+ };
+
+ return ContributorsStatGraph;
+})();
diff --git a/app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors_graph.js b/app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors_graph.js
new file mode 100644
index 00000000000..6ffaa277a0a
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors_graph.js
@@ -0,0 +1,294 @@
+/* eslint-disable func-names, space-before-function-paren, no-var, prefer-rest-params, max-len, no-restricted-syntax, vars-on-top, no-use-before-define, no-param-reassign, new-cap, no-underscore-dangle, wrap-iife, comma-dangle, no-return-assign, prefer-arrow-callback, quotes, prefer-template, newline-per-chained-call, no-else-return, no-shadow */
+import _ from 'underscore';
+import { extent, max } from 'd3-array';
+import { select, event as d3Event } from 'd3-selection';
+import { scaleTime, scaleLinear } from 'd3-scale';
+import { axisLeft, axisBottom } from 'd3-axis';
+import { area } from 'd3-shape';
+import { brushX } from 'd3-brush';
+import { timeParse } from 'd3-time-format';
+import { dateTickFormat } from '~/lib/utils/tick_formats';
+
+const d3 = { extent, max, select, scaleTime, scaleLinear, axisLeft, axisBottom, area, brushX, timeParse };
+
+const extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
+const hasProp = {}.hasOwnProperty;
+
+export const ContributorsGraph = (function() {
+ function ContributorsGraph() {}
+
+ ContributorsGraph.prototype.MARGIN = {
+ top: 20,
+ right: 20,
+ bottom: 30,
+ left: 50
+ };
+
+ ContributorsGraph.prototype.x_domain = null;
+
+ ContributorsGraph.prototype.y_domain = null;
+
+ ContributorsGraph.prototype.dates = [];
+
+ ContributorsGraph.set_x_domain = function(data) {
+ return ContributorsGraph.prototype.x_domain = data;
+ };
+
+ ContributorsGraph.set_y_domain = function(data) {
+ return ContributorsGraph.prototype.y_domain = [
+ 0, d3.max(data, function(d) {
+ return d.commits = d.commits || d.additions || d.deletions;
+ })
+ ];
+ };
+
+ ContributorsGraph.init_x_domain = function(data) {
+ return ContributorsGraph.prototype.x_domain = d3.extent(data, function(d) {
+ return d.date;
+ });
+ };
+
+ ContributorsGraph.init_y_domain = function(data) {
+ return ContributorsGraph.prototype.y_domain = [
+ 0, d3.max(data, function(d) {
+ return d.commits = d.commits || d.additions || d.deletions;
+ })
+ ];
+ };
+
+ ContributorsGraph.init_domain = function(data) {
+ ContributorsGraph.init_x_domain(data);
+ return ContributorsGraph.init_y_domain(data);
+ };
+
+ ContributorsGraph.set_dates = function(data) {
+ return ContributorsGraph.prototype.dates = data;
+ };
+
+ ContributorsGraph.prototype.set_x_domain = function() {
+ return this.x.domain(this.x_domain);
+ };
+
+ ContributorsGraph.prototype.set_y_domain = function() {
+ return this.y.domain(this.y_domain);
+ };
+
+ ContributorsGraph.prototype.set_domain = function() {
+ this.set_x_domain();
+ return this.set_y_domain();
+ };
+
+ ContributorsGraph.prototype.create_scale = function(width, height) {
+ this.x = d3.scaleTime().range([0, width]).clamp(true);
+ return this.y = d3.scaleLinear().range([height, 0]).nice();
+ };
+
+ ContributorsGraph.prototype.draw_x_axis = function() {
+ return this.svg.append("g").attr("class", "x axis").attr("transform", "translate(0, " + this.height + ")").call(this.x_axis);
+ };
+
+ ContributorsGraph.prototype.draw_y_axis = function() {
+ return this.svg.append("g").attr("class", "y axis").call(this.y_axis);
+ };
+
+ ContributorsGraph.prototype.set_data = function(data) {
+ return this.data = data;
+ };
+
+ return ContributorsGraph;
+})();
+
+export const ContributorsMasterGraph = (function(superClass) {
+ extend(ContributorsMasterGraph, superClass);
+
+ function ContributorsMasterGraph(data1) {
+ const $parentElement = $('#contributors-master');
+ const parentPadding = parseFloat($parentElement.css('padding-left')) + parseFloat($parentElement.css('padding-right'));
+
+ this.data = data1;
+ this.update_content = this.update_content.bind(this);
+ this.width = $('.content').width() - parentPadding - (this.MARGIN.left + this.MARGIN.right);
+ this.height = 200;
+ this.x = null;
+ this.y = null;
+ this.x_axis = null;
+ this.y_axis = null;
+ this.area = null;
+ this.svg = null;
+ this.brush = null;
+ this.x_max_domain = null;
+ }
+
+ ContributorsMasterGraph.prototype.process_dates = function(data) {
+ var dates;
+ dates = this.get_dates(data);
+ this.parse_dates(data);
+ return ContributorsGraph.set_dates(dates);
+ };
+
+ ContributorsMasterGraph.prototype.get_dates = function(data) {
+ return _.pluck(data, 'date');
+ };
+
+ ContributorsMasterGraph.prototype.parse_dates = function(data) {
+ var parseDate;
+ parseDate = d3.timeParse("%Y-%m-%d");
+ return data.forEach(function(d) {
+ return d.date = parseDate(d.date);
+ });
+ };
+
+ ContributorsMasterGraph.prototype.create_scale = function() {
+ return ContributorsMasterGraph.__super__.create_scale.call(this, this.width, this.height);
+ };
+
+ ContributorsMasterGraph.prototype.create_axes = function() {
+ this.x_axis = d3.axisBottom()
+ .scale(this.x)
+ .tickFormat(dateTickFormat);
+ return this.y_axis = d3.axisLeft().scale(this.y).ticks(5);
+ };
+
+ ContributorsMasterGraph.prototype.create_svg = function() {
+ return this.svg = d3.select("#contributors-master").append("svg").attr("width", this.width + this.MARGIN.left + this.MARGIN.right).attr("height", this.height + this.MARGIN.top + this.MARGIN.bottom).attr("class", "tint-box").append("g").attr("transform", "translate(" + this.MARGIN.left + "," + this.MARGIN.top + ")");
+ };
+
+ ContributorsMasterGraph.prototype.create_area = function(x, y) {
+ return this.area = d3.area().x(function(d) {
+ return x(d.date);
+ }).y0(this.height).y1(function(d) {
+ d.commits = d.commits || d.additions || d.deletions;
+ return y(d.commits);
+ });
+ };
+
+ ContributorsMasterGraph.prototype.create_brush = function() {
+ return this.brush = d3.brushX(this.x).extent([[this.x.range()[0], 0], [this.x.range()[1], this.height]]).on("end", this.update_content);
+ };
+
+ ContributorsMasterGraph.prototype.draw_path = function(data) {
+ return this.svg.append("path").datum(data).attr("class", "area").attr("d", this.area);
+ };
+
+ ContributorsMasterGraph.prototype.add_brush = function() {
+ return this.svg.append("g").attr("class", "selection").call(this.brush).selectAll("rect").attr("height", this.height);
+ };
+
+ ContributorsMasterGraph.prototype.update_content = function() {
+ // d3Event.selection replaces the function brush.empty() calls
+ if (d3Event.selection != null) {
+ ContributorsGraph.set_x_domain(d3Event.selection.map(this.x.invert));
+ } else {
+ ContributorsGraph.set_x_domain(this.x_max_domain);
+ }
+ return $("#brush_change").trigger('change');
+ };
+
+ ContributorsMasterGraph.prototype.draw = function() {
+ this.process_dates(this.data);
+ this.create_scale();
+ this.create_axes();
+ ContributorsGraph.init_domain(this.data);
+ this.x_max_domain = this.x_domain;
+ this.set_domain();
+ this.create_area(this.x, this.y);
+ this.create_svg();
+ this.create_brush();
+ this.draw_path(this.data);
+ this.draw_x_axis();
+ this.draw_y_axis();
+ return this.add_brush();
+ };
+
+ ContributorsMasterGraph.prototype.redraw = function() {
+ this.process_dates(this.data);
+ ContributorsGraph.set_y_domain(this.data);
+ this.set_y_domain();
+ this.svg.select("path").datum(this.data);
+ this.svg.select("path").attr("d", this.area);
+ return this.svg.select(".y.axis").call(this.y_axis);
+ };
+
+ return ContributorsMasterGraph;
+})(ContributorsGraph);
+
+export const ContributorsAuthorGraph = (function(superClass) {
+ extend(ContributorsAuthorGraph, superClass);
+
+ function ContributorsAuthorGraph(data1) {
+ this.data = data1;
+ // Don't split graph size in half for mobile devices.
+ if ($(window).width() < 768) {
+ this.width = $('.content').width() - 80;
+ } else {
+ this.width = ($('.content').width() / 2) - 100;
+ }
+ this.height = 200;
+ this.x = null;
+ this.y = null;
+ this.x_axis = null;
+ this.y_axis = null;
+ this.area = null;
+ this.svg = null;
+ this.list_item = null;
+ }
+
+ ContributorsAuthorGraph.prototype.create_scale = function() {
+ return ContributorsAuthorGraph.__super__.create_scale.call(this, this.width, this.height);
+ };
+
+ ContributorsAuthorGraph.prototype.create_axes = function() {
+ this.x_axis = d3.axisBottom()
+ .scale(this.x)
+ .ticks(8)
+ .tickFormat(dateTickFormat);
+ return this.y_axis = d3.axisLeft().scale(this.y).ticks(5);
+ };
+
+ ContributorsAuthorGraph.prototype.create_area = function(x, y) {
+ return this.area = d3.area().x(function(d) {
+ var parseDate;
+ parseDate = d3.timeParse("%Y-%m-%d");
+ return x(parseDate(d));
+ }).y0(this.height).y1((function(_this) {
+ return function(d) {
+ if (_this.data[d] != null) {
+ return y(_this.data[d]);
+ } else {
+ return y(0);
+ }
+ };
+ })(this));
+ };
+
+ ContributorsAuthorGraph.prototype.create_svg = function() {
+ var persons = document.querySelectorAll('.person');
+ this.list_item = persons[persons.length - 1];
+ return this.svg = d3.select(this.list_item).append("svg").attr("width", this.width + this.MARGIN.left + this.MARGIN.right).attr("height", this.height + this.MARGIN.top + this.MARGIN.bottom).attr("class", "spark").append("g").attr("transform", "translate(" + this.MARGIN.left + "," + this.MARGIN.top + ")");
+ };
+
+ ContributorsAuthorGraph.prototype.draw_path = function(data) {
+ return this.svg.append("path").datum(data).attr("class", "area-contributor").attr("d", this.area);
+ };
+
+ ContributorsAuthorGraph.prototype.draw = function() {
+ this.create_scale();
+ this.create_axes();
+ this.set_domain();
+ this.create_area(this.x, this.y);
+ this.create_svg();
+ this.draw_path(this.dates);
+ this.draw_x_axis();
+ return this.draw_y_axis();
+ };
+
+ ContributorsAuthorGraph.prototype.redraw = function() {
+ this.set_domain();
+ this.svg.select("path").datum(this.dates);
+ this.svg.select("path").attr("d", this.area);
+ this.svg.select(".x.axis").call(this.x_axis);
+ return this.svg.select(".y.axis").call(this.y_axis);
+ };
+
+ return ContributorsAuthorGraph;
+})(ContributorsGraph);
diff --git a/app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors_util.js b/app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors_util.js
new file mode 100644
index 00000000000..77135ad1f0e
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/graphs/show/stat_graph_contributors_util.js
@@ -0,0 +1,138 @@
+/* eslint-disable func-names, space-before-function-paren, object-shorthand, no-var, one-var, camelcase, one-var-declaration-per-line, comma-dangle, no-param-reassign, no-return-assign, quotes, prefer-arrow-callback, wrap-iife, consistent-return, no-unused-vars, max-len, no-cond-assign, no-else-return, max-len */
+import _ from 'underscore';
+
+export default {
+ parse_log: function(log) {
+ var by_author, by_email, data, entry, i, len, total, normalized_email;
+ total = {};
+ by_author = {};
+ by_email = {};
+ for (i = 0, len = log.length; i < len; i += 1) {
+ entry = log[i];
+ if (total[entry.date] == null) {
+ this.add_date(entry.date, total);
+ }
+ normalized_email = entry.author_email.toLowerCase();
+ data = by_author[entry.author_name] || by_email[normalized_email];
+ if (data == null) {
+ data = this.add_author(entry, by_author, by_email);
+ }
+ if (!data[entry.date]) {
+ this.add_date(entry.date, data);
+ }
+ this.store_data(entry, total[entry.date], data[entry.date]);
+ }
+ total = _.toArray(total);
+ by_author = _.toArray(by_author);
+ return {
+ total: total,
+ by_author: by_author
+ };
+ },
+ add_date: function(date, collection) {
+ collection[date] = {};
+ return collection[date].date = date;
+ },
+ add_author: function(author, by_author, by_email) {
+ var data, normalized_email;
+ data = {};
+ data.author_name = author.author_name;
+ data.author_email = author.author_email;
+ normalized_email = author.author_email.toLowerCase();
+ by_author[author.author_name] = data;
+ by_email[normalized_email] = data;
+ return data;
+ },
+ store_data: function(entry, total, by_author) {
+ this.store_commits(total, by_author);
+ this.store_additions(entry, total, by_author);
+ return this.store_deletions(entry, total, by_author);
+ },
+ store_commits: function(total, by_author) {
+ this.add(total, "commits", 1);
+ return this.add(by_author, "commits", 1);
+ },
+ add: function(collection, field, value) {
+ if (collection[field] == null) {
+ collection[field] = 0;
+ }
+ return collection[field] += value;
+ },
+ store_additions: function(entry, total, by_author) {
+ if (entry.additions == null) {
+ entry.additions = 0;
+ }
+ this.add(total, "additions", entry.additions);
+ return this.add(by_author, "additions", entry.additions);
+ },
+ store_deletions: function(entry, total, by_author) {
+ if (entry.deletions == null) {
+ entry.deletions = 0;
+ }
+ this.add(total, "deletions", entry.deletions);
+ return this.add(by_author, "deletions", entry.deletions);
+ },
+ get_total_data: function(parsed_log, field) {
+ var log, total_data;
+ log = parsed_log.total;
+ total_data = this.pick_field(log, field);
+ return _.sortBy(total_data, function(d) {
+ return d.date;
+ });
+ },
+ pick_field: function(log, field) {
+ var total_data;
+ total_data = [];
+ _.each(log, function(d) {
+ return total_data.push(_.pick(d, [field, 'date']));
+ });
+ return total_data;
+ },
+ get_author_data: function(parsed_log, field, date_range) {
+ var author_data, log;
+ if (date_range == null) {
+ date_range = null;
+ }
+ log = parsed_log.by_author;
+ author_data = [];
+ _.each(log, (function(_this) {
+ return function(log_entry) {
+ var parsed_log_entry;
+ parsed_log_entry = _this.parse_log_entry(log_entry, field, date_range);
+ if (!_.isEmpty(parsed_log_entry.dates)) {
+ return author_data.push(parsed_log_entry);
+ }
+ };
+ })(this));
+ return _.sortBy(author_data, function(d) {
+ return d[field];
+ }).reverse();
+ },
+ parse_log_entry: function(log_entry, field, date_range) {
+ var parsed_entry;
+ parsed_entry = {};
+ parsed_entry.author_name = log_entry.author_name;
+ parsed_entry.author_email = log_entry.author_email;
+ parsed_entry.dates = {};
+ parsed_entry.commits = parsed_entry.additions = parsed_entry.deletions = 0;
+ _.each(_.omit(log_entry, 'author_name', 'author_email'), (function(_this) {
+ return function(value, key) {
+ if (_this.in_range(value.date, date_range)) {
+ parsed_entry.dates[value.date] = value[field];
+ parsed_entry.commits += value.commits;
+ parsed_entry.additions += value.additions;
+ return parsed_entry.deletions += value.deletions;
+ }
+ };
+ })(this));
+ return parsed_entry;
+ },
+ in_range: function(date, date_range) {
+ var ref;
+ if (date_range === null || (date_range[0] <= (ref = new Date(date)) && ref <= date_range[1])) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+};
diff --git a/app/assets/javascripts/pages/projects/imports/show/index.js b/app/assets/javascripts/pages/projects/imports/show/index.js
index 378f7b3f38b..d5f92baf054 100644
--- a/app/assets/javascripts/pages/projects/imports/show/index.js
+++ b/app/assets/javascripts/pages/projects/imports/show/index.js
@@ -1,5 +1,5 @@
import ProjectImport from '~/project_import';
-export default () => {
+document.addEventListener('DOMContentLoaded', () => {
new ProjectImport(); // eslint-disable-line no-new
-};
+});
diff --git a/app/assets/javascripts/pages/projects/index.js b/app/assets/javascripts/pages/projects/index.js
index 9b1d52692a3..de1e13de7e9 100644
--- a/app/assets/javascripts/pages/projects/index.js
+++ b/app/assets/javascripts/pages/projects/index.js
@@ -1,7 +1,7 @@
import Project from './project';
import ShortcutsNavigation from '../../shortcuts_navigation';
-export default () => {
+document.addEventListener('DOMContentLoaded', () => {
new Project(); // eslint-disable-line no-new
new ShortcutsNavigation(); // eslint-disable-line no-new
-};
+});
diff --git a/app/assets/javascripts/pages/projects/init_blob.js b/app/assets/javascripts/pages/projects/init_blob.js
index 26f0ad46114..82143fa875a 100644
--- a/app/assets/javascripts/pages/projects/init_blob.js
+++ b/app/assets/javascripts/pages/projects/init_blob.js
@@ -3,6 +3,7 @@ import BlobLinePermalinkUpdater from '~/blob/blob_line_permalink_updater';
import ShortcutsNavigation from '~/shortcuts_navigation';
import ShortcutsBlob from '~/shortcuts_blob';
import BlobForkSuggestion from '~/blob/blob_fork_suggestion';
+import initBlobBundle from '~/blob_edit/blob_bundle';
export default () => {
new LineHighlighter(); // eslint-disable-line no-new
@@ -30,4 +31,6 @@ export default () => {
suggestionSections: document.querySelectorAll('.js-file-fork-suggestion-section'),
actionTextPieces: document.querySelectorAll('.js-file-fork-suggestion-section-action'),
}).init();
+
+ initBlobBundle();
};
diff --git a/app/assets/javascripts/pages/projects/issues/edit/index.js b/app/assets/javascripts/pages/projects/issues/edit/index.js
index 7f27f379d8c..ffc84dc106b 100644
--- a/app/assets/javascripts/pages/projects/issues/edit/index.js
+++ b/app/assets/javascripts/pages/projects/issues/edit/index.js
@@ -1,5 +1,3 @@
import initForm from '../form';
-export default () => {
- initForm();
-};
+document.addEventListener('DOMContentLoaded', initForm);
diff --git a/app/assets/javascripts/pages/projects/issues/new/index.js b/app/assets/javascripts/pages/projects/issues/new/index.js
index 7f27f379d8c..ffc84dc106b 100644
--- a/app/assets/javascripts/pages/projects/issues/new/index.js
+++ b/app/assets/javascripts/pages/projects/issues/new/index.js
@@ -1,5 +1,3 @@
import initForm from '../form';
-export default () => {
- initForm();
-};
+document.addEventListener('DOMContentLoaded', initForm);
diff --git a/app/assets/javascripts/pages/projects/issues/show/index.js b/app/assets/javascripts/pages/projects/issues/show/index.js
index da312c1f1b7..1e56aa58da2 100644
--- a/app/assets/javascripts/pages/projects/issues/show/index.js
+++ b/app/assets/javascripts/pages/projects/issues/show/index.js
@@ -1,13 +1,13 @@
-/* eslint-disable no-new */
-
import initIssuableSidebar from '~/init_issuable_sidebar';
import Issue from '~/issue';
import ShortcutsIssuable from '~/shortcuts_issuable';
import ZenMode from '~/zen_mode';
+import '~/notes/index';
+import '~/issue_show/index';
document.addEventListener('DOMContentLoaded', () => {
- new Issue();
- new ShortcutsIssuable();
- new ZenMode();
+ new Issue(); // eslint-disable-line no-new
+ new ShortcutsIssuable(); // eslint-disable-line no-new
+ new ZenMode(); // eslint-disable-line no-new
initIssuableSidebar();
});
diff --git a/app/assets/javascripts/pages/projects/jobs/show/index.js b/app/assets/javascripts/pages/projects/jobs/show/index.js
new file mode 100644
index 00000000000..3626f3ffec6
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/jobs/show/index.js
@@ -0,0 +1,3 @@
+import initJobDetails from '~/jobs/job_details_bundle';
+
+document.addEventListener('DOMContentLoaded', initJobDetails);
diff --git a/app/assets/javascripts/pages/projects/labels/edit/index.js b/app/assets/javascripts/pages/projects/labels/edit/index.js
index 72c5e4744ac..fa81ad914ba 100644
--- a/app/assets/javascripts/pages/projects/labels/edit/index.js
+++ b/app/assets/javascripts/pages/projects/labels/edit/index.js
@@ -1,3 +1,3 @@
import Labels from '~/labels';
-export default () => new Labels();
+document.addEventListener('DOMContentLoaded', () => new Labels());
diff --git a/app/assets/javascripts/pages/projects/labels/index/index.js b/app/assets/javascripts/pages/projects/labels/index/index.js
index 018345fa112..6e45de2a724 100644
--- a/app/assets/javascripts/pages/projects/labels/index/index.js
+++ b/app/assets/javascripts/pages/projects/labels/index/index.js
@@ -1,3 +1,3 @@
import initLabels from '~/init_labels';
-export default initLabels;
+document.addEventListener('DOMContentLoaded', initLabels);
diff --git a/app/assets/javascripts/pages/projects/labels/new/index.js b/app/assets/javascripts/pages/projects/labels/new/index.js
index 72c5e4744ac..fa81ad914ba 100644
--- a/app/assets/javascripts/pages/projects/labels/new/index.js
+++ b/app/assets/javascripts/pages/projects/labels/new/index.js
@@ -1,3 +1,3 @@
import Labels from '~/labels';
-export default () => new Labels();
+document.addEventListener('DOMContentLoaded', () => new Labels());
diff --git a/app/assets/javascripts/pages/projects/merge_requests/creations/diffs/index.js b/app/assets/javascripts/pages/projects/merge_requests/creations/index.js
index 734d01ae6f2..febfecebbd2 100644
--- a/app/assets/javascripts/pages/projects/merge_requests/creations/diffs/index.js
+++ b/app/assets/javascripts/pages/projects/merge_requests/creations/index.js
@@ -1,3 +1,3 @@
import initMergeRequest from '~/pages/projects/merge_requests/init_merge_request';
-export default initMergeRequest;
+document.addEventListener('DOMContentLoaded', initMergeRequest);
diff --git a/app/assets/javascripts/pages/projects/merge_requests/creations/new/index.js b/app/assets/javascripts/pages/projects/merge_requests/creations/new/index.js
index ccd0b54c5ed..6c9afddefac 100644
--- a/app/assets/javascripts/pages/projects/merge_requests/creations/new/index.js
+++ b/app/assets/javascripts/pages/projects/merge_requests/creations/new/index.js
@@ -1,7 +1,8 @@
import Compare from '~/compare';
import MergeRequest from '~/merge_request';
+import initPipelines from '~/commit/pipelines/pipelines_bundle';
-export default () => {
+document.addEventListener('DOMContentLoaded', () => {
const mrNewCompareNode = document.querySelector('.js-merge-request-new-compare');
if (mrNewCompareNode) {
new Compare({ // eslint-disable-line no-new
@@ -14,5 +15,6 @@ export default () => {
new MergeRequest({ // eslint-disable-line no-new
action: mrNewSubmitNode.dataset.mrSubmitAction,
});
+ initPipelines();
}
-};
+});
diff --git a/app/assets/javascripts/pages/projects/merge_requests/edit/index.js b/app/assets/javascripts/pages/projects/merge_requests/edit/index.js
index 734d01ae6f2..febfecebbd2 100644
--- a/app/assets/javascripts/pages/projects/merge_requests/edit/index.js
+++ b/app/assets/javascripts/pages/projects/merge_requests/edit/index.js
@@ -1,3 +1,3 @@
import initMergeRequest from '~/pages/projects/merge_requests/init_merge_request';
-export default initMergeRequest;
+document.addEventListener('DOMContentLoaded', initMergeRequest);
diff --git a/app/assets/javascripts/pages/projects/merge_requests/show/index.js b/app/assets/javascripts/pages/projects/merge_requests/show/index.js
new file mode 100644
index 00000000000..322d02f93db
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/merge_requests/show/index.js
@@ -0,0 +1,30 @@
+import MergeRequest from '~/merge_request';
+import ZenMode from '~/zen_mode';
+import initNotes from '~/init_notes';
+import initIssuableSidebar from '~/init_issuable_sidebar';
+import initDiffNotes from '~/diff_notes/diff_notes_bundle';
+import ShortcutsIssuable from '~/shortcuts_issuable';
+import Diff from '~/diff';
+import { handleLocationHash } from '~/lib/utils/common_utils';
+import howToMerge from '~/how_to_merge';
+import initPipelines from '~/commit/pipelines/pipelines_bundle';
+
+document.addEventListener('DOMContentLoaded', () => {
+ new Diff(); // eslint-disable-line no-new
+ new ZenMode(); // eslint-disable-line no-new
+
+ initIssuableSidebar();
+ initNotes();
+ initDiffNotes();
+ initPipelines();
+
+ const mrShowNode = document.querySelector('.merge-request');
+
+ window.mergeRequest = new MergeRequest({
+ action: mrShowNode.dataset.mrAction,
+ });
+
+ new ShortcutsIssuable(true); // eslint-disable-line no-new
+ handleLocationHash();
+ howToMerge();
+});
diff --git a/app/assets/javascripts/pages/projects/milestones/edit/index.js b/app/assets/javascripts/pages/projects/milestones/edit/index.js
index 10e3979a36e..9a4ebf9890d 100644
--- a/app/assets/javascripts/pages/projects/milestones/edit/index.js
+++ b/app/assets/javascripts/pages/projects/milestones/edit/index.js
@@ -1,3 +1,3 @@
import initForm from '../../../../shared/milestones/form';
-export default () => initForm();
+document.addEventListener('DOMContentLoaded', () => initForm());
diff --git a/app/assets/javascripts/pages/projects/milestones/index/index.js b/app/assets/javascripts/pages/projects/milestones/index/index.js
index 8fb4d83d8a3..38789365a67 100644
--- a/app/assets/javascripts/pages/projects/milestones/index/index.js
+++ b/app/assets/javascripts/pages/projects/milestones/index/index.js
@@ -1,3 +1,3 @@
import milestones from '~/pages/milestones/shared';
-export default milestones;
+document.addEventListener('DOMContentLoaded', milestones);
diff --git a/app/assets/javascripts/pages/projects/milestones/new/index.js b/app/assets/javascripts/pages/projects/milestones/new/index.js
index 10e3979a36e..9a4ebf9890d 100644
--- a/app/assets/javascripts/pages/projects/milestones/new/index.js
+++ b/app/assets/javascripts/pages/projects/milestones/new/index.js
@@ -1,3 +1,3 @@
import initForm from '../../../../shared/milestones/form';
-export default () => initForm();
+document.addEventListener('DOMContentLoaded', () => initForm());
diff --git a/app/assets/javascripts/pages/projects/milestones/show/index.js b/app/assets/javascripts/pages/projects/milestones/show/index.js
index 35b5c9c2ced..84a52421598 100644
--- a/app/assets/javascripts/pages/projects/milestones/show/index.js
+++ b/app/assets/javascripts/pages/projects/milestones/show/index.js
@@ -1,7 +1,7 @@
import initMilestonesShow from '~/pages/milestones/shared/init_milestones_show';
import milestones from '~/pages/milestones/shared';
-export default () => {
+document.addEventListener('DOMContentLoaded', () => {
initMilestonesShow();
milestones();
-};
+});
diff --git a/app/assets/javascripts/pages/projects/new/index.js b/app/assets/javascripts/pages/projects/new/index.js
index 71c49deb9d0..ea6fd961393 100644
--- a/app/assets/javascripts/pages/projects/new/index.js
+++ b/app/assets/javascripts/pages/projects/new/index.js
@@ -2,8 +2,8 @@ import ProjectNew from '../shared/project_new';
import initProjectVisibilitySelector from '../../../project_visibility';
import initProjectNew from '../../../projects/project_new';
-export default () => {
+document.addEventListener('DOMContentLoaded', () => {
new ProjectNew(); // eslint-disable-line no-new
initProjectVisibilitySelector();
initProjectNew.bindEvents();
-};
+});
diff --git a/app/assets/javascripts/pages/projects/pipeline_schedules/create/index.js b/app/assets/javascripts/pages/projects/pipeline_schedules/create/index.js
new file mode 100644
index 00000000000..d65be6bc69e
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/pipeline_schedules/create/index.js
@@ -0,0 +1,3 @@
+import initForm from '../shared/init_form';
+
+document.addEventListener('DOMContentLoaded', initForm);
diff --git a/app/assets/javascripts/pages/projects/pipeline_schedules/edit/index.js b/app/assets/javascripts/pages/projects/pipeline_schedules/edit/index.js
new file mode 100644
index 00000000000..d65be6bc69e
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/pipeline_schedules/edit/index.js
@@ -0,0 +1,3 @@
+import initForm from '../shared/init_form';
+
+document.addEventListener('DOMContentLoaded', initForm);
diff --git a/app/assets/javascripts/pages/projects/pipeline_schedules/index/index.js b/app/assets/javascripts/pages/projects/pipeline_schedules/index/index.js
new file mode 100644
index 00000000000..544360dcd51
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/pipeline_schedules/index/index.js
@@ -0,0 +1,12 @@
+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');
+ },
+}));
diff --git a/app/assets/javascripts/pages/projects/pipeline_schedules/new/index.js b/app/assets/javascripts/pages/projects/pipeline_schedules/new/index.js
new file mode 100644
index 00000000000..d65be6bc69e
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/pipeline_schedules/new/index.js
@@ -0,0 +1,3 @@
+import initForm from '../shared/init_form';
+
+document.addEventListener('DOMContentLoaded', initForm);
diff --git a/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/interval_pattern_input.vue b/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/interval_pattern_input.vue
new file mode 100644
index 00000000000..2d18fa2044b
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/interval_pattern_input.vue
@@ -0,0 +1,160 @@
+<script>
+ import _ from 'underscore';
+
+ export default {
+ props: {
+ initialCronInterval: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ },
+ data() {
+ return {
+ inputNameAttribute: 'schedule[cron]',
+ cronInterval: this.initialCronInterval,
+ cronIntervalPresets: {
+ everyDay: '0 4 * * *',
+ everyWeek: '0 4 * * 0',
+ everyMonth: '0 4 1 * *',
+ },
+ cronSyntaxUrl: 'https://en.wikipedia.org/wiki/Cron',
+ customInputEnabled: false,
+ };
+ },
+ computed: {
+ intervalIsPreset() {
+ return _.contains(this.cronIntervalPresets, this.cronInterval);
+ },
+ // The text input is editable when there's a custom interval, or when it's
+ // a preset interval and the user clicks the 'custom' radio button
+ isEditable() {
+ return !!(this.customInputEnabled || !this.intervalIsPreset);
+ },
+ },
+ watch: {
+ cronInterval() {
+ // updates field validation state when model changes, as
+ // glFieldError only updates on input.
+ this.$nextTick(() => {
+ gl.pipelineScheduleFieldErrors.updateFormValidityState();
+ });
+ },
+ },
+ created() {
+ if (this.intervalIsPreset) {
+ this.enableCustomInput = false;
+ }
+ },
+ methods: {
+ toggleCustomInput(shouldEnable) {
+ this.customInputEnabled = shouldEnable;
+
+ if (shouldEnable) {
+ // We need to change the value so other radios don't remain selected
+ // because the model (cronInterval) hasn't changed. The server trims it.
+ this.cronInterval = `${this.cronInterval} `;
+ }
+ },
+ },
+ };
+</script>
+
+<template>
+ <div class="interval-pattern-form-group">
+ <div class="cron-preset-radio-input">
+ <input
+ id="custom"
+ class="label-light"
+ type="radio"
+ :name="inputNameAttribute"
+ :value="cronInterval"
+ :checked="isEditable"
+ @click="toggleCustomInput(true)"
+ />
+
+ <label for="custom">
+ {{ s__('PipelineSheduleIntervalPattern|Custom') }}
+ </label>
+
+ <span class="cron-syntax-link-wrap">
+ (<a
+ :href="cronSyntaxUrl"
+ target="_blank"
+ >
+ {{ __('Cron syntax') }}
+ </a>)
+ </span>
+ </div>
+
+ <div class="cron-preset-radio-input">
+ <input
+ id="every-day"
+ class="label-light"
+ type="radio"
+ v-model="cronInterval"
+ :name="inputNameAttribute"
+ :value="cronIntervalPresets.everyDay"
+ @click="toggleCustomInput(false)"
+ />
+
+ <label
+ class="label-light"
+ for="every-day"
+ >
+ {{ __('Every day (at 4:00am)') }}
+ </label>
+ </div>
+
+ <div class="cron-preset-radio-input">
+ <input
+ id="every-week"
+ class="label-light"
+ type="radio"
+ v-model="cronInterval"
+ :name="inputNameAttribute"
+ :value="cronIntervalPresets.everyWeek"
+ @click="toggleCustomInput(false)"
+ />
+
+ <label
+ class="label-light"
+ for="every-week"
+ >
+ {{ __('Every week (Sundays at 4:00am)') }}
+ </label>
+ </div>
+
+ <div class="cron-preset-radio-input">
+ <input
+ id="every-month"
+ class="label-light"
+ type="radio"
+ v-model="cronInterval"
+ :name="inputNameAttribute"
+ :value="cronIntervalPresets.everyMonth"
+ @click="toggleCustomInput(false)"
+ />
+
+ <label
+ class="label-light"
+ for="every-month"
+ >
+ {{ __('Every month (on the 1st at 4:00am)') }}
+ </label>
+ </div>
+
+ <div class="cron-interval-input-wrapper">
+ <input
+ id="schedule_cron"
+ class="form-control inline cron-interval-input"
+ type="text"
+ :placeholder="__('Define a custom pattern with cron syntax')"
+ required="true"
+ v-model="cronInterval"
+ :name="inputNameAttribute"
+ :disabled="!isEditable"
+ />
+ </div>
+ </div>
+</template>
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
new file mode 100644
index 00000000000..77508e62cef
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/pipeline_schedules_callout.vue
@@ -0,0 +1,67 @@
+<script>
+ import Vue from 'vue';
+ import Cookies from 'js-cookie';
+ import Translate from '../../../../../vue_shared/translate';
+ import illustrationSvg from '../icons/intro_illustration.svg';
+
+ Vue.use(Translate);
+
+ const cookieKey = 'pipeline_schedules_callout_dismissed';
+
+ export default {
+ name: 'PipelineSchedulesCallout',
+ data() {
+ return {
+ docsUrl: document.getElementById('pipeline-schedules-callout').dataset.docsUrl,
+ calloutDismissed: Cookies.get(cookieKey) === 'true',
+ };
+ },
+ created() {
+ this.illustrationSvg = illustrationSvg;
+ },
+ methods: {
+ dismissCallout() {
+ this.calloutDismissed = true;
+ Cookies.set(cookieKey, this.calloutDismissed, { expires: 365 });
+ },
+ },
+ };
+</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">
+ <i
+ aria-hidden="true"
+ class="fa fa-times">
+ </i>
+ </button>
+ <div
+ class="svg-container"
+ v-html="illustrationSvg">
+ </div>
+ <div class="user-callout-copy">
+ <h4>{{ __('Scheduling Pipelines') }}</h4>
+ <p>
+ {{ __(`The pipelines schedule runs pipelines in the future,
+repeatedly, for specific branches or tags.
+Those scheduled pipelines will inherit limited project access based on their associated user.`) }}
+ </p>
+ <p> {{ __('Learn more in the') }}
+ <a
+ :href="docsUrl"
+ target="_blank"
+ rel="nofollow"
+ >
+ {{ s__('Learn more in the|pipeline schedules documentation') }}</a>.
+ <!-- oneline to prevent extra space before period -->
+ </p>
+ </div>
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/target_branch_dropdown.js b/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/target_branch_dropdown.js
new file mode 100644
index 00000000000..0c3926d76b5
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/target_branch_dropdown.js
@@ -0,0 +1,52 @@
+export default class TargetBranchDropdown {
+ constructor() {
+ this.$dropdown = $('.js-target-branch-dropdown');
+ this.$dropdownToggle = this.$dropdown.find('.dropdown-toggle-text');
+ this.$input = $('#schedule_ref');
+ this.initDefaultBranch();
+ this.initDropdown();
+ }
+
+ initDropdown() {
+ this.$dropdown.glDropdown({
+ data: this.formatBranchesList(),
+ filterable: true,
+ selectable: true,
+ toggleLabel: item => item.name,
+ search: {
+ fields: ['name'],
+ },
+ clicked: cfg => this.updateInputValue(cfg),
+ text: item => item.name,
+ });
+
+ this.setDropdownToggle();
+ }
+
+ formatBranchesList() {
+ return this.$dropdown.data('data')
+ .map(val => ({ name: val }));
+ }
+
+ setDropdownToggle() {
+ const initialValue = this.$input.val();
+
+ this.$dropdownToggle.text(initialValue);
+ }
+
+ initDefaultBranch() {
+ const initialValue = this.$input.val();
+ const defaultBranch = this.$dropdown.data('defaultBranch');
+
+ if (!initialValue) {
+ this.$input.val(defaultBranch);
+ }
+ }
+
+ updateInputValue({ selectedObj, e }) {
+ e.preventDefault();
+
+ this.$input.val(selectedObj.name);
+ gl.pipelineScheduleFieldErrors.updateFormValidityState();
+ }
+}
diff --git a/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/timezone_dropdown.js b/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/timezone_dropdown.js
new file mode 100644
index 00000000000..95ed9c7dc21
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/pipeline_schedules/shared/components/timezone_dropdown.js
@@ -0,0 +1,66 @@
+/* eslint-disable class-methods-use-this */
+
+const defaultTimezone = 'UTC';
+
+export default class TimezoneDropdown {
+ constructor() {
+ this.$dropdown = $('.js-timezone-dropdown');
+ this.$dropdownToggle = this.$dropdown.find('.dropdown-toggle-text');
+ this.$input = $('#schedule_cron_timezone');
+ this.timezoneData = this.$dropdown.data('data');
+ this.initDefaultTimezone();
+ this.initDropdown();
+ }
+
+ initDropdown() {
+ this.$dropdown.glDropdown({
+ data: this.timezoneData,
+ filterable: true,
+ selectable: true,
+ toggleLabel: item => item.name,
+ search: {
+ fields: ['name'],
+ },
+ clicked: cfg => this.updateInputValue(cfg),
+ text: item => this.formatTimezone(item),
+ });
+
+ this.setDropdownToggle();
+ }
+
+ formatUtcOffset(offset) {
+ let prefix = '';
+
+ if (offset > 0) {
+ prefix = '+';
+ } else if (offset < 0) {
+ prefix = '-';
+ }
+
+ return `${prefix} ${Math.abs(offset / 3600)}`;
+ }
+
+ formatTimezone(item) {
+ return `[UTC ${this.formatUtcOffset(item.offset)}] ${item.name}`;
+ }
+
+ initDefaultTimezone() {
+ const initialValue = this.$input.val();
+
+ if (!initialValue) {
+ this.$input.val(defaultTimezone);
+ }
+ }
+
+ setDropdownToggle() {
+ const initialValue = this.$input.val();
+
+ this.$dropdownToggle.text(initialValue);
+ }
+
+ updateInputValue({ selectedObj, e }) {
+ e.preventDefault();
+ this.$input.val(selectedObj.identifier);
+ gl.pipelineScheduleFieldErrors.updateFormValidityState();
+ }
+}
diff --git a/app/assets/javascripts/pages/projects/pipeline_schedules/shared/icons/intro_illustration.svg b/app/assets/javascripts/pages/projects/pipeline_schedules/shared/icons/intro_illustration.svg
new file mode 100644
index 00000000000..26d1ff97b3e
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/pipeline_schedules/shared/icons/intro_illustration.svg
@@ -0,0 +1 @@
+<svg width="140" height="102" viewBox="0 0 140 102" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><title>illustration</title><defs><rect id="a" width="12.033" height="40.197" rx="3"/><rect id="b" width="12.033" height="40.197" rx="3"/></defs><g fill="none" fill-rule="evenodd"><g transform="translate(-.446)"><path d="M91.747 35.675v-6.039a2.996 2.996 0 0 0-2.999-3.005H54.635a2.997 2.997 0 0 0-2.999 3.005v6.039H40.092a3.007 3.007 0 0 0-2.996 3.005v34.187a2.995 2.995 0 0 0 2.996 3.005h11.544V79.9a2.996 2.996 0 0 0 2.999 3.005h34.113a2.997 2.997 0 0 0 2.999-3.005v-4.03h11.544a3.007 3.007 0 0 0 2.996-3.004V38.68a2.995 2.995 0 0 0-2.996-3.005H91.747z" stroke="#B5A7DD" stroke-width="2"/><rect stroke="#E5E5E5" stroke-width="2" fill="#FFF" x="21.556" y="38.69" width="98.27" height="34.167" rx="3"/><path d="M121.325 38.19c.55 0 .995.444.995 1.002 0 .554-.453 1.003-.995 1.003h-4.039a1.004 1.004 0 0 1 0-2.006h4.039zm9.044 0c.55 0 .996.444.996 1.002 0 .554-.454 1.003-.996 1.003h-4.038a1.004 1.004 0 0 1 0-2.006h4.038zm9.044 0c.55 0 .996.444.996 1.002 0 .554-.453 1.003-.996 1.003h-4.038a1.004 1.004 0 0 1 0-2.006h4.038zM121.325 71.854a1.004 1.004 0 0 1 0 2.006h-4.039a1.004 1.004 0 0 1 0-2.006h4.039zm9.044 0a1.004 1.004 0 0 1 0 2.006h-4.038a1.004 1.004 0 0 1 0-2.006h4.038zm9.044 0a1.004 1.004 0 0 1 0 2.006h-4.038a1.004 1.004 0 0 1 0-2.006h4.038z" fill="#E5E5E5"/><g transform="translate(110.3 35.675)"><use fill="#FFF" xlink:href="#a"/><rect stroke="#FDE5D8" stroke-width="2" x="1" y="1" width="10.033" height="38.197" rx="3"/><ellipse fill="#FC8A51" cx="6.017" cy="9.547" rx="1.504" ry="1.507"/><ellipse fill="#FC8A51" cx="6.017" cy="20.099" rx="1.504" ry="1.507"/><ellipse fill="#FC8A51" cx="6.017" cy="30.65" rx="1.504" ry="1.507"/></g><path d="M6.008 38.19c.55 0 .996.444.996 1.002 0 .554-.454 1.003-.996 1.003H1.97a1.004 1.004 0 0 1 0-2.006h4.038zm9.044 0c.55 0 .996.444.996 1.002 0 .554-.453 1.003-.996 1.003h-4.038a1.004 1.004 0 0 1 0-2.006h4.038zm9.045 0c.55 0 .995.444.995 1.002 0 .554-.453 1.003-.995 1.003h-4.039a1.004 1.004 0 0 1 0-2.006h4.039zM6.008 71.854a1.004 1.004 0 0 1 0 2.006H1.97a1.004 1.004 0 0 1 0-2.006h4.038zm9.044 0a1.004 1.004 0 0 1 0 2.006h-4.038a1.004 1.004 0 0 1 0-2.006h4.038zm9.045 0a1.004 1.004 0 0 1 0 2.006h-4.039a1.004 1.004 0 0 1 0-2.006h4.039z" fill="#E5E5E5"/><g transform="translate(19.05 35.675)"><use fill="#FFF" xlink:href="#b"/><rect stroke="#FDE5D8" stroke-width="2" x="1" y="1" width="10.033" height="38.197" rx="3"/><ellipse fill="#FC8A51" cx="6.017" cy="10.049" rx="1.504" ry="1.507"/><ellipse fill="#FC8A51" cx="6.017" cy="20.601" rx="1.504" ry="1.507"/><ellipse fill="#FC8A51" cx="6.017" cy="31.153" rx="1.504" ry="1.507"/></g><g transform="translate(47.096)"><g transform="translate(7.05)"><ellipse fill="#FC8A51" cx="17.548" cy="5.025" rx="4.512" ry="4.522"/><rect stroke="#B5A7DD" stroke-width="2" fill="#FFF" x="13.036" y="4.02" width="9.025" height="20.099" rx="1.5"/><rect stroke="#FDE5D8" stroke-width="2" fill="#FFF" y="4.02" width="35.096" height="4.02" rx="2.01"/><rect stroke="#6B4FBB" stroke-width="2" fill="#FFF" x="4.512" y="18.089" width="26.072" height="17.084" rx="1.5"/></g><rect stroke="#6B4FBB" stroke-width="2" fill="#FFF" transform="rotate(-45 43.117 35.117)" x="38.168" y="31.416" width="9.899" height="7.403" rx="3.702"/><ellipse stroke="#6B4FBB" stroke-width="2" fill="#FFF" cx="25" cy="55" rx="25" ry="25"/><ellipse stroke="#6B4FBB" stroke-width="2" fill="#FFF" cx="25" cy="55" rx="21" ry="21"/><rect stroke="#6B4FBB" stroke-width="2" fill="#FFF" x="43.05" y="53.281" width="2.95" height="1.538" rx=".769"/><rect stroke="#6B4FBB" stroke-width="2" fill="#FFF" x="4.305" y="53.281" width="2.95" height="1.538" rx=".769"/><rect stroke="#6B4FBB" stroke-width="2" fill="#FFF" transform="rotate(90 25.153 74.422)" x="23.677" y="73.653" width="2.95" height="1.538" rx=".769"/><rect stroke="#6B4FBB" stroke-width="2" fill="#FFF" transform="rotate(90 25.153 35.51)" x="23.844" y="34.742" width="2.616" height="1.538" rx=".769"/><path d="M13.362 42.502c-.124-.543.198-.854.74-.69l2.321.704c.533.161.643.592.235.972l-.22.206 7.06 7.572a1.002 1.002 0 1 1-1.467 1.368l-7.06-7.573-.118.11c-.402.375-.826.248-.952-.304l-.54-2.365zM21.606 67.576c-.408.38-.84.255-.968-.295l-.551-2.363c-.127-.542.191-.852.725-.69l.288.089 3.027-9.901a1.002 1.002 0 1 1 1.918.586l-3.027 9.901.154.047c.525.16.627.592.213.977l-1.779 1.65z" fill="#FC8A51"/><ellipse stroke="#6B4FBB" stroke-width="2" fill="#FFF" cx="25.099" cy="54.768" rx="2.507" ry="2.512"/></g></g><path d="M52.697 96.966a1.004 1.004 0 0 1 2.006 0v4.038a1.004 1.004 0 0 1-2.006 0v-4.038zm0-9.044a1.004 1.004 0 0 1 2.006 0v4.038a1.004 1.004 0 0 1-2.006 0v-4.038zM86.29 96.966c0-.55.444-.996 1.002-.996.554 0 1.003.454 1.003.996v4.038a1.004 1.004 0 0 1-2.006 0v-4.038zm0-9.044c0-.55.444-.996 1.002-.996.554 0 1.003.453 1.003.996v4.038a1.004 1.004 0 0 1-2.006 0v-4.038z" fill="#E5E5E5"/></g></svg> \ No newline at end of file
diff --git a/app/assets/javascripts/pages/projects/pipeline_schedules/shared/init_form.js b/app/assets/javascripts/pages/projects/pipeline_schedules/shared/init_form.js
new file mode 100644
index 00000000000..cfd30d6053f
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/pipeline_schedules/shared/init_form.js
@@ -0,0 +1,49 @@
+import Vue from 'vue';
+import Translate from '../../../../vue_shared/translate';
+import GlFieldErrors from '../../../../gl_field_errors';
+import intervalPatternInput from './components/interval_pattern_input.vue';
+import TimezoneDropdown from './components/timezone_dropdown';
+import TargetBranchDropdown from './components/target_branch_dropdown';
+import setupNativeFormVariableList from '../../../../ci_variable_list/native_form_variable_list';
+
+Vue.use(Translate);
+
+function initIntervalPatternInput() {
+ const intervalPatternMount = document.getElementById('interval-pattern-input');
+ const initialCronInterval = intervalPatternMount ? intervalPatternMount.dataset.initialInterval : '';
+
+ return new Vue({
+ el: intervalPatternMount,
+ components: {
+ intervalPatternInput,
+ },
+ render(createElement) {
+ return createElement('interval-pattern-input', {
+ props: {
+ initialCronInterval,
+ },
+ });
+ },
+ });
+}
+
+export default () => {
+ /* Most of the form is written in haml, but for fields with more complex behaviors,
+ * you should mount individual Vue components here. If at some point components need
+ * to share state, it may make sense to refactor the whole form to Vue */
+
+ initIntervalPatternInput();
+
+ // Initialize non-Vue JS components in the form
+
+ const formElement = document.getElementById('new-pipeline-schedule-form');
+
+ gl.timezoneDropdown = new TimezoneDropdown();
+ gl.targetBranchDropdown = new TargetBranchDropdown();
+ gl.pipelineScheduleFieldErrors = new GlFieldErrors(formElement);
+
+ setupNativeFormVariableList({
+ container: $('.js-ci-variable-list-section'),
+ formField: 'schedule',
+ });
+};
diff --git a/app/assets/javascripts/pages/projects/pipeline_schedules/update/index.js b/app/assets/javascripts/pages/projects/pipeline_schedules/update/index.js
new file mode 100644
index 00000000000..d65be6bc69e
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/pipeline_schedules/update/index.js
@@ -0,0 +1,3 @@
+import initForm from '../shared/init_form';
+
+document.addEventListener('DOMContentLoaded', initForm);
diff --git a/app/assets/javascripts/pages/projects/pipelines/builds/index.js b/app/assets/javascripts/pages/projects/pipelines/builds/index.js
index 060a78b427e..fbe9824c34b 100644
--- a/app/assets/javascripts/pages/projects/pipelines/builds/index.js
+++ b/app/assets/javascripts/pages/projects/pipelines/builds/index.js
@@ -1,16 +1,3 @@
-import Pipelines from '../../../../pipelines';
+import initPipelines from '../init_pipelines';
-export default () => {
- const { controllerAction } = document.querySelector('.js-pipeline-container').dataset;
- const pipelineStatusUrl = `${document.querySelector('.js-pipeline-tab-link a').getAttribute('href')}/status.json`;
-
- new Pipelines({ // eslint-disable-line no-new
- initTabs: true,
- pipelineStatusUrl,
- tabsOptions: {
- action: controllerAction,
- defaultAction: 'pipelines',
- parentEl: '.pipelines-tabs',
- },
- });
-};
+document.addEventListener('DOMContentLoaded', initPipelines);
diff --git a/app/assets/javascripts/pages/projects/pipelines/charts/index.js b/app/assets/javascripts/pages/projects/pipelines/charts/index.js
new file mode 100644
index 00000000000..bb92f4e1459
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/pipelines/charts/index.js
@@ -0,0 +1,56 @@
+import Chart from 'chart.js';
+
+const options = {
+ scaleOverlay: true,
+ responsive: true,
+ maintainAspectRatio: false,
+};
+
+const buildChart = (chartScope) => {
+ const data = {
+ labels: chartScope.labels,
+ datasets: [{
+ fillColor: '#707070',
+ strokeColor: '#707070',
+ pointColor: '#707070',
+ pointStrokeColor: '#EEE',
+ data: chartScope.totalValues,
+ },
+ {
+ fillColor: '#1aaa55',
+ strokeColor: '#1aaa55',
+ pointColor: '#1aaa55',
+ pointStrokeColor: '#fff',
+ data: chartScope.successValues,
+ },
+ ],
+ };
+ const ctx = $(`#${chartScope.scope}Chart`).get(0).getContext('2d');
+
+ new Chart(ctx).Line(data, options);
+};
+
+document.addEventListener('DOMContentLoaded', () => {
+ const chartTimesData = JSON.parse(document.getElementById('pipelinesTimesChartsData').innerHTML);
+ const chartsData = JSON.parse(document.getElementById('pipelinesChartsData').innerHTML);
+ const data = {
+ labels: chartTimesData.labels,
+ datasets: [{
+ fillColor: 'rgba(220,220,220,0.5)',
+ strokeColor: 'rgba(220,220,220,1)',
+ barStrokeWidth: 1,
+ barValueSpacing: 1,
+ barDatasetSpacing: 1,
+ data: chartTimesData.values,
+ }],
+ };
+
+ if (window.innerWidth < 768) {
+ // Scale fonts if window width lower than 768px (iPad portrait)
+ options.scaleFontSize = 8;
+ }
+
+ new Chart($('#build_timesChart').get(0).getContext('2d')).Bar(data, options);
+
+ chartsData.forEach(scope => buildChart(scope));
+});
diff --git a/app/assets/javascripts/pages/projects/pipelines/failures/index.js b/app/assets/javascripts/pages/projects/pipelines/failures/index.js
new file mode 100644
index 00000000000..fbe9824c34b
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/pipelines/failures/index.js
@@ -0,0 +1,3 @@
+import initPipelines from '../init_pipelines';
+
+document.addEventListener('DOMContentLoaded', initPipelines);
diff --git a/app/assets/javascripts/pages/projects/pipelines/init_pipelines.js b/app/assets/javascripts/pages/projects/pipelines/init_pipelines.js
new file mode 100644
index 00000000000..94dfeb96e8c
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/pipelines/init_pipelines.js
@@ -0,0 +1,16 @@
+import Pipelines from '~/pipelines';
+
+export default () => {
+ const { controllerAction } = document.querySelector('.js-pipeline-container').dataset;
+ const pipelineStatusUrl = `${document.querySelector('.js-pipeline-tab-link a').getAttribute('href')}/status.json`;
+
+ new Pipelines({ // eslint-disable-line no-new
+ initTabs: true,
+ pipelineStatusUrl,
+ tabsOptions: {
+ action: controllerAction,
+ defaultAction: 'pipelines',
+ parentEl: '.pipelines-tabs',
+ },
+ });
+};
diff --git a/app/assets/javascripts/pages/projects/pipelines/new/index.js b/app/assets/javascripts/pages/projects/pipelines/new/index.js
index c54cc62bf05..da20bd995e9 100644
--- a/app/assets/javascripts/pages/projects/pipelines/new/index.js
+++ b/app/assets/javascripts/pages/projects/pipelines/new/index.js
@@ -1,5 +1,5 @@
-import NewBranchForm from '../../../../new_branch_form';
+import NewBranchForm from '~/new_branch_form';
-export default () => {
+document.addEventListener('DOMContentLoaded', () => {
new NewBranchForm($('.js-new-pipeline-form')); // eslint-disable-line no-new
-};
+});
diff --git a/app/assets/javascripts/pages/projects/pipelines/show/index.js b/app/assets/javascripts/pages/projects/pipelines/show/index.js
new file mode 100644
index 00000000000..fbe9824c34b
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/pipelines/show/index.js
@@ -0,0 +1,3 @@
+import initPipelines from '../init_pipelines';
+
+document.addEventListener('DOMContentLoaded', initPipelines);
diff --git a/app/assets/javascripts/pages/projects/project.js b/app/assets/javascripts/pages/projects/project.js
index 863dac0d20e..d23ad9a92f4 100644
--- a/app/assets/javascripts/pages/projects/project.js
+++ b/app/assets/javascripts/pages/projects/project.js
@@ -50,7 +50,7 @@ export default class Project {
Project.projectSelectDropdown();
}
- static projectSelectDropdown () {
+ static projectSelectDropdown() {
projectSelect();
$('.project-item-select').on('click', e => Project.changeProject($(e.currentTarget).val()));
}
@@ -71,7 +71,7 @@ export default class Project {
selected = $dropdown.data('selected');
return $dropdown.glDropdown({
data(term, callback) {
- axios.get($dropdown.data('refs-url'), {
+ axios.get($dropdown.data('refsUrl'), {
params: {
ref: $dropdown.data('ref'),
search: term,
@@ -84,8 +84,8 @@ export default class Project {
filterable: true,
filterRemote: true,
filterByText: true,
- inputFieldName: $dropdown.data('input-field-name'),
- fieldName: $dropdown.data('field-name'),
+ inputFieldName: $dropdown.data('inputFieldName'),
+ fieldName: $dropdown.data('fieldName'),
renderRow: function(ref) {
var li = refListItem.cloneNode(false);
diff --git a/app/assets/javascripts/pages/projects/project_members/index.js b/app/assets/javascripts/pages/projects/project_members/index.js
index f4643e7dba0..adbe744290a 100644
--- a/app/assets/javascripts/pages/projects/project_members/index.js
+++ b/app/assets/javascripts/pages/projects/project_members/index.js
@@ -3,10 +3,10 @@ import UsersSelect from '../../../users_select';
import groupsSelect from '../../../groups_select';
import Members from '../../../members';
-export default () => {
+document.addEventListener('DOMContentLoaded', () => {
memberExpirationDate('.js-access-expiration-date-groups');
groupsSelect();
memberExpirationDate();
new Members(); // eslint-disable-line no-new
new UsersSelect(); // eslint-disable-line no-new
-};
+});
diff --git a/app/assets/javascripts/pages/projects/releases/edit/index.js b/app/assets/javascripts/pages/projects/releases/edit/index.js
index 3d997cdfff0..0bf53a8de09 100644
--- a/app/assets/javascripts/pages/projects/releases/edit/index.js
+++ b/app/assets/javascripts/pages/projects/releases/edit/index.js
@@ -1,3 +1,3 @@
import initForm from '~/pages/projects/init_form';
-export default initForm($('.release-form'));
+document.addEventListener('DOMContentLoaded', () => initForm($('.release-form')));
diff --git a/app/assets/javascripts/pages/projects/services/edit/index.js b/app/assets/javascripts/pages/projects/services/edit/index.js
new file mode 100644
index 00000000000..ba4b271f09e
--- /dev/null
+++ b/app/assets/javascripts/pages/projects/services/edit/index.js
@@ -0,0 +1,13 @@
+import IntegrationSettingsForm from '~/integrations/integration_settings_form';
+import PrometheusMetrics from '~/prometheus_metrics/prometheus_metrics';
+
+document.addEventListener('DOMContentLoaded', () => {
+ const prometheusSettingsWrapper = document.querySelector('.js-prometheus-metrics-monitoring');
+ const integrationSettingsForm = new IntegrationSettingsForm('.js-integration-settings-form');
+ integrationSettingsForm.init();
+
+ if (prometheusSettingsWrapper) {
+ const prometheusMetrics = new PrometheusMetrics('.js-prometheus-metrics-monitoring');
+ prometheusMetrics.loadActiveMetrics();
+ }
+});
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 a563d0f9961..6c2a785c0af 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
@@ -2,7 +2,7 @@ import initSettingsPanels from '~/settings_panels';
import SecretValues from '~/behaviors/secret_values';
import AjaxVariableList from '~/ci_variable_list/ajax_variable_list';
-export default function () {
+document.addEventListener('DOMContentLoaded', () => {
// Initialize expandable settings panels
initSettingsPanels();
@@ -22,4 +22,4 @@ export default function () {
errorBox: variableListEl.querySelector('.js-ci-variable-error-box'),
saveEndpoint: variableListEl.dataset.saveEndpoint,
});
-}
+});
diff --git a/app/assets/javascripts/pages/projects/settings/repository/show/index.js b/app/assets/javascripts/pages/projects/settings/repository/show/index.js
index 83b5467fbc0..5a6f4138b10 100644
--- a/app/assets/javascripts/pages/projects/settings/repository/show/index.js
+++ b/app/assets/javascripts/pages/projects/settings/repository/show/index.js
@@ -1,3 +1,7 @@
import initSettingsPanels from '~/settings_panels';
+import initDeployKeys from '~/deploy_keys';
-export default initSettingsPanels;
+document.addEventListener('DOMContentLoaded', () => {
+ initDeployKeys();
+ initSettingsPanels();
+});
diff --git a/app/assets/javascripts/pages/projects/snippets/edit/index.js b/app/assets/javascripts/pages/projects/snippets/edit/index.js
index 9edb16dc73b..caf9ee9b398 100644
--- a/app/assets/javascripts/pages/projects/snippets/edit/index.js
+++ b/app/assets/javascripts/pages/projects/snippets/edit/index.js
@@ -1,3 +1,3 @@
import initForm from '~/pages/projects/init_form';
-export default initForm($('.snippet-form'));
+document.addEventListener('DOMContentLoaded', () => initForm($('.snippet-form')));
diff --git a/app/assets/javascripts/pages/projects/snippets/new/index.js b/app/assets/javascripts/pages/projects/snippets/new/index.js
index 9edb16dc73b..caf9ee9b398 100644
--- a/app/assets/javascripts/pages/projects/snippets/new/index.js
+++ b/app/assets/javascripts/pages/projects/snippets/new/index.js
@@ -1,3 +1,3 @@
import initForm from '~/pages/projects/init_form';
-export default initForm($('.snippet-form'));
+document.addEventListener('DOMContentLoaded', () => initForm($('.snippet-form')));
diff --git a/app/assets/javascripts/pages/projects/snippets/show/index.js b/app/assets/javascripts/pages/projects/snippets/show/index.js
index a3cf75c385b..a134599cb04 100644
--- a/app/assets/javascripts/pages/projects/snippets/show/index.js
+++ b/app/assets/javascripts/pages/projects/snippets/show/index.js
@@ -3,9 +3,9 @@ import ZenMode from '~/zen_mode';
import LineHighlighter from '../../../../line_highlighter';
import BlobViewer from '../../../../blob/viewer';
-export default function () {
+document.addEventListener('DOMContentLoaded', () => {
new LineHighlighter(); // eslint-disable-line no-new
new BlobViewer(); // eslint-disable-line no-new
initNotes();
new ZenMode(); // eslint-disable-line no-new
-}
+});
diff --git a/app/assets/javascripts/pages/projects/tags/new/index.js b/app/assets/javascripts/pages/projects/tags/new/index.js
index dacc2875c8c..191c98b36bb 100644
--- a/app/assets/javascripts/pages/projects/tags/new/index.js
+++ b/app/assets/javascripts/pages/projects/tags/new/index.js
@@ -2,8 +2,8 @@ import RefSelectDropdown from '../../../../ref_select_dropdown';
import ZenMode from '../../../../zen_mode';
import GLForm from '../../../../gl_form';
-export default () => {
+document.addEventListener('DOMContentLoaded', () => {
new ZenMode(); // eslint-disable-line no-new
new GLForm($('.tag-form'), true); // eslint-disable-line no-new
new RefSelectDropdown($('.js-branch-select')); // eslint-disable-line no-new
-};
+});
diff --git a/app/assets/javascripts/pages/projects/tree/show/index.js b/app/assets/javascripts/pages/projects/tree/show/index.js
index c4b3356e478..ed7d3f1747c 100644
--- a/app/assets/javascripts/pages/projects/tree/show/index.js
+++ b/app/assets/javascripts/pages/projects/tree/show/index.js
@@ -1,4 +1,5 @@
import Vue from 'vue';
+import initBlob from '~/blob_edit/blob_bundle';
import commitPipelineStatus from '~/projects/tree/components/commit_pipeline_status_component.vue';
import TreeView from '../../../../tree';
import ShortcutsNavigation from '../../../../shortcuts_navigation';
@@ -6,7 +7,7 @@ import BlobViewer from '../../../../blob/viewer';
import NewCommitForm from '../../../../new_commit_form';
import { ajaxGet } from '../../../../lib/utils/common_utils';
-export default () => {
+document.addEventListener('DOMContentLoaded', () => {
new ShortcutsNavigation(); // eslint-disable-line no-new
new TreeView(); // eslint-disable-line no-new
new BlobViewer(); // eslint-disable-line no-new
@@ -14,7 +15,8 @@ export default () => {
$('#tree-slider').waitForImages(() =>
ajaxGet(document.querySelector('.js-tree-content').dataset.logsPath));
- const commitPipelineStatusEl = document.getElementById('commit-pipeline-status');
+ initBlob();
+ const commitPipelineStatusEl = document.querySelector('.js-commit-pipeline-status');
const statusLink = document.querySelector('.commit-actions .ci-status-link');
if (statusLink != null) {
statusLink.remove();
@@ -33,5 +35,4 @@ export default () => {
},
});
}
-};
-
+});
diff --git a/app/assets/javascripts/pages/projects/wikis/index.js b/app/assets/javascripts/pages/projects/wikis/index.js
index eb14c7a0e78..b9f8707fd6e 100644
--- a/app/assets/javascripts/pages/projects/wikis/index.js
+++ b/app/assets/javascripts/pages/projects/wikis/index.js
@@ -3,9 +3,9 @@ import ShortcutsWiki from '../../../shortcuts_wiki';
import ZenMode from '../../../zen_mode';
import GLForm from '../../../gl_form';
-export default () => {
+document.addEventListener('DOMContentLoaded', () => {
new Wikis(); // eslint-disable-line no-new
new ShortcutsWiki(); // eslint-disable-line no-new
new ZenMode(); // eslint-disable-line no-new
new GLForm($('.wiki-form'), true); // eslint-disable-line no-new
-};
+});
diff --git a/app/assets/javascripts/pages/search/init_filtered_search.js b/app/assets/javascripts/pages/search/init_filtered_search.js
index 250f9d992ab..de8d4168d71 100644
--- a/app/assets/javascripts/pages/search/init_filtered_search.js
+++ b/app/assets/javascripts/pages/search/init_filtered_search.js
@@ -1,7 +1,9 @@
+import FilteredSearchManager from '~/filtered_search/filtered_search_manager';
+
export default ({ page }) => {
- const filteredSearchEnabled = gl.FilteredSearchManager && document.querySelector('.filtered-search');
+ const filteredSearchEnabled = FilteredSearchManager && document.querySelector('.filtered-search');
if (filteredSearchEnabled) {
- const filteredSearchManager = new gl.FilteredSearchManager({ page });
+ const filteredSearchManager = new FilteredSearchManager({ page });
filteredSearchManager.setup();
}
};
diff --git a/app/assets/javascripts/pages/search/show/index.js b/app/assets/javascripts/pages/search/show/index.js
index 4264c5c9dbe..85aaaa2c9da 100644
--- a/app/assets/javascripts/pages/search/show/index.js
+++ b/app/assets/javascripts/pages/search/show/index.js
@@ -1,3 +1,3 @@
import Search from './search';
-export default () => new Search();
+document.addEventListener('DOMContentLoaded', () => new Search());
diff --git a/app/assets/javascripts/pages/search/show/search.js b/app/assets/javascripts/pages/search/show/search.js
index dc621bc87c0..cf44e291199 100644
--- a/app/assets/javascripts/pages/search/show/search.js
+++ b/app/assets/javascripts/pages/search/show/search.js
@@ -9,7 +9,7 @@ export default class Search {
this.searchInput = '.js-search-input';
this.searchClear = '.js-search-clear';
- this.groupId = $groupDropdown.data('group-id');
+ this.groupId = $groupDropdown.data('groupId');
this.eventListeners();
$groupDropdown.glDropdown({
@@ -36,7 +36,7 @@ export default class Search {
return obj.full_name;
},
toggleLabel(obj) {
- return `${($groupDropdown.data('default-label'))} ${obj.full_name}`;
+ return `${($groupDropdown.data('defaultLabel'))} ${obj.full_name}`;
},
clicked: () => Search.submitSearch(),
});
@@ -69,7 +69,7 @@ export default class Search {
return obj.name_with_namespace;
},
toggleLabel(obj) {
- return `${($projectDropdown.data('default-label'))} ${obj.name_with_namespace}`;
+ return `${($projectDropdown.data('defaultLabel'))} ${obj.name_with_namespace}`;
},
clicked: () => Search.submitSearch(),
});
diff --git a/app/assets/javascripts/pages/sessions/index.js b/app/assets/javascripts/pages/sessions/index.js
index 54f4e56359a..c2c069d1ca8 100644
--- a/app/assets/javascripts/pages/sessions/index.js
+++ b/app/assets/javascripts/pages/sessions/index.js
@@ -1,5 +1,3 @@
import initU2F from '../../shared/sessions/u2f';
-export default () => {
- initU2F();
-};
+document.addEventListener('DOMContentLoaded', initU2F);
diff --git a/app/assets/javascripts/pages/snippets/edit/index.js b/app/assets/javascripts/pages/snippets/edit/index.js
index 9c664b5f1ff..2ee38b64ca1 100644
--- a/app/assets/javascripts/pages/snippets/edit/index.js
+++ b/app/assets/javascripts/pages/snippets/edit/index.js
@@ -1,3 +1,3 @@
import form from '../form';
-export default form;
+document.addEventListener('DOMContentLoaded', form);
diff --git a/app/assets/javascripts/pages/snippets/new/index.js b/app/assets/javascripts/pages/snippets/new/index.js
index 9c664b5f1ff..2ee38b64ca1 100644
--- a/app/assets/javascripts/pages/snippets/new/index.js
+++ b/app/assets/javascripts/pages/snippets/new/index.js
@@ -1,3 +1,3 @@
import form from '../form';
-export default form;
+document.addEventListener('DOMContentLoaded', form);
diff --git a/app/assets/javascripts/pages/snippets/show/index.js b/app/assets/javascripts/pages/snippets/show/index.js
index 04c9562bfbb..f548b9fad65 100644
--- a/app/assets/javascripts/pages/snippets/show/index.js
+++ b/app/assets/javascripts/pages/snippets/show/index.js
@@ -1,12 +1,11 @@
-/* eslint-disable no-new */
import LineHighlighter from '../../../line_highlighter';
import BlobViewer from '../../../blob/viewer';
import ZenMode from '../../../zen_mode';
import initNotes from '../../../init_notes';
-export default () => {
- new LineHighlighter();
- new BlobViewer();
+document.addEventListener('DOMContentLoaded', () => {
+ new LineHighlighter(); // eslint-disable-line no-new
+ new BlobViewer(); // eslint-disable-line no-new
initNotes();
- new ZenMode();
-};
+ new ZenMode(); // eslint-disable-line no-new
+});
diff --git a/app/assets/javascripts/pages/users/activity_calendar.js b/app/assets/javascripts/pages/users/activity_calendar.js
new file mode 100644
index 00000000000..57306322aa4
--- /dev/null
+++ b/app/assets/javascripts/pages/users/activity_calendar.js
@@ -0,0 +1,242 @@
+import _ from 'underscore';
+import { scaleLinear, scaleThreshold } from 'd3-scale';
+import { select } from 'd3-selection';
+import { getDayName, getDayDifference } from '~/lib/utils/datetime_utility';
+import axios from '~/lib/utils/axios_utils';
+import flash from '~/flash';
+import { __ } from '~/locale';
+
+const d3 = { select, scaleLinear, scaleThreshold };
+
+const LOADING_HTML = `
+ <div class="text-center">
+ <i class="fa fa-spinner fa-spin user-calendar-activities-loading"></i>
+ </div>
+`;
+
+function getSystemDate(systemUtcOffsetSeconds) {
+ const date = new Date();
+ const localUtcOffsetMinutes = 0 - date.getTimezoneOffset();
+ const systemUtcOffsetMinutes = systemUtcOffsetSeconds / 60;
+ date.setMinutes((date.getMinutes() - localUtcOffsetMinutes) + systemUtcOffsetMinutes);
+ return date;
+}
+
+function formatTooltipText({ date, count }) {
+ const dateObject = new Date(date);
+ const dateDayName = getDayName(dateObject);
+ const dateText = dateObject.format('mmm d, yyyy');
+
+ let contribText = 'No contributions';
+ if (count > 0) {
+ contribText = `${count} contribution${count > 1 ? 's' : ''}`;
+ }
+ return `${contribText}<br />${dateDayName} ${dateText}`;
+}
+
+const initColorKey = () => d3.scaleLinear().range(['#acd5f2', '#254e77']).domain([0, 3]);
+
+export default class ActivityCalendar {
+ constructor(container, timestamps, calendarActivitiesPath, utcOffset = 0) {
+ this.calendarActivitiesPath = calendarActivitiesPath;
+ this.clickDay = this.clickDay.bind(this);
+ this.currentSelectedDate = '';
+ this.daySpace = 1;
+ this.daySize = 15;
+ this.daySizeWithSpace = this.daySize + (this.daySpace * 2);
+ this.monthNames = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
+ this.months = [];
+
+ // Loop through the timestamps to create a group of objects
+ // The group of objects will be grouped based on the day of the week they are
+ this.timestampsTmp = [];
+ let group = 0;
+
+ const today = getSystemDate(utcOffset);
+ today.setHours(0, 0, 0, 0, 0);
+
+ const oneYearAgo = new Date(today);
+ oneYearAgo.setFullYear(today.getFullYear() - 1);
+
+ const days = getDayDifference(oneYearAgo, today);
+
+ for (let i = 0; i <= days; i += 1) {
+ const date = new Date(oneYearAgo);
+ date.setDate(date.getDate() + i);
+
+ const day = date.getDay();
+ const count = timestamps[date.format('yyyy-mm-dd')] || 0;
+
+ // Create a new group array if this is the first day of the week
+ // or if is first object
+ if ((day === 0 && i !== 0) || i === 0) {
+ this.timestampsTmp.push([]);
+ group += 1;
+ }
+
+ // Push to the inner array the values that will be used to render map
+ const innerArray = this.timestampsTmp[group - 1];
+ innerArray.push({ count, date, day });
+ }
+
+ // Init color functions
+ this.colorKey = initColorKey();
+ this.color = this.initColor();
+
+ // Init the svg element
+ this.svg = this.renderSvg(container, group);
+ this.renderDays();
+ 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
+ getExtraWidthPadding(group) {
+ let extraWidthPadding = 0;
+ const lastColMonth = this.timestampsTmp[group - 1][0].date.getMonth();
+ const secondLastColMonth = this.timestampsTmp[group - 2][0].date.getMonth();
+
+ if (lastColMonth !== secondLastColMonth) {
+ extraWidthPadding = 6;
+ }
+
+ return extraWidthPadding;
+ }
+
+ renderSvg(container, group) {
+ const width = ((group + 1) * this.daySizeWithSpace) + this.getExtraWidthPadding(group);
+ return d3.select(container)
+ .append('svg')
+ .attr('width', width)
+ .attr('height', 167)
+ .attr('class', 'contrib-calendar');
+ }
+
+ renderDays() {
+ this.svg.selectAll('g').data(this.timestampsTmp).enter().append('g')
+ .attr('transform', (group, i) => {
+ _.each(group, (stamp, a) => {
+ if (a === 0 && stamp.day === 0) {
+ const month = stamp.date.getMonth();
+ const x = (this.daySizeWithSpace * i) + 1 + this.daySizeWithSpace;
+ const lastMonth = _.last(this.months);
+ if (
+ lastMonth == null ||
+ (month !== lastMonth.month && x - this.daySizeWithSpace !== lastMonth.x)
+ ) {
+ this.months.push({ month, x });
+ }
+ }
+ });
+ return `translate(${(this.daySizeWithSpace * i) + 1 + this.daySizeWithSpace}, 18)`;
+ })
+ .selectAll('rect')
+ .data(stamp => stamp)
+ .enter()
+ .append('rect')
+ .attr('x', '0')
+ .attr('y', stamp => this.daySizeWithSpace * stamp.day)
+ .attr('width', this.daySize)
+ .attr('height', this.daySize)
+ .attr('fill', stamp => (
+ stamp.count !== 0 ? this.color(Math.min(stamp.count, 40)) : '#ededed'
+ ))
+ .attr('title', stamp => formatTooltipText(stamp))
+ .attr('class', 'user-contrib-cell js-tooltip')
+ .attr('data-container', 'body')
+ .on('click', this.clickDay);
+ }
+
+ renderDayTitles() {
+ const days = [
+ {
+ text: 'M',
+ y: 29 + (this.daySizeWithSpace * 1),
+ }, {
+ text: 'W',
+ y: 29 + (this.daySizeWithSpace * 3),
+ }, {
+ text: 'F',
+ y: 29 + (this.daySizeWithSpace * 5),
+ },
+ ];
+ this.svg.append('g')
+ .selectAll('text')
+ .data(days)
+ .enter()
+ .append('text')
+ .attr('text-anchor', 'middle')
+ .attr('x', 8)
+ .attr('y', day => day.y)
+ .text(day => day.text)
+ .attr('class', 'user-contrib-text');
+ }
+
+ renderMonths() {
+ this.svg.append('g')
+ .attr('direction', 'ltr')
+ .selectAll('text')
+ .data(this.months)
+ .enter()
+ .append('text')
+ .attr('x', date => date.x)
+ .attr('y', 10)
+ .attr('class', 'user-contrib-text')
+ .text(date => this.monthNames[date.month]);
+ }
+
+ renderKey() {
+ const keyValues = ['no contributions', '1-9 contributions', '10-19 contributions', '20-29 contributions', '30+ contributions'];
+ const keyColors = ['#ededed', this.colorKey(0), this.colorKey(1), this.colorKey(2), this.colorKey(3)];
+
+ this.svg.append('g')
+ .attr('transform', `translate(18, ${(this.daySizeWithSpace * 8) + 16})`)
+ .selectAll('rect')
+ .data(keyColors)
+ .enter()
+ .append('rect')
+ .attr('width', this.daySize)
+ .attr('height', this.daySize)
+ .attr('x', (color, i) => this.daySizeWithSpace * i)
+ .attr('y', 0)
+ .attr('fill', color => color)
+ .attr('class', 'js-tooltip')
+ .attr('title', (color, i) => keyValues[i])
+ .attr('data-container', 'body');
+ }
+
+ initColor() {
+ const colorRange = ['#ededed', this.colorKey(0), this.colorKey(1), this.colorKey(2), this.colorKey(3)];
+ return d3.scaleThreshold().domain([0, 10, 20, 30]).range(colorRange);
+ }
+
+ clickDay(stamp) {
+ if (this.currentSelectedDate !== stamp.date) {
+ this.currentSelectedDate = stamp.date;
+
+ const date = [
+ this.currentSelectedDate.getFullYear(),
+ this.currentSelectedDate.getMonth() + 1,
+ this.currentSelectedDate.getDate(),
+ ].join('-');
+
+ $('.user-calendar-activities').html(LOADING_HTML);
+
+ axios.get(this.calendarActivitiesPath, {
+ params: {
+ date,
+ },
+ responseType: 'text',
+ })
+ .then(({ data }) => $('.user-calendar-activities').html(data))
+ .catch(() => flash(__('An error occurred while retrieving calendar activity')));
+ } else {
+ this.currentSelectedDate = '';
+ $('.user-calendar-activities').html('');
+ }
+ }
+}
diff --git a/app/assets/javascripts/pages/users/index.js b/app/assets/javascripts/pages/users/index.js
new file mode 100644
index 00000000000..899dcd42e37
--- /dev/null
+++ b/app/assets/javascripts/pages/users/index.js
@@ -0,0 +1,27 @@
+import UserCallout from '~/user_callout';
+import Cookies from 'js-cookie';
+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 });
+
+ // hide project limit message
+ $('.hide-project-limit-message').on('click', (e) => {
+ e.preventDefault();
+ Cookies.set('hide_project_limit_message', 'false');
+ $(this).parents('.project-limit-message').remove();
+ });
+}
+
+document.addEventListener('DOMContentLoaded', () => {
+ const page = $('body').attr('data-page');
+ const action = page.split(':')[1];
+ initUserProfile(action);
+ new UserCallout(); // eslint-disable-line no-new
+});
diff --git a/app/assets/javascripts/pages/users/show/index.js b/app/assets/javascripts/pages/users/show/index.js
deleted file mode 100644
index f18f98b4e9a..00000000000
--- a/app/assets/javascripts/pages/users/show/index.js
+++ /dev/null
@@ -1,3 +0,0 @@
-import UserCallout from '~/user_callout';
-
-export default () => new UserCallout();
diff --git a/app/assets/javascripts/pages/users/user_tabs.js b/app/assets/javascripts/pages/users/user_tabs.js
new file mode 100644
index 00000000000..c1217623467
--- /dev/null
+++ b/app/assets/javascripts/pages/users/user_tabs.js
@@ -0,0 +1,199 @@
+import axios from '~/lib/utils/axios_utils';
+import Activities from '~/activities';
+import { localTimeAgo } from '~/lib/utils/datetime_utility';
+import { __ } from '~/locale';
+import flash from '~/flash';
+import ActivityCalendar from './activity_calendar';
+
+/**
+ * UserTabs
+ *
+ * Handles persisting and restoring the current tab selection and lazily-loading
+ * content on the Users#show page.
+ *
+ * ### Example Markup
+ *
+ * <ul class="nav-links">
+ * <li class="activity-tab active">
+ * <a data-action="activity" data-target="#activity" data-toggle="tab" href="/u/username">
+ * Activity
+ * </a>
+ * </li>
+ * <li class="groups-tab">
+ * <a data-action="groups" data-target="#groups" data-toggle="tab" href="/u/username/groups">
+ * Groups
+ * </a>
+ * </li>
+ * <li class="contributed-tab">
+ * ...
+ * </li>
+ * <li class="projects-tab">
+ * ...
+ * </li>
+ * <li class="snippets-tab">
+ * ...
+ * </li>
+ * </ul>
+ *
+ * <div class="tab-content">
+ * <div class="tab-pane" id="activity">
+ * Activity Content
+ * </div>
+ * <div class="tab-pane" id="groups">
+ * Groups Content
+ * </div>
+ * <div class="tab-pane" id="contributed">
+ * Contributed projects content
+ * </div>
+ * <div class="tab-pane" id="projects">
+ * Projects content
+ * </div>
+ * <div class="tab-pane" id="snippets">
+ * Snippets content
+ * </div>
+ * </div>
+ *
+ * <div class="loading-status">
+ * <div class="loading">
+ * Loading Animation
+ * </div>
+ * </div>
+ */
+
+const CALENDAR_TEMPLATE = `
+ <div class="clearfix calendar">
+ <div class="js-contrib-calendar"></div>
+ <div class="calendar-hint">
+ Summary of issues, merge requests, push events, and comments
+ </div>
+ </div>
+`;
+
+export default class UserTabs {
+ constructor({ defaultAction, action, parentEl }) {
+ this.loaded = {};
+ this.defaultAction = defaultAction || 'activity';
+ this.action = action || this.defaultAction;
+ this.$parentEl = $(parentEl) || $(document);
+ this.windowLocation = window.location;
+ this.$parentEl.find('.nav-links a')
+ .each((i, navLink) => {
+ this.loaded[$(navLink).attr('data-action')] = false;
+ });
+ this.actions = Object.keys(this.loaded);
+ this.bindEvents();
+
+ if (this.action === 'show') {
+ this.action = this.defaultAction;
+ }
+
+ this.activateTab(this.action);
+ }
+
+ bindEvents() {
+ this.$parentEl
+ .off('shown.bs.tab', '.nav-links a[data-toggle="tab"]')
+ .on('shown.bs.tab', '.nav-links a[data-toggle="tab"]', event => this.tabShown(event))
+ .on('click', '.gl-pagination a', event => this.changeProjectsPage(event));
+ }
+
+ changeProjectsPage(e) {
+ e.preventDefault();
+
+ $('.tab-pane.active').empty();
+ const endpoint = $(e.target).attr('href');
+ this.loadTab(this.getCurrentAction(), endpoint);
+ }
+
+ tabShown(event) {
+ const $target = $(event.target);
+ const action = $target.data('action');
+ const source = $target.attr('href');
+ const endpoint = $target.data('endpoint');
+ this.setTab(action, endpoint);
+ return this.setCurrentAction(source);
+ }
+
+ activateTab(action) {
+ return this.$parentEl.find(`.nav-links .js-${action}-tab a`)
+ .tab('show');
+ }
+
+ setTab(action, endpoint) {
+ if (this.loaded[action]) {
+ return;
+ }
+ if (action === 'activity') {
+ this.loadActivities();
+ }
+
+ const loadableActions = ['groups', 'contributed', 'projects', 'snippets'];
+ if (loadableActions.indexOf(action) > -1) {
+ this.loadTab(action, endpoint);
+ }
+ }
+
+ loadTab(action, endpoint) {
+ this.toggleLoading(true);
+
+ return axios.get(endpoint)
+ .then(({ data }) => {
+ const tabSelector = `div#${action}`;
+ this.$parentEl.find(tabSelector).html(data.html);
+ this.loaded[action] = true;
+ localTimeAgo($('.js-timeago', tabSelector));
+
+ this.toggleLoading(false);
+ })
+ .catch(() => {
+ this.toggleLoading(false);
+ });
+ }
+
+ loadActivities() {
+ if (this.loaded.activity) {
+ return;
+ }
+ const $calendarWrap = this.$parentEl.find('.user-calendar');
+ const calendarPath = $calendarWrap.data('calendarPath');
+ const calendarActivitiesPath = $calendarWrap.data('calendarActivitiesPath');
+ const utcOffset = $calendarWrap.data('utcOffset');
+ let utcFormatted = 'UTC';
+ if (utcOffset !== 0) {
+ utcFormatted = `UTC${utcOffset > 0 ? '+' : ''}${(utcOffset / 3600)}`;
+ }
+
+ axios.get(calendarPath)
+ .then(({ data }) => {
+ $calendarWrap.html(CALENDAR_TEMPLATE);
+ $calendarWrap.find('.calendar-hint').append(`(Timezone: ${utcFormatted})`);
+
+ // eslint-disable-next-line no-new
+ new ActivityCalendar('.js-contrib-calendar', data, calendarActivitiesPath, utcOffset);
+ })
+ .catch(() => flash(__('There was an error loading users activity calendar.')));
+
+ // eslint-disable-next-line no-new
+ new Activities();
+ this.loaded.activity = true;
+ }
+
+ toggleLoading(status) {
+ return this.$parentEl.find('.loading-status .loading')
+ .toggle(status);
+ }
+
+ setCurrentAction(source) {
+ let newState = source;
+ newState = newState.replace(/\/+$/, '');
+ newState += this.windowLocation.search + this.windowLocation.hash;
+ history.replaceState({
+ url: newState,
+ }, document.title, newState);
+ return newState;
+ }
+
+ getCurrentAction() {
+ return this.$parentEl.find('.nav-links .active a').data('action');
+ }
+}