Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2019-09-20 00:06:29 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2019-09-20 00:06:29 +0300
commitb35b9ac7e2fd4a707ea9291eb57769c690403b4c (patch)
treeae746b64cc7d3a19926e6d4a39a5daeb990a4154 /app
parent81f7adf08b4557c38ac2ef1c730e72e07db2f1a3 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/event_tracking/issue_sidebar.js2
-rw-r--r--app/assets/javascripts/event_tracking/notes.js2
-rw-r--r--app/assets/javascripts/filterable_list.js1
-rw-r--r--app/assets/javascripts/integrations/integration_settings_form.js1
-rw-r--r--app/assets/javascripts/issue_show/index.js4
-rw-r--r--app/assets/javascripts/main.js1
-rw-r--r--app/assets/javascripts/notes.js1
-rw-r--r--app/assets/javascripts/notes/components/note_actions/reply_button.vue4
-rw-r--r--app/assets/javascripts/notes/index.js4
-rw-r--r--app/assets/javascripts/pages/projects/commit/pipelines/index.js1
-rw-r--r--app/assets/javascripts/pages/projects/commit/show/index.js1
-rw-r--r--app/assets/javascripts/sidebar/components/assignees/assignee_title.vue10
-rw-r--r--app/assets/javascripts/sidebar/components/confidential/confidential_issue_sidebar.vue11
-rw-r--r--app/assets/javascripts/sidebar/components/lock/lock_issue_sidebar.vue11
-rw-r--r--app/assets/javascripts/sidebar/components/subscriptions/subscriptions.vue8
-rw-r--r--app/assets/javascripts/tracking.js103
-rw-r--r--app/assets/stylesheets/framework/flash.scss2
-rw-r--r--app/models/repository.rb28
18 files changed, 102 insertions, 93 deletions
diff --git a/app/assets/javascripts/event_tracking/issue_sidebar.js b/app/assets/javascripts/event_tracking/issue_sidebar.js
deleted file mode 100644
index 6909f82c66f..00000000000
--- a/app/assets/javascripts/event_tracking/issue_sidebar.js
+++ /dev/null
@@ -1,2 +0,0 @@
-export const initSidebarTracking = () => {};
-export const trackEvent = () => {};
diff --git a/app/assets/javascripts/event_tracking/notes.js b/app/assets/javascripts/event_tracking/notes.js
deleted file mode 100644
index 1f70290c397..00000000000
--- a/app/assets/javascripts/event_tracking/notes.js
+++ /dev/null
@@ -1,2 +0,0 @@
-// Noop function which has a EE counter-part
-export default () => {};
diff --git a/app/assets/javascripts/filterable_list.js b/app/assets/javascripts/filterable_list.js
index 77080691dcb..c21fba06d42 100644
--- a/app/assets/javascripts/filterable_list.js
+++ b/app/assets/javascripts/filterable_list.js
@@ -22,6 +22,7 @@ export default class FilterableList {
getPagePath() {
const action = this.filterForm.getAttribute('action');
+ // eslint-disable-next-line no-jquery/no-serialize
const params = $(this.filterForm).serialize();
return `${action}${action.indexOf('?') > 0 ? '&' : '?'}${params}`;
}
diff --git a/app/assets/javascripts/integrations/integration_settings_form.js b/app/assets/javascripts/integrations/integration_settings_form.js
index a7746bb3a0b..1c9b94ade8a 100644
--- a/app/assets/javascripts/integrations/integration_settings_form.js
+++ b/app/assets/javascripts/integrations/integration_settings_form.js
@@ -42,6 +42,7 @@ export default class IntegrationSettingsForm {
// and test the service using provided configuration.
if (this.$form.get(0).checkValidity() && this.canTestService) {
e.preventDefault();
+ // eslint-disable-next-line no-jquery/no-serialize
this.testSettings(this.$form.serialize());
}
}
diff --git a/app/assets/javascripts/issue_show/index.js b/app/assets/javascripts/issue_show/index.js
index 4bcba72bc23..e170d338408 100644
--- a/app/assets/javascripts/issue_show/index.js
+++ b/app/assets/javascripts/issue_show/index.js
@@ -1,5 +1,4 @@
import Vue from 'vue';
-import { initSidebarTracking } from 'ee_else_ce/event_tracking/issue_sidebar';
import issuableApp from './components/app.vue';
import { parseIssuableData } from './utils/parse_data';
@@ -9,9 +8,6 @@ export default function initIssueableApp() {
components: {
issuableApp,
},
- mounted() {
- initSidebarTracking();
- },
render(createElement) {
return createElement('issuable-app', {
props: parseIssuableData(),
diff --git a/app/assets/javascripts/main.js b/app/assets/javascripts/main.js
index 49be11d466d..c19a845eb69 100644
--- a/app/assets/javascripts/main.js
+++ b/app/assets/javascripts/main.js
@@ -314,6 +314,7 @@ document.addEventListener('DOMContentLoaded', () => {
const action = `${this.action}${link.search === '' ? '?' : '&'}`;
event.preventDefault();
+ // eslint-disable-next-line no-jquery/no-serialize
visitUrl(`${action}${$(this).serialize()}`);
});
diff --git a/app/assets/javascripts/notes.js b/app/assets/javascripts/notes.js
index 9cc56b34c75..ed52eec8b18 100644
--- a/app/assets/javascripts/notes.js
+++ b/app/assets/javascripts/notes.js
@@ -1461,6 +1461,7 @@ export default class Notes {
getFormData($form) {
const content = $form.find('.js-note-text').val();
return {
+ // eslint-disable-next-line no-jquery/no-serialize
formData: $form.serialize(),
formContent: _.escape(content),
formAction: $form.attr('action'),
diff --git a/app/assets/javascripts/notes/components/note_actions/reply_button.vue b/app/assets/javascripts/notes/components/note_actions/reply_button.vue
index 1aeb07d6608..8bdee759a23 100644
--- a/app/assets/javascripts/notes/components/note_actions/reply_button.vue
+++ b/app/assets/javascripts/notes/components/note_actions/reply_button.vue
@@ -19,7 +19,9 @@ export default {
<gl-button
ref="button"
v-gl-tooltip
- class="note-action-button js-note-action-reply"
+ class="note-action-button"
+ data-track-event="click_button"
+ data-track-label="reply_comment_button"
variant="transparent"
:title="__('Reply to comment')"
@click="$emit('startReplying')"
diff --git a/app/assets/javascripts/notes/index.js b/app/assets/javascripts/notes/index.js
index c70c0e4095c..30372103590 100644
--- a/app/assets/javascripts/notes/index.js
+++ b/app/assets/javascripts/notes/index.js
@@ -1,5 +1,4 @@
import Vue from 'vue';
-import initNoteStats from 'ee_else_ce/event_tracking/notes';
import notesApp from './components/notes_app.vue';
import initDiscussionFilters from './discussion_filters';
import createStore from './stores';
@@ -39,9 +38,6 @@ document.addEventListener('DOMContentLoaded', () => {
notesData: JSON.parse(notesDataset.notesData),
};
},
- mounted() {
- initNoteStats();
- },
render(createElement) {
return createElement('notes-app', {
props: {
diff --git a/app/assets/javascripts/pages/projects/commit/pipelines/index.js b/app/assets/javascripts/pages/projects/commit/pipelines/index.js
index 8cc3cb0a57c..9f08260c3d6 100644
--- a/app/assets/javascripts/pages/projects/commit/pipelines/index.js
+++ b/app/assets/javascripts/pages/projects/commit/pipelines/index.js
@@ -6,6 +6,7 @@ document.addEventListener('DOMContentLoaded', () => {
new MiniPipelineGraph({
container: '.js-commit-pipeline-graph',
}).bindEvents();
+ // eslint-disable-next-line no-jquery/no-load
$('.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 6fc982967eb..5aa4734244e 100644
--- a/app/assets/javascripts/pages/projects/commit/show/index.js
+++ b/app/assets/javascripts/pages/projects/commit/show/index.js
@@ -21,6 +21,7 @@ document.addEventListener('DOMContentLoaded', () => {
}).bindEvents();
initNotes();
initChangesDropdown(document.querySelector('.navbar-gitlab').offsetHeight + performanceHeight);
+ // eslint-disable-next-line no-jquery/no-load
$('.commit-info.branches').load(document.querySelector('.js-commit-box').dataset.commitPath);
fetchCommitMergeRequests();
initDiffNotes();
diff --git a/app/assets/javascripts/sidebar/components/assignees/assignee_title.vue b/app/assets/javascripts/sidebar/components/assignees/assignee_title.vue
index 63b93a80ead..f4dac38b9e1 100644
--- a/app/assets/javascripts/sidebar/components/assignees/assignee_title.vue
+++ b/app/assets/javascripts/sidebar/components/assignees/assignee_title.vue
@@ -1,6 +1,5 @@
<script>
import { n__ } from '~/locale';
-import { trackEvent } from 'ee_else_ce/event_tracking/issue_sidebar';
export default {
name: 'AssigneeTitle',
@@ -30,11 +29,6 @@ export default {
return n__('Assignee', `%d Assignees`, assignees);
},
},
- methods: {
- trackEdit() {
- trackEvent('click_edit_button', 'assignee');
- },
- },
};
</script>
<template>
@@ -45,7 +39,9 @@ export default {
v-if="editable"
class="js-sidebar-dropdown-toggle edit-link float-right"
href="#"
- @click.prevent="trackEdit"
+ data-track-event="click_edit_button"
+ data-track-label="right_sidebar"
+ data-track-property="assignee"
>
{{ __('Edit') }}
</a>
diff --git a/app/assets/javascripts/sidebar/components/confidential/confidential_issue_sidebar.vue b/app/assets/javascripts/sidebar/components/confidential/confidential_issue_sidebar.vue
index 1c75b6148e8..e350264de96 100644
--- a/app/assets/javascripts/sidebar/components/confidential/confidential_issue_sidebar.vue
+++ b/app/assets/javascripts/sidebar/components/confidential/confidential_issue_sidebar.vue
@@ -5,7 +5,6 @@ import tooltip from '~/vue_shared/directives/tooltip';
import Icon from '~/vue_shared/components/icon.vue';
import eventHub from '~/sidebar/event_hub';
import editForm from './edit_form.vue';
-import { trackEvent } from 'ee_else_ce/event_tracking/issue_sidebar';
export default {
components: {
@@ -52,11 +51,6 @@ export default {
toggleForm() {
this.edit = !this.edit;
},
- onEditClick() {
- this.toggleForm();
-
- trackEvent('click_edit_button', 'confidentiality');
- },
updateConfidentialAttribute(confidential) {
this.service
.update('issue', { confidential })
@@ -88,7 +82,10 @@ export default {
v-if="isEditable"
class="float-right confidential-edit"
href="#"
- @click.prevent="onEditClick"
+ data-track-event="click_edit_button"
+ data-track-label="right_sidebar"
+ data-track-property="confidentiality"
+ @click.prevent="toggleForm"
>
{{ __('Edit') }}
</a>
diff --git a/app/assets/javascripts/sidebar/components/lock/lock_issue_sidebar.vue b/app/assets/javascripts/sidebar/components/lock/lock_issue_sidebar.vue
index ec2a7b93a98..c7c5e0e20f1 100644
--- a/app/assets/javascripts/sidebar/components/lock/lock_issue_sidebar.vue
+++ b/app/assets/javascripts/sidebar/components/lock/lock_issue_sidebar.vue
@@ -6,7 +6,6 @@ import issuableMixin from '~/vue_shared/mixins/issuable';
import Icon from '~/vue_shared/components/icon.vue';
import eventHub from '~/sidebar/event_hub';
import editForm from './edit_form.vue';
-import { trackEvent } from 'ee_else_ce/event_tracking/issue_sidebar';
export default {
components: {
@@ -66,11 +65,6 @@ export default {
toggleForm() {
this.mediator.store.isLockDialogOpen = !this.mediator.store.isLockDialogOpen;
},
- onEditClick() {
- this.toggleForm();
-
- trackEvent('click_edit_button', 'lock_issue');
- },
updateLockedAttribute(locked) {
this.mediator.service
.update(this.issuableType, {
@@ -114,7 +108,10 @@ export default {
v-if="isEditable"
class="float-right lock-edit"
type="button"
- @click.prevent="onEditClick"
+ data-track-event="click_edit_button"
+ data-track-label="right_sidebar"
+ data-track-property="lock_issue"
+ @click.prevent="toggleForm"
>
{{ __('Edit') }}
</button>
diff --git a/app/assets/javascripts/sidebar/components/subscriptions/subscriptions.vue b/app/assets/javascripts/sidebar/components/subscriptions/subscriptions.vue
index 1f5f19d1931..ea5edb3ce3f 100644
--- a/app/assets/javascripts/sidebar/components/subscriptions/subscriptions.vue
+++ b/app/assets/javascripts/sidebar/components/subscriptions/subscriptions.vue
@@ -1,10 +1,10 @@
<script>
import { __ } from '~/locale';
+import Tracking from '~/tracking';
import icon from '~/vue_shared/components/icon.vue';
import toggleButton from '~/vue_shared/components/toggle_button.vue';
import tooltip from '~/vue_shared/directives/tooltip';
import eventHub from '../../event_hub';
-import { trackEvent } from 'ee_else_ce/event_tracking/issue_sidebar';
const ICON_ON = 'notifications';
const ICON_OFF = 'notifications-off';
@@ -19,6 +19,7 @@ export default {
icon,
toggleButton,
},
+ mixins: [Tracking.mixin({ label: 'right_sidebar' })],
props: {
loading: {
type: Boolean,
@@ -65,7 +66,10 @@ export default {
// Component event emission.
this.$emit('toggleSubscription', this.id);
- trackEvent('toggle_button', 'notifications', this.subscribed ? 0 : 1);
+ this.track('toggle_button', {
+ property: 'notifications',
+ value: this.subscribed ? 0 : 1,
+ });
},
onClickCollapsedIcon() {
this.$emit('toggleSidebar');
diff --git a/app/assets/javascripts/tracking.js b/app/assets/javascripts/tracking.js
index 1b4ca1d5741..7c0097fbe37 100644
--- a/app/assets/javascripts/tracking.js
+++ b/app/assets/javascripts/tracking.js
@@ -1,4 +1,4 @@
-import $ from 'jquery';
+import _ from 'underscore';
const DEFAULT_SNOWPLOW_OPTIONS = {
namespace: 'gl',
@@ -14,18 +14,31 @@ const DEFAULT_SNOWPLOW_OPTIONS = {
linkClickTracking: false,
};
-const extractData = (el, opts = {}) => {
- const { trackEvent, trackLabel = '', trackProperty = '' } = el.dataset;
- let trackValue = el.dataset.trackValue || el.value || '';
- if (el.type === 'checkbox' && !el.checked) trackValue = false;
- return [
- trackEvent + (opts.suffix || ''),
- {
- label: trackLabel,
- property: trackProperty,
- value: trackValue,
- },
- ];
+const eventHandler = (e, func, opts = {}) => {
+ const el = e.target.closest('[data-track-event]');
+ const action = el && el.dataset.trackEvent;
+ if (!action) return;
+
+ let value = el.dataset.trackValue || el.value || undefined;
+ if (el.type === 'checkbox' && !el.checked) value = false;
+
+ const data = {
+ label: el.dataset.trackLabel,
+ property: el.dataset.trackProperty,
+ value,
+ context: el.dataset.trackContext,
+ };
+
+ func(opts.category, action + (opts.suffix || ''), _.omit(data, _.isUndefined));
+};
+
+const eventHandlers = (category, func) => {
+ const handler = opts => e => eventHandler(e, func, { ...{ category }, ...opts });
+ const handlers = [];
+ handlers.push({ name: 'click', func: handler() });
+ handlers.push({ name: 'show.bs.dropdown', func: handler({ suffix: '_show' }) });
+ handlers.push({ name: 'hide.bs.dropdown', func: handler({ suffix: '_hide' }) });
+ return handlers;
};
export default class Tracking {
@@ -39,49 +52,43 @@ export default class Tracking {
return typeof window.snowplow === 'function' && this.trackable();
}
- static event(category = document.body.dataset.page, event = 'generic', data = {}) {
+ static event(category = document.body.dataset.page, action = 'generic', data = {}) {
if (!this.enabled()) return false;
// eslint-disable-next-line @gitlab/i18n/no-non-i18n-strings
if (!category) throw new Error('Tracking: no category provided for tracking.');
- return window.snowplow(
- 'trackStructEvent',
- category,
- event,
- Object.assign({}, { label: '', property: '', value: '' }, data),
- );
+ const { label, property, value, context } = data;
+ const contexts = context ? [context] : undefined;
+ return window.snowplow('trackStructEvent', category, action, label, property, value, contexts);
}
- constructor(category = document.body.dataset.page) {
- this.category = category;
- }
-
- bind(container = document) {
- if (!this.constructor.enabled()) return;
- container.querySelectorAll(`[data-track-event]`).forEach(el => {
- if (this.customHandlingFor(el)) return;
- // jquery is required for select2, so we use it always
- // see: https://github.com/select2/select2/issues/4686
- $(el).on('click', this.eventHandler(this.category));
- });
- }
+ static bindDocument(category = document.body.dataset.page, documentOverride = null) {
+ const el = documentOverride || document;
+ if (!this.enabled() || el.trackingBound) return [];
- customHandlingFor(el) {
- const classes = el.classList;
+ el.trackingBound = true;
- // bootstrap dropdowns
- if (classes.contains('dropdown')) {
- $(el).on('show.bs.dropdown', this.eventHandler(this.category, { suffix: '_show' }));
- $(el).on('hide.bs.dropdown', this.eventHandler(this.category, { suffix: '_hide' }));
- return true;
- }
-
- return false;
+ const handlers = eventHandlers(category, (...args) => this.event(...args));
+ handlers.forEach(event => el.addEventListener(event.name, event.func));
+ return handlers;
}
- eventHandler(category = null, opts = {}) {
- return e => {
- this.constructor.event(category || this.category, ...extractData(e.currentTarget, opts));
+ static mixin(opts) {
+ return {
+ data() {
+ return {
+ tracking: {
+ // eslint-disable-next-line no-underscore-dangle
+ category: this.$options.name || this.$options._componentTag,
+ },
+ };
+ },
+ methods: {
+ track(action, data) {
+ const category = opts.category || data.category || this.tracking.category;
+ Tracking.event(category || 'unspecified', action, { ...opts, ...this.tracking, ...data });
+ },
+ },
};
}
}
@@ -89,7 +96,7 @@ export default class Tracking {
export function initUserTracking() {
if (!Tracking.enabled()) return;
- const opts = Object.assign({}, DEFAULT_SNOWPLOW_OPTIONS, window.snowplowOptions);
+ const opts = { ...DEFAULT_SNOWPLOW_OPTIONS, ...window.snowplowOptions };
window.snowplow('newTracker', opts.namespace, opts.hostname, opts);
window.snowplow('enableActivityTracking', 30, 30);
@@ -97,4 +104,6 @@ export function initUserTracking() {
if (opts.formTracking) window.snowplow('enableFormTracking');
if (opts.linkClickTracking) window.snowplow('enableLinkClickTracking');
+
+ Tracking.bindDocument();
}
diff --git a/app/assets/stylesheets/framework/flash.scss b/app/assets/stylesheets/framework/flash.scss
index 7e7b08797b2..13a2a74fdab 100644
--- a/app/assets/stylesheets/framework/flash.scss
+++ b/app/assets/stylesheets/framework/flash.scss
@@ -12,7 +12,7 @@ $notification-box-shadow-color: rgba(0, 0, 0, 0.25);
position: sticky;
position: -webkit-sticky;
top: $flash-container-top;
- z-index: 200;
+ z-index: 251;
.flash-content {
box-shadow: 0 2px 4px 0 $notification-box-shadow-color;
diff --git a/app/models/repository.rb b/app/models/repository.rb
index f084a314392..96b1b55e2b1 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -133,18 +133,28 @@ class Repository
end
end
- def commits(ref = nil, path: nil, limit: nil, offset: nil, skip_merges: false, after: nil, before: nil, all: nil)
+ # the opts are:
+ # - :path
+ # - :limit
+ # - :offset
+ # - :skip_merges
+ # - :after
+ # - :before
+ # - :all
+ # - :first_parent
+ def commits(ref = nil, opts = {})
options = {
repo: raw_repository,
ref: ref,
- path: path,
- limit: limit,
- offset: offset,
- after: after,
- before: before,
- follow: Array(path).length == 1,
- skip_merges: skip_merges,
- all: all
+ path: opts[:path],
+ follow: Array(opts[:path]).length == 1,
+ limit: opts[:limit],
+ offset: opts[:offset],
+ skip_merges: !!opts[:skip_merges],
+ after: opts[:after],
+ before: opts[:before],
+ all: !!opts[:all],
+ first_parent: !!opts[:first_parent]
}
commits = Gitlab::Git::Commit.where(options)