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
diff options
context:
space:
mode:
-rw-r--r--app/assets/javascripts/api.js1
-rw-r--r--app/assets/javascripts/groups_select.js7
-rw-r--r--app/assets/javascripts/pages/groups/edit/index.js4
-rw-r--r--app/assets/stylesheets/framework/callout.scss6
-rw-r--r--app/services/projects/create_service.rb2
-rw-r--r--app/views/groups/edit.html.haml1
-rw-r--r--app/views/projects/new.html.haml2
-rw-r--r--app/views/projects/project_templates/_built_in_templates.html.haml6
-rw-r--r--doc/user/admin_area/custom_project_templates.md25
-rw-r--r--doc/user/group/custom_project_templates.md23
-rw-r--r--doc/user/group/index.md5
-rw-r--r--spec/migrations/clean_up_for_members_spec.rb5
-rw-r--r--spec/migrations/delete_inconsistent_internal_id_records_spec.rb15
13 files changed, 86 insertions, 16 deletions
diff --git a/app/assets/javascripts/api.js b/app/assets/javascripts/api.js
index 0da7ae1b229..f8dbe412f80 100644
--- a/app/assets/javascripts/api.js
+++ b/app/assets/javascripts/api.js
@@ -5,6 +5,7 @@ import axios from './lib/utils/axios_utils';
const Api = {
groupsPath: '/api/:version/groups.json',
groupPath: '/api/:version/groups/:id',
+ subgroupsPath: '/api/:version/groups/:id/subgroups',
namespacesPath: '/api/:version/namespaces.json',
groupProjectsPath: '/api/:version/groups/:id/projects.json',
projectsPath: '/api/:version/projects.json',
diff --git a/app/assets/javascripts/groups_select.js b/app/assets/javascripts/groups_select.js
index b4a3037c1b7..2049760fe29 100644
--- a/app/assets/javascripts/groups_select.js
+++ b/app/assets/javascripts/groups_select.js
@@ -10,13 +10,18 @@ export default function groupsSelect() {
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(Api.groupsPath),
+ url: Api.buildUrl(groupsPath),
dataType: 'json',
quietMillis: 250,
transport(params) {
diff --git a/app/assets/javascripts/pages/groups/edit/index.js b/app/assets/javascripts/pages/groups/edit/index.js
index 32b55575f95..01ef445c901 100644
--- a/app/assets/javascripts/pages/groups/edit/index.js
+++ b/app/assets/javascripts/pages/groups/edit/index.js
@@ -5,6 +5,7 @@ import initSettingsPanels from '~/settings_panels';
import dirtySubmitFactory from '~/dirty_submit/dirty_submit_factory';
import mountBadgeSettings from '~/pages/shared/mount_badge_settings';
import { GROUP_BADGE } from '~/badges/constants';
+import groupsSelect from '~/groups_select';
import projectSelect from '~/project_select';
document.addEventListener('DOMContentLoaded', () => {
@@ -17,5 +18,8 @@ document.addEventListener('DOMContentLoaded', () => {
);
mountBadgeSettings(GROUP_BADGE);
+ // Initialize Subgroups selector
+ groupsSelect();
+
projectSelect();
});
diff --git a/app/assets/stylesheets/framework/callout.scss b/app/assets/stylesheets/framework/callout.scss
index bdd7f09d926..0d8e4afa76f 100644
--- a/app/assets/stylesheets/framework/callout.scss
+++ b/app/assets/stylesheets/framework/callout.scss
@@ -33,7 +33,11 @@
.bs-callout-warning {
background-color: $orange-100;
border-color: $orange-200;
- color: $orange-700;
+ color: $orange-900;
+
+ a {
+ color: $orange-900;
+ }
}
.bs-callout-info {
diff --git a/app/services/projects/create_service.rb b/app/services/projects/create_service.rb
index 2458f5b308a..9e77a3237e3 100644
--- a/app/services/projects/create_service.rb
+++ b/app/services/projects/create_service.rb
@@ -9,7 +9,7 @@ module Projects
end
def execute
- if @params[:template_name]&.present?
+ if @params[:template_name].present?
return ::Projects::CreateFromTemplateService.new(current_user, params).execute
end
diff --git a/app/views/groups/edit.html.haml b/app/views/groups/edit.html.haml
index 869c54d89ea..39d0f620283 100644
--- a/app/views/groups/edit.html.haml
+++ b/app/views/groups/edit.html.haml
@@ -37,6 +37,7 @@
.settings-content
= render 'shared/badges/badge_settings'
+= render_if_exists 'groups/custom_project_templates_setting'
= render_if_exists 'groups/templates_setting', expanded: expanded
%section.settings.gs-advanced.no-animate#js-advanced-settings{ class: ('expanded' if expanded) }
diff --git a/app/views/projects/new.html.haml b/app/views/projects/new.html.haml
index 10e3b01096a..a760d02c4c3 100644
--- a/app/views/projects/new.html.haml
+++ b/app/views/projects/new.html.haml
@@ -50,7 +50,7 @@
.project-template
.form-group
%div
- = render 'project_templates', f: f
+ = render 'project_templates', f: f, project: @project
.tab-pane.import-project-pane.js-toggle-container{ id: 'import-project-pane', class: active_when(active_tab == 'import'), role: 'tabpanel' }
- if import_sources_enabled?
diff --git a/app/views/projects/project_templates/_built_in_templates.html.haml b/app/views/projects/project_templates/_built_in_templates.html.haml
index 233c3adba0e..5b4d8927045 100644
--- a/app/views/projects/project_templates/_built_in_templates.html.haml
+++ b/app/views/projects/project_templates/_built_in_templates.html.haml
@@ -9,9 +9,9 @@
.text-muted
= template.description
.controls.d-flex.align-items-center
- %label.btn.btn-success.template-button.choose-template.append-right-10.append-bottom-0{ for: template.name }
+ %a.btn.btn-default.append-right-10{ href: template.preview, rel: 'noopener noreferrer', target: '_blank', data: { track_label: "create_from_template", track_property: "template_preview", track_event: "click_button", track_value: template.name } }
+ = _("Preview")
+ %label.btn.btn-success.template-button.choose-template.append-bottom-0{ for: template.name }
%input{ type: "radio", autocomplete: "off", name: "project[template_name]", id: template.name, value: template.name, data: { track_label: "create_from_template", track_property: "template_use", track_event: "click_button" } }
%span
= _("Use template")
- %a.btn.btn-default{ href: template.preview, rel: 'noopener noreferrer', target: '_blank', data: { track_label: "create_from_template", track_property: "template_preview", track_event: "click_button", track_value: template.name } }
- = _("Preview")
diff --git a/doc/user/admin_area/custom_project_templates.md b/doc/user/admin_area/custom_project_templates.md
new file mode 100644
index 00000000000..5afbf9f2934
--- /dev/null
+++ b/doc/user/admin_area/custom_project_templates.md
@@ -0,0 +1,25 @@
+# Custom instance-level project templates **[PREMIUM ONLY]**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/6860) in [GitLab Premium](https://about.gitlab.com/pricing) 11.2.
+
+When you create a new project, creating it based on custom project templates is
+a convenient option to bootstrap from an existing project boilerplate.
+The administration setting to configure a GitLab group that serves as template
+source can be found under **Admin > Settings > Custom project templates**.
+
+Within this section, you can configure the group where all the custom project
+templates are sourced. Every project directly under the group namespace will be
+available to the user if they have access to them. For example, every public
+project in the group will be available to every logged user. However,
+private projects will be available only if the user has view [permissions](../permissions.md)
+in the project:
+
+- Project Owner, Maintainer, Developer, Reporter or Guest
+- Is a member of the Group: Owner, Maintainer, Developer, Reporter or Guest
+
+Projects below subgroups of the template group are **not** supported.
+
+Repository and database information that are copied over to each new project are
+identical to the data exported with [GitLab's Project Import/Export](../project/settings/import_export.md).
+
+If you would like to set project templates at a group level, please see [Custom group-level project templates](../group/custom_project_templates.md). \ No newline at end of file
diff --git a/doc/user/group/custom_project_templates.md b/doc/user/group/custom_project_templates.md
new file mode 100644
index 00000000000..eaf0273050b
--- /dev/null
+++ b/doc/user/group/custom_project_templates.md
@@ -0,0 +1,23 @@
+# Custom group-level project templates **[PREMIUM ONLY]**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/6861) in [GitLab Premium](https://about.gitlab.com/pricing) 11.6.
+
+When you create a new project, creating it based on custom project templates is
+a convenient option to bootstrap from an existing project boilerplate.
+The group-level setting to configure a GitLab group that serves as template
+source can be found under **Group > Settings > General > Custom project templates**.
+
+Within this section, you can configure the group where all the custom project
+templates are sourced. Every project directly under the group namespace will be
+available to the user if they have access to them. For example, every public
+project in the group will be available to every logged in user. However,
+private projects will be available only if the user has view [permissions](../permissions.md)
+in the project. That is, users with Owner, Maintainer, Developer, Reporter or Guest roles for projects,
+or for groups to which the project belongs.
+
+Projects of nested subgroups of a selected template source cannot be used.
+
+Repository and database information that are copied over to each new project are
+identical to the data exported with [GitLab's Project Import/Export](../project/settings/import_export.md).
+
+If you would like to set project templates at an instance level, please see [Custom instance-level project templates](../admin_area/custom_project_templates.md). \ No newline at end of file
diff --git a/doc/user/group/index.md b/doc/user/group/index.md
index d673fa4d21a..36b9318c0e0 100644
--- a/doc/user/group/index.md
+++ b/doc/user/group/index.md
@@ -259,6 +259,11 @@ types with every project in a group.
Learn more about [Group-level file templates](https://docs.gitlab.com/ee/user/group/index.html#group-level-file-templates-premium).
+#### Group-level project templates **[PREMIUM]**
+
+Define project templates at a group-level by setting a group as a template source.
+[Learn more about group-level project templates](custom_project_templates.md).
+
### Advanced settings
- **Projects**: view all projects within that group, add members to each project,
diff --git a/spec/migrations/clean_up_for_members_spec.rb b/spec/migrations/clean_up_for_members_spec.rb
index 0258860d169..7876536cb3e 100644
--- a/spec/migrations/clean_up_for_members_spec.rb
+++ b/spec/migrations/clean_up_for_members_spec.rb
@@ -3,6 +3,7 @@ require Rails.root.join('db', 'migrate', '20171216111734_clean_up_for_members.rb
describe CleanUpForMembers, :migration do
let(:migration) { described_class.new }
+ let(:groups) { table(:namespaces) }
let!(:group_member) { create_group_member }
let!(:unbinded_group_member) { create_group_member }
let!(:invited_group_member) { create_group_member(true) }
@@ -25,7 +26,7 @@ describe CleanUpForMembers, :migration do
end
def create_group_member(invited = false)
- fill_member(GroupMember.new(group: create_group), invited)
+ fill_member(GroupMember.new(source_id: create_group.id, source_type: 'Namespace'), invited)
end
def create_project_member(invited = false)
@@ -54,7 +55,7 @@ describe CleanUpForMembers, :migration do
def create_group
name = FFaker::Lorem.characters(10)
- Group.create(name: name, path: name.downcase.gsub(/\s/, '_'))
+ groups.create!(type: 'Group', name: name, path: name.downcase.gsub(/\s/, '_'))
end
def create_project
diff --git a/spec/migrations/delete_inconsistent_internal_id_records_spec.rb b/spec/migrations/delete_inconsistent_internal_id_records_spec.rb
index 4af51217031..8c55daf0d37 100644
--- a/spec/migrations/delete_inconsistent_internal_id_records_spec.rb
+++ b/spec/migrations/delete_inconsistent_internal_id_records_spec.rb
@@ -94,17 +94,18 @@ describe DeleteInconsistentInternalIdRecords, :migration do
end
context 'for milestones (by group)' do
- # milestones (by group) is a little different than all of the other models
- let!(:group1) { create(:group) }
- let!(:group2) { create(:group) }
- let!(:group3) { create(:group) }
+ # milestones (by group) is a little different than most of the other models
+ let(:groups) { table(:namespaces) }
+ let(:group1) { groups.create(name: 'Group 1', type: 'Group', path: 'group_1') }
+ let(:group2) { groups.create(name: 'Group 2', type: 'Group', path: 'group_2') }
+ let(:group3) { groups.create(name: 'Group 2', type: 'Group', path: 'group_3') }
let(:internal_id_query) { ->(group) { InternalId.where(usage: InternalId.usages['milestones'], namespace: group) } }
before do
- 3.times { create(:milestone, group: group1) }
- 3.times { create(:milestone, group: group2) }
- 3.times { create(:milestone, group: group3) }
+ 3.times { create(:milestone, group_id: group1.id) }
+ 3.times { create(:milestone, group_id: group2.id) }
+ 3.times { create(:milestone, group_id: group3.id) }
internal_id_query.call(group1).first.tap do |iid|
iid.last_value = iid.last_value - 2