diff --git a/Gemfile b/Gemfile index 3b637a02538..ef6061eb243 100644 --- a/Gemfile +++ b/Gemfile @@ -154,7 +154,7 @@ gem 'html-pipeline', '~> 2.13.2' gem 'deckar01-task_list', '2.3.1' gem 'gitlab-markup', '~> 1.7.1' gem 'github-markup', '~> 1.7.0', require: 'github/markup' -gem 'commonmarker', '~> 0.21' +gem 'commonmarker', '~> 0.23.2' gem 'kramdown', '~> 2.3.1' gem 'RedCloth', '~> 4.3.2' gem 'rdoc', '~> 6.3.2' @@ -474,7 +474,7 @@ end gem 'spamcheck', '~> 0.1.0' # Gitaly GRPC protocol definitions -gem 'gitaly', '~> 14.3.0.pre.rc1' +gem 'gitaly', '~> 14.3.0.pre.rc2' # KAS GRPC protocol definitions gem 'kas-grpc', '~> 0.0.2' diff --git a/Gemfile.lock b/Gemfile.lock index 99cd6b8bab6..f3d2860110e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -200,8 +200,7 @@ GEM open4 (~> 1.3) coderay (1.1.3) colored2 (3.1.2) - commonmarker (0.21.0) - ruby-enum (~> 0.5) + commonmarker (0.23.2) concurrent-ruby (1.1.9) connection_pool (2.2.2) contracts (0.11.0) @@ -453,7 +452,7 @@ GEM rails (>= 3.2.0) git (1.7.0) rchardet (~> 1.8) - gitaly (14.3.0.pre.rc1) + gitaly (14.3.0.pre.rc2) grpc (~> 1.0) github-markup (1.7.0) gitlab (4.16.1) @@ -1116,8 +1115,6 @@ GEM rubocop-rspec (1.44.1) rubocop (~> 0.87) rubocop-ast (>= 0.7.1) - ruby-enum (0.8.0) - i18n ruby-fogbugz (0.2.1) crack (~> 0.4) ruby-magic (0.4.0) @@ -1414,7 +1411,7 @@ DEPENDENCIES capybara-screenshot (~> 1.0.22) carrierwave (~> 1.3) charlock_holmes (~> 0.7.7) - commonmarker (~> 0.21) + commonmarker (~> 0.23.2) concurrent-ruby (~> 1.1) connection_pool (~> 2.0) countries (~> 3.0) @@ -1464,7 +1461,7 @@ DEPENDENCIES gettext (~> 3.3) gettext_i18n_rails (~> 1.8.0) gettext_i18n_rails_js (~> 1.3) - gitaly (~> 14.3.0.pre.rc1) + gitaly (~> 14.3.0.pre.rc2) github-markup (~> 1.7.0) gitlab-chronic (~> 0.10.5) gitlab-dangerfiles (~> 2.3.0) diff --git a/app/assets/javascripts/packages_and_registries/dependency_proxy/app.vue b/app/assets/javascripts/packages_and_registries/dependency_proxy/app.vue new file mode 100644 index 00000000000..7c2df91150b --- /dev/null +++ b/app/assets/javascripts/packages_and_registries/dependency_proxy/app.vue @@ -0,0 +1,83 @@ + + + diff --git a/app/assets/javascripts/packages_and_registries/dependency_proxy/index.js b/app/assets/javascripts/packages_and_registries/dependency_proxy/index.js new file mode 100644 index 00000000000..952953fb3b7 --- /dev/null +++ b/app/assets/javascripts/packages_and_registries/dependency_proxy/index.js @@ -0,0 +1,26 @@ +import Vue from 'vue'; +import { parseBoolean } from '~/lib/utils/common_utils'; +import app from '~/packages_and_registries/dependency_proxy/app.vue'; +import { apolloProvider } from '~/packages_and_registries/package_registry/graphql'; +import Translate from '~/vue_shared/translate'; + +Vue.use(Translate); + +export const initDependencyProxyApp = () => { + const el = document.getElementById('js-dependency-proxy'); + if (!el) { + return null; + } + const { dependencyProxyAvailable, ...dataset } = el.dataset; + return new Vue({ + el, + apolloProvider, + provide: { + dependencyProxyAvailable: parseBoolean(dependencyProxyAvailable), + ...dataset, + }, + render(createElement) { + return createElement(app); + }, + }); +}; diff --git a/app/assets/javascripts/pages/projects/new/components/new_project_url_select.vue b/app/assets/javascripts/pages/projects/new/components/new_project_url_select.vue index ba8858c985a..c30d3ec5db4 100644 --- a/app/assets/javascripts/pages/projects/new/components/new_project_url_select.vue +++ b/app/assets/javascripts/pages/projects/new/components/new_project_url_select.vue @@ -4,6 +4,7 @@ import { GlButtonGroup, GlDropdown, GlDropdownItem, + GlDropdownText, GlDropdownSectionHeader, GlLoadingIcon, GlSearchBoxByType, @@ -20,6 +21,7 @@ export default { GlButtonGroup, GlDropdown, GlDropdownItem, + GlDropdownText, GlDropdownSectionHeader, GlLoadingIcon, GlSearchBoxByType, @@ -57,8 +59,20 @@ export default { userNamespace() { return this.currentUser.namespace || {}; }, + hasGroupMatches() { + return this.userGroups.length; + }, + hasNamespaceMatches() { + return this.userNamespace.fullPath?.toLowerCase().includes(this.search.toLowerCase()); + }, + hasNoMatches() { + return !this.hasGroupMatches && !this.hasNamespaceMatches; + }, }, methods: { + focusInput() { + this.$refs.search.focusInput(); + }, handleClick({ id, fullPath }) { this.selectedNamespace = { id: getIdFromGraphQLId(id), @@ -78,18 +92,24 @@ export default { toggle-class="gl-rounded-top-right-base! gl-rounded-bottom-right-base!" data-qa-selector="select_namespace_dropdown" @show="track('activate_form_input', { label: trackLabel, property: 'project_path' })" + @shown="focusInput" > - + diff --git a/app/assets/javascripts/projects/settings/access_dropdown.js b/app/assets/javascripts/projects/settings/access_dropdown.js index a5e53ee3927..7fb7a416dca 100644 --- a/app/assets/javascripts/projects/settings/access_dropdown.js +++ b/app/assets/javascripts/projects/settings/access_dropdown.js @@ -2,8 +2,8 @@ import { escape, find, countBy } from 'lodash'; import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown'; import createFlash from '~/flash'; -import axios from '~/lib/utils/axios_utils'; import { n__, s__, __, sprintf } from '~/locale'; +import { getUsers, getGroups, getDeployKeys } from './api/access_dropdown_api'; import { LEVEL_TYPES, LEVEL_ID_PROP, ACCESS_LEVELS, ACCESS_LEVEL_NONE } from './constants'; export default class AccessDropdown { @@ -16,9 +16,6 @@ export default class AccessDropdown { this.accessLevelsData = accessLevelsData.roles; this.$dropdown = $dropdown; this.$wrap = this.$dropdown.closest(`.${this.accessLevel}-container`); - this.usersPath = '/-/autocomplete/users.json'; - this.groupsPath = '/-/autocomplete/project_groups.json'; - this.deployKeysPath = '/-/autocomplete/deploy_keys_with_owners.json'; this.defaultLabel = this.$dropdown.data('defaultLabel'); this.setSelectedItems([]); @@ -318,9 +315,9 @@ export default class AccessDropdown { getData(query, callback) { if (this.hasLicense) { Promise.all([ - this.getDeployKeys(query), - this.getUsers(query), - this.groupsData ? Promise.resolve(this.groupsData) : this.getGroups(), + getDeployKeys(query), + getUsers(query), + this.groupsData ? Promise.resolve(this.groupsData) : getGroups(), ]) .then(([deployKeysResponse, usersResponse, groupsResponse]) => { this.groupsData = groupsResponse; @@ -332,7 +329,7 @@ export default class AccessDropdown { createFlash({ message: __('Failed to load groups, users and deploy keys.') }); }); } else { - this.getDeployKeys(query) + getDeployKeys(query) .then((deployKeysResponse) => callback(this.consolidateData(deployKeysResponse.data))) .catch(() => createFlash({ message: __('Failed to load deploy keys.') })); } @@ -473,46 +470,6 @@ export default class AccessDropdown { return consolidatedData; } - getUsers(query) { - return axios.get(this.buildUrl(gon.relative_url_root, this.usersPath), { - params: { - search: query, - per_page: 20, - active: true, - project_id: gon.current_project_id, - push_code: true, - }, - }); - } - - getGroups() { - return axios.get(this.buildUrl(gon.relative_url_root, this.groupsPath), { - params: { - project_id: gon.current_project_id, - }, - }); - } - - getDeployKeys(query) { - return axios.get(this.buildUrl(gon.relative_url_root, this.deployKeysPath), { - params: { - search: query, - per_page: 20, - active: true, - project_id: gon.current_project_id, - push_code: true, - }, - }); - } - - buildUrl(urlRoot, url) { - let newUrl; - if (urlRoot != null) { - newUrl = urlRoot.replace(/\/$/, '') + url; - } - return newUrl; - } - renderRow(item) { let criteria = {}; let groupRowEl; diff --git a/app/assets/javascripts/projects/settings/api/access_dropdown_api.js b/app/assets/javascripts/projects/settings/api/access_dropdown_api.js new file mode 100644 index 00000000000..10f6c28a7bf --- /dev/null +++ b/app/assets/javascripts/projects/settings/api/access_dropdown_api.js @@ -0,0 +1,45 @@ +import axios from '~/lib/utils/axios_utils'; + +const USERS_PATH = '/-/autocomplete/users.json'; +const GROUPS_PATH = '/-/autocomplete/project_groups.json'; +const DEPLOY_KEYS_PATH = '/-/autocomplete/deploy_keys_with_owners.json'; + +const buildUrl = (urlRoot, url) => { + let newUrl; + if (urlRoot != null) { + newUrl = urlRoot.replace(/\/$/, '') + url; + } + return newUrl; +}; + +export const getUsers = (query) => { + return axios.get(buildUrl(gon.relative_url_root || '', USERS_PATH), { + params: { + search: query, + per_page: 20, + active: true, + project_id: gon.current_project_id, + push_code: true, + }, + }); +}; + +export const getGroups = () => { + return axios.get(buildUrl(gon.relative_url_root || '', GROUPS_PATH), { + params: { + project_id: gon.current_project_id, + }, + }); +}; + +export const getDeployKeys = (query) => { + return axios.get(buildUrl(gon.relative_url_root || '', DEPLOY_KEYS_PATH), { + params: { + search: query, + per_page: 20, + active: true, + project_id: gon.current_project_id, + push_code: true, + }, + }); +}; diff --git a/app/assets/javascripts/projects/settings/components/access_dropdown.vue b/app/assets/javascripts/projects/settings/components/access_dropdown.vue new file mode 100644 index 00000000000..35b001f8ef9 --- /dev/null +++ b/app/assets/javascripts/projects/settings/components/access_dropdown.vue @@ -0,0 +1,292 @@ + + + diff --git a/app/assets/javascripts/projects/settings/init_access_dropdown.js b/app/assets/javascripts/projects/settings/init_access_dropdown.js new file mode 100644 index 00000000000..9944b05d206 --- /dev/null +++ b/app/assets/javascripts/projects/settings/init_access_dropdown.js @@ -0,0 +1,28 @@ +import Vue from 'vue'; +import AccessDropdown from './components/access_dropdown.vue'; + +export const initAccessDropdown = (el, options) => { + if (!el) { + return false; + } + + const { accessLevelsData, accessLevel } = options; + + return new Vue({ + el, + render(createElement) { + const vm = this; + return createElement(AccessDropdown, { + props: { + accessLevel, + accessLevelsData: accessLevelsData.roles, + }, + on: { + select(selected) { + vm.$emit('select', selected); + }, + }, + }); + }, + }); +}; diff --git a/app/assets/javascripts/vue_shared/components/dismissible_feedback_alert.vue b/app/assets/javascripts/vue_shared/components/dismissible_feedback_alert.vue index c4dfcf93a18..014276c7e36 100644 --- a/app/assets/javascripts/vue_shared/components/dismissible_feedback_alert.vue +++ b/app/assets/javascripts/vue_shared/components/dismissible_feedback_alert.vue @@ -1,13 +1,11 @@