Skip to content
Snippets Groups Projects
Commit e66d6781 authored by GitLab Bot's avatar GitLab Bot
Browse files

Add latest changes from gitlab-org/gitlab@master

parent 4e9f718e
No related branches found
No related tags found
No related merge requests found
Showing
with 149 additions and 105 deletions
Loading
Loading
@@ -17,7 +17,7 @@
- [ ] Follow the [Documentation Guidelines](https://docs.gitlab.com/ee/development/documentation/) and [Style Guide](https://docs.gitlab.com/ee/development/documentation/styleguide.html).
- [ ] If applicable, update the [permissions table](https://docs.gitlab.com/ee/user/permissions.html).
- [ ] Link docs to and from the higher-level index page, plus other related docs where helpful.
- [ ] Apply the ~Documentation label.
- [ ] Apply the ~documentation label.
 
## Review checklist
 
Loading
Loading
Loading
Loading
@@ -4,96 +4,97 @@ import Api from './api';
import { normalizeHeaders } from './lib/utils/common_utils';
import { __ } from '~/locale';
 
export default function groupsSelect() {
import(/* webpackChunkName: 'select2' */ 'select2/select2')
.then(() => {
// Needs to be accessible in rspec
window.GROUP_SELECT_PER_PAGE = 20;
$('.ajax-groups-select').each(function setAjaxGroupsSelect2() {
const $select = $(this);
const allAvailable = $select.data('allAvailable');
const skipGroups = $select.data('skipGroups') || [];
const parentGroupID = $select.data('parentId');
const groupsPath = parentGroupID
? Api.subgroupsPath.replace(':id', parentGroupID)
: Api.groupsPath;
const groupsSelect = () => {
// Needs to be accessible in rspec
window.GROUP_SELECT_PER_PAGE = 20;
$('.ajax-groups-select').each(function setAjaxGroupsSelect2() {
const $select = $(this);
const allAvailable = $select.data('allAvailable');
const skipGroups = $select.data('skipGroups') || [];
const parentGroupID = $select.data('parentId');
const groupsPath = parentGroupID
? Api.subgroupsPath.replace(':id', parentGroupID)
: Api.groupsPath;
 
$select.select2({
placeholder: __('Search for a group'),
allowClear: $select.hasClass('allowClear'),
multiple: $select.hasClass('multiselect'),
minimumInputLength: 0,
ajax: {
url: Api.buildUrl(groupsPath),
dataType: 'json',
quietMillis: 250,
transport(params) {
axios[params.type.toLowerCase()](params.url, {
params: params.data,
})
.then(res => {
const results = res.data || [];
const headers = normalizeHeaders(res.headers);
const currentPage = parseInt(headers['X-PAGE'], 10) || 0;
const totalPages = parseInt(headers['X-TOTAL-PAGES'], 10) || 0;
const more = currentPage < totalPages;
$select.select2({
placeholder: __('Search for a group'),
allowClear: $select.hasClass('allowClear'),
multiple: $select.hasClass('multiselect'),
minimumInputLength: 0,
ajax: {
url: Api.buildUrl(groupsPath),
dataType: 'json',
quietMillis: 250,
transport(params) {
axios[params.type.toLowerCase()](params.url, {
params: params.data,
})
.then(res => {
const results = res.data || [];
const headers = normalizeHeaders(res.headers);
const currentPage = parseInt(headers['X-PAGE'], 10) || 0;
const totalPages = parseInt(headers['X-TOTAL-PAGES'], 10) || 0;
const more = currentPage < totalPages;
 
params.success({
results,
pagination: {
more,
},
});
})
.catch(params.error);
},
data(search, page) {
return {
search,
page,
per_page: window.GROUP_SELECT_PER_PAGE,
all_available: allAvailable,
};
},
results(data, page) {
if (data.length) return { results: [] };
params.success({
results,
pagination: {
more,
},
});
})
.catch(params.error);
},
data(search, page) {
return {
search,
page,
per_page: window.GROUP_SELECT_PER_PAGE,
all_available: allAvailable,
};
},
results(data, page) {
if (data.length) return { results: [] };
 
const groups = data.length ? data : data.results || [];
const more = data.pagination ? data.pagination.more : false;
const results = groups.filter(group => skipGroups.indexOf(group.id) === -1);
const groups = data.length ? data : data.results || [];
const more = data.pagination ? data.pagination.more : false;
const results = groups.filter(group => skipGroups.indexOf(group.id) === -1);
 
return {
results,
page,
more,
};
},
},
// eslint-disable-next-line consistent-return
initSelection(element, callback) {
const id = $(element).val();
if (id !== '') {
return Api.group(id, callback);
}
},
formatResult(object) {
return `<div class='group-result'> <div class='group-name'>${object.full_name}</div> <div class='group-path'>${object.full_path}</div> </div>`;
},
formatSelection(object) {
return object.full_name;
},
dropdownCssClass: 'ajax-groups-dropdown select2-infinite',
// we do not want to escape markup since we are displaying html in results
escapeMarkup(m) {
return m;
},
});
return {
results,
page,
more,
};
},
},
// eslint-disable-next-line consistent-return
initSelection(element, callback) {
const id = $(element).val();
if (id !== '') {
return Api.group(id, callback);
}
},
formatResult(object) {
return `<div class='group-result'> <div class='group-name'>${object.full_name}</div> <div class='group-path'>${object.full_path}</div> </div>`;
},
formatSelection(object) {
return object.full_name;
},
dropdownCssClass: 'ajax-groups-dropdown select2-infinite',
// we do not want to escape markup since we are displaying html in results
escapeMarkup(m) {
return m;
},
});
 
$select.on('select2-loaded', () => {
const dropdown = document.querySelector('.select2-infinite .select2-results');
dropdown.style.height = `${Math.floor(dropdown.scrollHeight)}px`;
});
});
})
$select.on('select2-loaded', () => {
const dropdown = document.querySelector('.select2-infinite .select2-results');
dropdown.style.height = `${Math.floor(dropdown.scrollHeight)}px`;
});
});
};
export default () =>
import(/* webpackChunkName: 'select2' */ 'select2/select2')
.then(groupsSelect)
.catch(() => {});
}
Loading
Loading
@@ -120,7 +120,7 @@ export default class LabelsSelect {
labelCount = 0;
if (data.labels.length && issueUpdateURL) {
template = LabelsSelect.getLabelTemplate({
labels: data.labels,
labels: _.sortBy(data.labels, 'title'),
issueUpdateURL,
enableScopedLabels: scopedLabels,
scopedLabelsDocumentationLink,
Loading
Loading
# frozen_string_literal: true
 
class Import::BitbucketController < Import::BaseController
include ActionView::Helpers::SanitizeHelper
before_action :verify_bitbucket_import_enabled
before_action :bitbucket_auth, except: :callback
 
Loading
Loading
@@ -21,7 +23,7 @@ class Import::BitbucketController < Import::BaseController
# rubocop: disable CodeReuse/ActiveRecord
def status
bitbucket_client = Bitbucket::Client.new(credentials)
repos = bitbucket_client.repos
repos = bitbucket_client.repos(filter: sanitized_filter_param)
 
@repos, @incompatible_repos = repos.partition { |repo| repo.valid? }
 
Loading
Loading
@@ -104,4 +106,8 @@ class Import::BitbucketController < Import::BaseController
refresh_token: session[:bitbucket_refresh_token]
}
end
def sanitized_filter_param
@filter ||= sanitize(params[:filter])
end
end
Loading
Loading
@@ -9,6 +9,7 @@ module Groups
 
def execute
remove_unallowed_params
set_visibility_level
 
@group = Group.new(params)
 
Loading
Loading
@@ -68,6 +69,12 @@ module Groups
 
true
end
def set_visibility_level
return if visibility_level.present?
params[:visibility_level] = Gitlab::CurrentSettings.current_application_settings.default_group_visibility
end
end
end
 
Loading
Loading
Loading
Loading
@@ -8,7 +8,6 @@
- if @repos.any?
%p.light
= _('Select projects you want to import.')
%hr
%p
- if @incompatible_repos.any?
= button_tag class: 'btn btn-import btn-success js-import-all' do
Loading
Loading
@@ -19,6 +18,14 @@
= _('Import all projects')
= icon('spinner spin', class: 'loading-icon')
 
.position-relative.ms-no-clear.d-flex.flex-fill.float-right.append-bottom-10
= form_tag status_import_bitbucket_path, method: 'get' do
= text_field_tag :filter, @filter, class: 'form-control pr-5', placeholder: _('Filter projects'), size: 40, autofocus: true, 'aria-label': _('Search')
.position-absolute.position-top-0.d-flex.align-items-center.text-muted.position-right-0.h-100
.border-left
%button{ class: 'btn btn-transparent btn-secondary', 'aria-label': _('Search Button'), type: 'submit' }
%i{ class: 'fa fa-search', 'aria-hidden': true }
.table-responsive
%table.table.import-jobs
%colgroup.import-jobs-from-col
Loading
Loading
@@ -59,7 +66,7 @@
- if current_user.can_select_namespace?
- selected = params[:namespace_id] || :current_user
- opts = current_user.can_create_group? ? { extra_group: Group.new(name: repo.owner, path: repo.owner) } : {}
= select_tag :namespace_id, namespaces_options(selected, opts.merge({ display_path: true })), { class: 'input-group-text select2 js-select-namespace', tabindex: 1 }
= select_tag :namespace_id, namespaces_options(selected, opts.merge({ display_path: true })), { class: 'select2 js-select-namespace', tabindex: 1 }
- else
= text_field_tag :path, current_user.namespace_path, class: "input-group-text input-large form-control", tabindex: 1, disabled: true
%span.input-group-prepend
Loading
Loading
Loading
Loading
@@ -62,7 +62,7 @@
- if current_user.can_select_namespace?
- selected = params[:namespace_id] || :extra_group
- opts = current_user.can_create_group? ? { extra_group: Group.new(name: sanitize_project_name(repo.project_key), path: sanitize_project_name(repo.project_key)) } : {}
= select_tag :namespace_id, namespaces_options(selected, opts.merge({ display_path: true })), { class: 'input-group-text select2 js-select-namespace', tabindex: 1 }
= select_tag :namespace_id, namespaces_options(selected, opts.merge({ display_path: true })), { class: 'select2 js-select-namespace', tabindex: 1 }
- else
= text_field_tag :path, current_user.namespace_path, class: "input-group-text input-large form-control", tabindex: 1, disabled: true
%span.input-group-prepend
Loading
Loading
---
title: Alphabetically sorts selected sidebar labels.
merge_request: 17309
author:
type: fixed
---
title: 'Allow to exclude ancestor groups on group labels API'
merge_request: 17221
author: Mathieu Parent
type: added
---
title: Add project filtering to Bitbucket Cloud import
merge_request: 16828
author:
type: added
---
title: Fix visibility level error when updating group from API
merge_request: 17227
author: Mathieu Parent
type: fixed
---
title: Remove Postgresql specific setup tasks and move to schema.rb
merge_request:
author:
type: other
Loading
Loading
@@ -20,9 +20,7 @@ class ReworkRedirectRoutesIndexes < ActiveRecord::Migration[4.2]
def up
disable_statement_timeout do
# this is a plain btree on a single boolean column. It'll never be
# selective enough to be valuable. This class is called by
# setup_postgresql.rake so it needs to be able to handle this
# index not existing.
# selective enough to be valuable.
if index_exists?(:redirect_routes, :permanent)
remove_concurrent_index(:redirect_routes, :permanent)
end
Loading
Loading
Loading
Loading
@@ -14,9 +14,7 @@ class AddPathIndexToRedirectRoutes < ActiveRecord::Migration[4.2]
# RedirectRoute.matching_path_and_descendants
#
# This same index is also added in the `ReworkRedirectRoutesIndexes` so this
# is a no-op in most cases. But this migration is also called from the
# `setup_postgresql.rake` task when setting up a new database, in which case
# we want to create the index.
# is a no-op in most cases.
def up
return unless Gitlab::Database.postgresql?
 
Loading
Loading
@@ -31,8 +29,5 @@ class AddPathIndexToRedirectRoutes < ActiveRecord::Migration[4.2]
# Do nothing in the DOWN. Since the index above is originally created in the
# `ReworkRedirectRoutesIndexes`. This migration wouldn't have actually
# created any new index.
#
# This migration is only here to be called form `setup_postgresql.rake` so
# any newly created database would have this index.
end
end
Loading
Loading
@@ -2917,6 +2917,7 @@ ActiveRecord::Schema.define(version: 2019_09_26_041216) do
t.boolean "emails_disabled"
t.integer "max_pages_size"
t.integer "max_artifacts_size"
t.index "lower((name)::text)", name: "index_projects_on_lower_name"
t.index ["archived", "pending_delete", "merge_requests_require_code_owner_approval"], name: "projects_requiring_code_owner_approval", where: "((pending_delete = false) AND (archived = false) AND (merge_requests_require_code_owner_approval = true))"
t.index ["created_at"], name: "index_projects_on_created_at"
t.index ["creator_id"], name: "index_projects_on_creator_id"
Loading
Loading
@@ -3113,6 +3114,7 @@ ActiveRecord::Schema.define(version: 2019_09_26_041216) do
t.string "path", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index "lower((path)::text) varchar_pattern_ops", name: "index_redirect_routes_on_path_unique_text_pattern_ops", unique: true
t.index ["path"], name: "index_redirect_routes_on_path", unique: true
t.index ["source_type", "source_id"], name: "index_redirect_routes_on_source_type_and_source_id"
end
Loading
Loading
@@ -3641,6 +3643,7 @@ ActiveRecord::Schema.define(version: 2019_09_26_041216) do
t.string "first_name", limit: 255
t.string "last_name", limit: 255
t.string "static_object_token", limit: 255
t.index "lower((name)::text)", name: "index_on_users_name_lower"
t.index ["accepted_term_id"], name: "index_users_on_accepted_term_id"
t.index ["admin"], name: "index_users_on_admin"
t.index ["bot_type"], name: "index_users_on_bot_type"
Loading
Loading
Loading
Loading
@@ -16,6 +16,7 @@ GET /groups/:id/labels
| --------- | ---- | -------- | ----------- |
| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) owned by the authenticated user. |
| `with_counts` | boolean | no | Whether or not to include issue and merge request counts. Defaults to `false`. _([Introduced in GitLab 12.2](https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/31543))_ |
| `include_ancestor_groups` | boolean | no | Include ancestor groups. Defaults to `true`. |
 
```bash
curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/groups/5/labels?with_counts=true
Loading
Loading
Loading
Loading
@@ -12,6 +12,7 @@ GET /projects/:id/labels
| --------- | ------- | -------- | --------------------- |
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
| `with_counts` | boolean | no | Whether or not to include issue and merge request counts. Defaults to `false`. _([Introduced in GitLab 12.2](https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/31543))_ |
| `include_ancestor_groups` | boolean | no | Include ancestor groups. Defaults to `true`. |
 
```bash
curl --header "PRIVATE-TOKEN: <your_access_token>" https://gitlab.example.com/api/v4/projects/1/labels?with_counts=true
Loading
Loading
Loading
Loading
@@ -56,10 +56,10 @@ namespace that started the import process.
![Grant access](img/bitbucket_import_grant_access.png)
 
1. Click on the projects that you'd like to import or **Import all projects**.
You can also select the namespace under which each project will be
imported.
You can also filter projects by name and select the namespace under which
each project will be imported.
 
![Import projects](img/bitbucket_import_select_project.png)
![Import projects](img/bitbucket_import_select_project_v12_3.png)
 
[bb-import]: ../../../integration/bitbucket.md
[social sign-in]: ../../profile/account/social_sign_in.md
doc/user/project/import/img/bitbucket_import_select_project.png

8.48 KiB

doc/user/project/import/img/bitbucket_import_select_project_v12_3.png

110 KiB

0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment