diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2019-11-22 18:06:00 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2019-11-22 18:06:00 +0000 |
commit | ea4762d464bb36f3e36e318db47086e41f493377 (patch) | |
tree | c2fb2b7d2eb2b775d9ab149dc3781975fcc4b7d5 /app/assets/javascripts | |
parent | 68b6846fa6c7b630cc8dab7a8474dcc34e4d67d4 (diff) | |
download | gitlab-ce-ea4762d464bb36f3e36e318db47086e41f493377.tar.gz |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets/javascripts')
10 files changed, 133 insertions, 122 deletions
diff --git a/app/assets/javascripts/api.js b/app/assets/javascripts/api.js index aee9990bc0b..6ec77186298 100644 --- a/app/assets/javascripts/api.js +++ b/app/assets/javascripts/api.js @@ -5,6 +5,8 @@ import { joinPaths } from './lib/utils/url_utility'; import flash from '~/flash'; import { __ } from '~/locale'; +const DEFAULT_PER_PAGE = 20; + const Api = { groupsPath: '/api/:version/groups.json', groupPath: '/api/:version/groups/:id', @@ -66,7 +68,7 @@ const Api = { params: Object.assign( { search: query, - per_page: 20, + per_page: DEFAULT_PER_PAGE, }, options, ), @@ -90,7 +92,7 @@ const Api = { .get(url, { params: { search: query, - per_page: 20, + per_page: DEFAULT_PER_PAGE, }, }) .then(({ data }) => callback(data)); @@ -101,7 +103,7 @@ const Api = { const url = Api.buildUrl(Api.projectsPath); const defaults = { search: query, - per_page: 20, + per_page: DEFAULT_PER_PAGE, simple: true, }; @@ -126,7 +128,7 @@ const Api = { .get(url, { params: { search: query, - per_page: 20, + per_page: DEFAULT_PER_PAGE, ...options, }, }) @@ -235,7 +237,7 @@ const Api = { const url = Api.buildUrl(Api.groupProjectsPath).replace(':id', groupId); const defaults = { search: query, - per_page: 20, + per_page: DEFAULT_PER_PAGE, }; return axios .get(url, { @@ -325,7 +327,7 @@ const Api = { params: Object.assign( { search: query, - per_page: 20, + per_page: DEFAULT_PER_PAGE, }, options, ), @@ -355,7 +357,7 @@ const Api = { const url = Api.buildUrl(Api.userProjectsPath).replace(':id', userId); const defaults = { search: query, - per_page: 20, + per_page: DEFAULT_PER_PAGE, }; return axios .get(url, { @@ -371,7 +373,7 @@ const Api = { return axios.get(url, { params: { search: query, - per_page: 20, + per_page: DEFAULT_PER_PAGE, ...options, }, }); @@ -403,10 +405,15 @@ const Api = { return axios.post(url); }, - releases(id) { + releases(id, options = {}) { const url = Api.buildUrl(this.releasesPath).replace(':id', encodeURIComponent(id)); - return axios.get(url); + return axios.get(url, { + params: { + per_page: DEFAULT_PER_PAGE, + ...options, + }, + }); }, release(projectPath, tagName) { diff --git a/app/assets/javascripts/notes/components/discussion_counter.vue b/app/assets/javascripts/notes/components/discussion_counter.vue index d7ffa0abb79..98f1f385e9b 100644 --- a/app/assets/javascripts/notes/components/discussion_counter.vue +++ b/app/assets/javascripts/notes/components/discussion_counter.vue @@ -19,6 +19,7 @@ export default { 'resolvableDiscussionsCount', 'firstUnresolvedDiscussionId', 'unresolvedDiscussionsCount', + 'getDiscussion', ]), isLoggedIn() { return this.getUserData.id; @@ -40,9 +41,10 @@ export default { ...mapActions(['expandDiscussion']), jumpToFirstUnresolvedDiscussion() { const diffTab = window.mrTabs.currentAction === 'diffs'; - const discussionId = this.firstUnresolvedDiscussionId(diffTab); - - this.jumpToDiscussion(discussionId); + const discussionId = + this.firstUnresolvedDiscussionId(diffTab) || this.firstUnresolvedDiscussionId(); + const firstDiscussion = this.getDiscussion(discussionId); + this.jumpToDiscussion(firstDiscussion); }, }, }; diff --git a/app/assets/javascripts/notes/components/discussion_keyboard_navigator.vue b/app/assets/javascripts/notes/components/discussion_keyboard_navigator.vue index 7fbfe8eebb2..7d742fbfeee 100644 --- a/app/assets/javascripts/notes/components/discussion_keyboard_navigator.vue +++ b/app/assets/javascripts/notes/components/discussion_keyboard_navigator.vue @@ -19,7 +19,11 @@ export default { }; }, computed: { - ...mapGetters(['nextUnresolvedDiscussionId', 'previousUnresolvedDiscussionId']), + ...mapGetters([ + 'nextUnresolvedDiscussionId', + 'previousUnresolvedDiscussionId', + 'getDiscussion', + ]), }, mounted() { Mousetrap.bind('n', () => this.jumpToNextDiscussion()); @@ -33,14 +37,14 @@ export default { ...mapActions(['expandDiscussion']), jumpToNextDiscussion() { const nextId = this.nextUnresolvedDiscussionId(this.currentDiscussionId, this.isDiffView); - - this.jumpToDiscussion(nextId); + const nextDiscussion = this.getDiscussion(nextId); + this.jumpToDiscussion(nextDiscussion); this.currentDiscussionId = nextId; }, jumpToPreviousDiscussion() { const prevId = this.previousUnresolvedDiscussionId(this.currentDiscussionId, this.isDiffView); - - this.jumpToDiscussion(prevId); + const prevDiscussion = this.getDiscussion(prevId); + this.jumpToDiscussion(prevDiscussion); this.currentDiscussionId = prevId; }, }, diff --git a/app/assets/javascripts/notes/components/noteable_discussion.vue b/app/assets/javascripts/notes/components/noteable_discussion.vue index 47ec740b63a..62d401d4911 100644 --- a/app/assets/javascripts/notes/components/noteable_discussion.vue +++ b/app/assets/javascripts/notes/components/noteable_discussion.vue @@ -84,6 +84,7 @@ export default { 'hasUnresolvedDiscussions', 'showJumpToNextDiscussion', 'getUserData', + 'getDiscussion', ]), currentUser() { return this.getUserData; @@ -221,8 +222,9 @@ export default { this.discussion.id, this.discussionsByDiffOrder, ); + const nextDiscussion = this.getDiscussion(nextId); - this.jumpToDiscussion(nextId); + this.jumpToDiscussion(nextDiscussion); }, deleteNoteHandler(note) { this.$emit('noteDeleted', this.discussion, note); diff --git a/app/assets/javascripts/notes/mixins/discussion_navigation.js b/app/assets/javascripts/notes/mixins/discussion_navigation.js index 3d89d907777..94ca01e44cc 100644 --- a/app/assets/javascripts/notes/mixins/discussion_navigation.js +++ b/app/assets/javascripts/notes/mixins/discussion_navigation.js @@ -35,20 +35,26 @@ export default { return false; }, - jumpToDiscussion(id) { + + switchToDiscussionsTabAndJumpTo(id) { + window.mrTabs.eventHub.$once('MergeRequestTabChange', () => { + setTimeout(() => this.discussionJump(id), 0); + }); + + window.mrTabs.tabShown('show'); + }, + + jumpToDiscussion(discussion) { + const { id, diff_discussion: isDiffDiscussion } = discussion; if (id) { const activeTab = window.mrTabs.currentAction; - if (activeTab === 'diffs') { + if (activeTab === 'diffs' && isDiffDiscussion) { this.diffsJump(id); - } else if (activeTab === 'commits' || activeTab === 'pipelines') { - window.mrTabs.eventHub.$once('MergeRequestTabChange', () => { - setTimeout(() => this.discussionJump(id), 0); - }); - - window.mrTabs.tabShown('show'); - } else { + } else if (activeTab === 'show') { this.discussionJump(id); + } else { + this.switchToDiscussionsTabAndJumpTo(id); } } }, diff --git a/app/assets/javascripts/releases/list/components/app.vue b/app/assets/javascripts/releases/list/components/app.vue index 5a06c4fec58..a414b3ccd4e 100644 --- a/app/assets/javascripts/releases/list/components/app.vue +++ b/app/assets/javascripts/releases/list/components/app.vue @@ -1,6 +1,12 @@ <script> import { mapState, mapActions } from 'vuex'; import { GlSkeletonLoading, GlEmptyState } from '@gitlab/ui'; +import { + getParameterByName, + historyPushState, + buildUrlWithCurrentLocation, +} from '~/lib/utils/common_utils'; +import TablePagination from '~/vue_shared/components/pagination/table_pagination.vue'; import ReleaseBlock from './release_block.vue'; export default { @@ -9,6 +15,7 @@ export default { GlSkeletonLoading, GlEmptyState, ReleaseBlock, + TablePagination, }, props: { projectId: { @@ -25,7 +32,7 @@ export default { }, }, computed: { - ...mapState(['isLoading', 'releases', 'hasError']), + ...mapState(['isLoading', 'releases', 'hasError', 'pageInfo']), shouldRenderEmptyState() { return !this.releases.length && !this.hasError && !this.isLoading; }, @@ -34,10 +41,17 @@ export default { }, }, created() { - this.fetchReleases(this.projectId); + this.fetchReleases({ + page: getParameterByName('page'), + projectId: this.projectId, + }); }, methods: { ...mapActions(['fetchReleases']), + onChangePage(page) { + historyPushState(buildUrlWithCurrentLocation(`?page=${page}`)); + this.fetchReleases({ page, projectId: this.projectId }); + }, }, }; </script> @@ -67,6 +81,8 @@ export default { :class="{ 'linked-card': releases.length > 1 && index !== releases.length - 1 }" /> </div> + + <table-pagination v-if="!isLoading" :change="onChangePage" :page-info="pageInfo" /> </div> </template> <style> diff --git a/app/assets/javascripts/releases/list/store/actions.js b/app/assets/javascripts/releases/list/store/actions.js index e0a922d5ef6..b15fb69226f 100644 --- a/app/assets/javascripts/releases/list/store/actions.js +++ b/app/assets/javascripts/releases/list/store/actions.js @@ -2,6 +2,7 @@ import * as types from './mutation_types'; import createFlash from '~/flash'; import { __ } from '~/locale'; import api from '~/api'; +import { normalizeHeaders, parseIntPagination } from '~/lib/utils/common_utils'; /** * Commits a mutation to update the state while the main endpoint is being requested. @@ -16,17 +17,19 @@ export const requestReleases = ({ commit }) => commit(types.REQUEST_RELEASES); * * @param {String} projectId */ -export const fetchReleases = ({ dispatch }, projectId) => { +export const fetchReleases = ({ dispatch }, { page = '1', projectId }) => { dispatch('requestReleases'); api - .releases(projectId) - .then(({ data }) => dispatch('receiveReleasesSuccess', data)) + .releases(projectId, { page }) + .then(response => dispatch('receiveReleasesSuccess', response)) .catch(() => dispatch('receiveReleasesError')); }; -export const receiveReleasesSuccess = ({ commit }, data) => - commit(types.RECEIVE_RELEASES_SUCCESS, data); +export const receiveReleasesSuccess = ({ commit }, { data, headers }) => { + const pageInfo = parseIntPagination(normalizeHeaders(headers)); + commit(types.RECEIVE_RELEASES_SUCCESS, { data, pageInfo }); +}; export const receiveReleasesError = ({ commit }) => { commit(types.RECEIVE_RELEASES_ERROR); diff --git a/app/assets/javascripts/releases/list/store/mutations.js b/app/assets/javascripts/releases/list/store/mutations.js index b97dc6cb0ab..99fc096264a 100644 --- a/app/assets/javascripts/releases/list/store/mutations.js +++ b/app/assets/javascripts/releases/list/store/mutations.js @@ -13,13 +13,15 @@ export default { * Sets isLoading to false. * Sets hasError to false. * Sets the received data + * Sets the received pagination information * @param {Object} state - * @param {Object} data + * @param {Object} resp */ - [types.RECEIVE_RELEASES_SUCCESS](state, data) { + [types.RECEIVE_RELEASES_SUCCESS](state, { data, pageInfo }) { state.hasError = false; state.isLoading = false; state.releases = data; + state.pageInfo = pageInfo; }, /** diff --git a/app/assets/javascripts/releases/list/store/state.js b/app/assets/javascripts/releases/list/store/state.js index bf25e651c99..c251f56c9c5 100644 --- a/app/assets/javascripts/releases/list/store/state.js +++ b/app/assets/javascripts/releases/list/store/state.js @@ -2,4 +2,5 @@ export default () => ({ isLoading: false, hasError: false, releases: [], + pageInfo: {}, }); diff --git a/app/assets/javascripts/users_select.js b/app/assets/javascripts/users_select.js index da1a7c290f8..57fbb88ca2e 100644 --- a/app/assets/javascripts/users_select.js +++ b/app/assets/javascripts/users_select.js @@ -1,4 +1,4 @@ -/* eslint-disable func-names, one-var, no-var, prefer-rest-params, vars-on-top, consistent-return, no-shadow, no-else-return, no-self-compare, no-unused-expressions, yoda, prefer-spread, camelcase, no-param-reassign */ +/* eslint-disable func-names, prefer-rest-params, consistent-return, no-shadow, no-else-return, no-self-compare, no-unused-expressions, yoda, prefer-spread, camelcase, no-param-reassign */ /* global Issuable */ /* global emitSidebarEvent */ @@ -13,7 +13,7 @@ import { parseBoolean } from './lib/utils/common_utils'; window.emitSidebarEvent = window.emitSidebarEvent || $.noop; function UsersSelect(currentUser, els, options = {}) { - var $els; + const $els = $(els || '.js-user-search'); this.users = this.users.bind(this); this.user = this.user.bind(this); this.usersPath = '/autocomplete/users.json'; @@ -28,36 +28,11 @@ function UsersSelect(currentUser, els, options = {}) { const { handleClick } = options; - $els = $(els); - - if (!els) { - $els = $('.js-user-search'); - } - $els.each( (function(_this) { return function(i, dropdown) { - var options = {}; - var $block, - $collapsedSidebar, - $dropdown, - $loading, - $selectbox, - $value, - abilityName, - assignTo, - assigneeTemplate, - collapsedAssigneeTemplate, - defaultLabel, - defaultNullUser, - firstUser, - issueURL, - selectedId, - selectedIdDefault, - showAnyUser, - showNullUser, - showMenuAbove; - $dropdown = $(dropdown); + const options = {}; + const $dropdown = $(dropdown); options.projectId = $dropdown.data('projectId'); options.groupId = $dropdown.data('groupId'); options.showCurrentUser = $dropdown.data('currentUser'); @@ -65,22 +40,25 @@ function UsersSelect(currentUser, els, options = {}) { options.todoStateFilter = $dropdown.data('todoStateFilter'); options.iid = $dropdown.data('iid'); options.issuableType = $dropdown.data('issuableType'); - showNullUser = $dropdown.data('nullUser'); - defaultNullUser = $dropdown.data('nullUserDefault'); - showMenuAbove = $dropdown.data('showMenuAbove'); - showAnyUser = $dropdown.data('anyUser'); - firstUser = $dropdown.data('firstUser'); + const showNullUser = $dropdown.data('nullUser'); + const defaultNullUser = $dropdown.data('nullUserDefault'); + const showMenuAbove = $dropdown.data('showMenuAbove'); + const showAnyUser = $dropdown.data('anyUser'); + const firstUser = $dropdown.data('firstUser'); options.authorId = $dropdown.data('authorId'); - defaultLabel = $dropdown.data('defaultLabel'); - issueURL = $dropdown.data('issueUpdate'); - $selectbox = $dropdown.closest('.selectbox'); - $block = $selectbox.closest('.block'); - abilityName = $dropdown.data('abilityName'); - $value = $block.find('.value'); - $collapsedSidebar = $block.find('.sidebar-collapsed-user'); - $loading = $block.find('.block-loading').fadeOut(); - selectedIdDefault = defaultNullUser && showNullUser ? 0 : null; - selectedId = $dropdown.data('selected'); + const defaultLabel = $dropdown.data('defaultLabel'); + const issueURL = $dropdown.data('issueUpdate'); + const $selectbox = $dropdown.closest('.selectbox'); + let $block = $selectbox.closest('.block'); + const abilityName = $dropdown.data('abilityName'); + let $value = $block.find('.value'); + const $collapsedSidebar = $block.find('.sidebar-collapsed-user'); + const $loading = $block.find('.block-loading').fadeOut(); + const selectedIdDefault = defaultNullUser && showNullUser ? 0 : null; + let selectedId = $dropdown.data('selected'); + let assignTo; + let assigneeTemplate; + let collapsedAssigneeTemplate; if (selectedId === undefined) { selectedId = selectedIdDefault; @@ -207,15 +185,15 @@ function UsersSelect(currentUser, els, options = {}) { }); assignTo = function(selected) { - var data; - data = {}; + const data = {}; data[abilityName] = {}; data[abilityName].assignee_id = selected != null ? selected : null; $loading.removeClass('hidden').fadeIn(); $dropdown.trigger('loading.gl.dropdown'); return axios.put(issueURL, data).then(({ data }) => { - var user, tooltipTitle; + let user = {}; + let tooltipTitle = user.name; $dropdown.trigger('loaded.gl.dropdown'); $loading.fadeOut(); if (data.assignee) { @@ -471,10 +449,9 @@ function UsersSelect(currentUser, els, options = {}) { } } - var isIssueIndex, isMRIndex, page, selected; - page = $('body').attr('data-page'); - isIssueIndex = page === 'projects:issues:index'; - isMRIndex = page === page && page === 'projects:merge_requests:index'; + const page = $('body').attr('data-page'); + const isIssueIndex = page === 'projects:issues:index'; + const isMRIndex = page === page && page === 'projects:merge_requests:index'; if ( $dropdown.hasClass('js-filter-bulk-update') || $dropdown.hasClass('js-issuable-form-dropdown') @@ -501,7 +478,7 @@ function UsersSelect(currentUser, els, options = {}) { } else if ($dropdown.hasClass('js-filter-submit')) { return $dropdown.closest('form').submit(); } else if (!$dropdown.hasClass('js-multiselect')) { - selected = $dropdown + const selected = $dropdown .closest('.selectbox') .find(`input[name='${$dropdown.data('fieldName')}']`) .val(); @@ -544,9 +521,8 @@ function UsersSelect(currentUser, els, options = {}) { }, updateLabel: $dropdown.data('dropdownTitle'), renderRow(user) { - var avatar, img, username; - username = user.username ? `@${user.username}` : ''; - avatar = user.avatar_url ? user.avatar_url : gon.default_avatar_url; + const username = user.username ? `@${user.username}` : ''; + const avatar = user.avatar_url ? user.avatar_url : gon.default_avatar_url; let selected = false; @@ -565,7 +541,7 @@ function UsersSelect(currentUser, els, options = {}) { selected = user.id === selectedId; } - img = ''; + let img = ''; if (user.beforeDivider != null) { `<li><a href='#' class='${selected === true ? 'is-active' : ''}'>${_.escape( user.name, @@ -586,35 +562,34 @@ function UsersSelect(currentUser, els, options = {}) { $('.ajax-users-select').each( (function(_this) { return function(i, select) { - var firstUser, showAnyUser, showEmailUser, showNullUser; - var options = {}; + const options = {}; options.skipLdap = $(select).hasClass('skip_ldap'); options.projectId = $(select).data('projectId'); options.groupId = $(select).data('groupId'); options.showCurrentUser = $(select).data('currentUser'); options.authorId = $(select).data('authorId'); options.skipUsers = $(select).data('skipUsers'); - showNullUser = $(select).data('nullUser'); - showAnyUser = $(select).data('anyUser'); - showEmailUser = $(select).data('emailUser'); - firstUser = $(select).data('firstUser'); + const showNullUser = $(select).data('nullUser'); + const showAnyUser = $(select).data('anyUser'); + const showEmailUser = $(select).data('emailUser'); + const firstUser = $(select).data('firstUser'); return $(select).select2({ placeholder: __('Search for a user'), multiple: $(select).hasClass('multiselect'), minimumInputLength: 0, query(query) { return _this.users(query.term, options, users => { - var anyUser, data, emailUser, index, len, name, nullUser, obj, ref; - data = { + let name; + const data = { results: users, }; if (query.term.length === 0) { if (firstUser) { // Move current user to the front of the list - ref = data.results; + const ref = data.results; - for (index = 0, len = ref.length; index < len; index += 1) { - obj = ref[index]; + for (let index = 0, len = ref.length; index < len; index += 1) { + const obj = ref[index]; if (obj.username === firstUser) { data.results.splice(index, 1); data.results.unshift(obj); @@ -623,7 +598,7 @@ function UsersSelect(currentUser, els, options = {}) { } } if (showNullUser) { - nullUser = { + const nullUser = { name: s__('UsersSelect|Unassigned'), id: 0, }; @@ -634,7 +609,7 @@ function UsersSelect(currentUser, els, options = {}) { if (name === true) { name = s__('UsersSelect|Any User'); } - anyUser = { + const anyUser = { name, id: null, }; @@ -646,8 +621,8 @@ function UsersSelect(currentUser, els, options = {}) { data.results.length === 0 && query.term.match(/^[^@]+@[^@]+$/) ) { - var trimmed = query.term.trim(); - emailUser = { + const trimmed = query.term.trim(); + const emailUser = { name: sprintf(__('Invite "%{trimmed}" by email'), { trimmed }), username: trimmed, id: trimmed, @@ -659,18 +634,15 @@ function UsersSelect(currentUser, els, options = {}) { }); }, initSelection() { - var args; - args = 1 <= arguments.length ? [].slice.call(arguments, 0) : []; + const args = 1 <= arguments.length ? [].slice.call(arguments, 0) : []; return _this.initSelection.apply(_this, args); }, formatResult() { - var args; - args = 1 <= arguments.length ? [].slice.call(arguments, 0) : []; + const args = 1 <= arguments.length ? [].slice.call(arguments, 0) : []; return _this.formatResult.apply(_this, args); }, formatSelection() { - var args; - args = 1 <= arguments.length ? [].slice.call(arguments, 0) : []; + const args = 1 <= arguments.length ? [].slice.call(arguments, 0) : []; return _this.formatSelection.apply(_this, args); }, dropdownCssClass: 'ajax-users-dropdown', @@ -687,10 +659,9 @@ function UsersSelect(currentUser, els, options = {}) { } UsersSelect.prototype.initSelection = function(element, callback) { - var id, nullUser; - id = $(element).val(); + const id = $(element).val(); if (id === '0') { - nullUser = { + const nullUser = { name: s__('UsersSelect|Unassigned'), }; return callback(nullUser); @@ -700,11 +671,9 @@ UsersSelect.prototype.initSelection = function(element, callback) { }; UsersSelect.prototype.formatResult = function(user) { - var avatar; + let avatar = gon.default_avatar_url; if (user.avatar_url) { avatar = user.avatar_url; - } else { - avatar = gon.default_avatar_url; } return ` <div class='user-result'> @@ -732,8 +701,7 @@ UsersSelect.prototype.user = function(user_id, callback) { return false; } - var url; - url = this.buildUrl(this.userPath); + let url = this.buildUrl(this.userPath); url = url.replace(':id', user_id); return axios.get(url).then(({ data }) => { callback(data); |