Commit 2aa19681 authored by Mike Greiling's avatar Mike Greiling

Merge branch 'fe-cluster-management-project' into 'master'

Add ability to select a Cluster management project

See merge request gitlab-org/gitlab!18928
parents d864efd9 f97e5042
......@@ -2,6 +2,8 @@ import $ from 'jquery';
import _ from 'underscore';
import axios from './lib/utils/axios_utils';
import { joinPaths } from './lib/utils/url_utility';
import flash from '~/flash';
import { __ } from '~/locale';
const Api = {
groupsPath: '/api/:version/groups.json',
......@@ -29,6 +31,7 @@ const Api = {
usersPath: '/api/:version/users.json',
userPath: '/api/:version/users/:id',
userStatusPath: '/api/:version/users/:id/status',
userProjectsPath: '/api/:version/users/:id/projects',
userPostStatusPath: '/api/:version/user/status',
commitPath: '/api/:version/projects/:id/repository/commits',
applySuggestionPath: '/api/:version/suggestions/:id/apply',
......@@ -239,7 +242,8 @@ const Api = {
.get(url, {
params: Object.assign({}, defaults, options),
})
.then(({ data }) => callback(data));
.then(({ data }) => callback(data))
.catch(() => flash(__('Something went wrong while fetching projects')));
},
commitMultiple(id, data) {
......@@ -348,6 +352,20 @@ const Api = {
});
},
userProjects(userId, query, options, callback) {
const url = Api.buildUrl(Api.userProjectsPath).replace(':id', userId);
const defaults = {
search: query,
per_page: 20,
};
return axios
.get(url, {
params: Object.assign({}, defaults, options),
})
.then(({ data }) => callback(data))
.catch(() => flash(__('Something went wrong while fetching projects')));
},
branches(id, query = '', options = {}) {
const url = Api.buildUrl(this.createBranchPath).replace(':id', encodeURIComponent(id));
......
......@@ -13,6 +13,7 @@ import ClustersService from './services/clusters_service';
import ClustersStore from './stores/clusters_store';
import Applications from './components/applications.vue';
import setupToggleButtons from '../toggle_buttons';
import initProjectSelectDropdown from '~/project_select';
const Environments = () => import('ee_component/clusters/components/environments.vue');
......@@ -110,8 +111,10 @@ export default class Clusters {
this.ingressDomainHelpText &&
this.ingressDomainHelpText.querySelector('.js-ingress-domain-snippet');
initProjectSelectDropdown();
Clusters.initDismissableCallout();
initSettingsPanels();
const toggleButtonsContainer = document.querySelector('.js-cluster-enable-toggle-area');
if (toggleButtonsContainer) {
setupToggleButtons(toggleButtonsContainer);
......
......@@ -9,7 +9,9 @@ const projectSelect = () => {
$('.ajax-project-select').each(function(i, select) {
var placeholder;
const simpleFilter = $(select).data('simpleFilter') || false;
const isInstantiated = $(select).data('select2');
this.groupId = $(select).data('groupId');
this.userId = $(select).data('userId');
this.includeGroups = $(select).data('includeGroups');
this.allProjects = $(select).data('allProjects') || false;
this.orderBy = $(select).data('orderBy') || 'id';
......@@ -63,6 +65,18 @@ const projectSelect = () => {
},
projectsCallback,
);
} else if (_this.userId) {
return Api.userProjects(
_this.userId,
query.term,
{
with_issues_enabled: _this.withIssuesEnabled,
with_merge_requests_enabled: _this.withMergeRequestsEnabled,
with_shared: _this.withShared,
include_subgroups: _this.includeProjectsInSubgroups,
},
projectsCallback,
);
} else {
return Api.projects(
query.term,
......@@ -96,7 +110,7 @@ const projectSelect = () => {
dropdownCssClass: 'ajax-project-dropdown',
});
if (simpleFilter) return select;
if (isInstantiated || simpleFilter) return select;
return new ProjectSelectComboButton(select);
});
};
......
- group_id = @cluster.group.id if @cluster.group_type?
- if @cluster.project_type?
- group_id = @cluster.project.group.id if @cluster.project.group
- user_id = @cluster.project.namespace.owner_id unless group_id
- if can?(current_user, :admin_cluster, @cluster)
- unless @cluster.provided_by_user?
.append-bottom-20
......@@ -7,6 +13,21 @@
- link_gke = link_to(s_('ClusterIntegration|Google Kubernetes Engine'), @cluster.gke_cluster_url, target: '_blank', rel: 'noopener noreferrer')
= s_('ClusterIntegration|Manage your Kubernetes cluster by visiting %{link_gke}').html_safe % { link_gke: link_gke }
= form_for @cluster, url: clusterable.cluster_path(@cluster), as: :cluster, html: { class: 'cluster_management_form' } do |field|
%h5
= s_('ClusterIntegration|Cluster management project (alpha)')
.form-group
.form-text.text-muted
= project_select_tag('cluster[management_project_id]', class: 'hidden-filter-value', toggle_class: 'js-project-search js-project-filter js-filter-submit', dropdown_class: 'dropdown-menu-selectable dropdown-menu-project js-filter-submit',
placeholder: _('Select project'), idAttribute: 'id', data: { order_by: 'last_activity_at', idattribute: 'id', simple_filter: true, allow_clear: true, include_groups: false, include_projects_in_subgroups: true, group_id: group_id, user_id: user_id }, value: @cluster.management_project_id)
.text-muted
= s_('ClusterIntegration|A cluster management project can be used to run deployment jobs with Kubernetes <code>cluster-admin</code> privileges.').html_safe
= link_to _('More information'), help_page_path('user/clusters/management_project.md'), target: '_blank'
.form-group
= field.submit _('Save changes'), class: 'btn btn-success qa-save-domain'
.sub-section.form-group
%h4.text-danger
= s_('ClusterIntegration|Remove Kubernetes cluster integration')
......
---
title: Add ability to select a Cluster management project
merge_request: 18928
author:
type: added
......@@ -3399,6 +3399,9 @@ msgstr ""
msgid "ClusterIntegration|%{title} updated successfully."
msgstr ""
msgid "ClusterIntegration|A cluster management project can be used to run deployment jobs with Kubernetes <code>cluster-admin</code> privileges."
msgstr ""
msgid "ClusterIntegration|A service token scoped to %{code}kube-system%{end_code} with %{code}cluster-admin%{end_code} privileges."
msgstr ""
......@@ -3507,6 +3510,9 @@ msgstr ""
msgid "ClusterIntegration|Cluster health"
msgstr ""
msgid "ClusterIntegration|Cluster management project (alpha)"
msgstr ""
msgid "ClusterIntegration|Cluster name is required."
msgstr ""
......@@ -15587,6 +15593,9 @@ msgstr ""
msgid "Something went wrong while fetching latest comments."
msgstr ""
msgid "Something went wrong while fetching projects"
msgstr ""
msgid "Something went wrong while fetching related merge requests."
msgstr ""
......
......@@ -467,6 +467,26 @@ describe('Api', () => {
});
});
describe('user projects', () => {
it('fetches all projects that belong to a particular user', done => {
const query = 'dummy query';
const options = { unused: 'option' };
const userId = '123456';
const expectedUrl = `${dummyUrlRoot}/api/${dummyApiVersion}/users/${userId}/projects`;
mock.onGet(expectedUrl).reply(200, [
{
name: 'test',
},
]);
Api.userProjects(userId, query, options, response => {
expect(response.length).toBe(1);
expect(response[0].name).toBe('test');
done();
});
});
});
describe('commitPipelines', () => {
it('fetches pipelines for a given commit', done => {
const projectId = 'example/foobar';
......
......@@ -10,8 +10,10 @@ import axios from '~/lib/utils/axios_utils';
import { loadHTMLFixture } from 'helpers/fixtures';
import { setTestTimeout } from 'helpers/timeout';
import $ from 'jquery';
import initProjectSelectDropdown from '~/project_select';
jest.mock('~/lib/utils/poll');
jest.mock('~/project_select');
const { INSTALLING, INSTALLABLE, INSTALLED, UNINSTALLING } = APPLICATION_STATUS;
......@@ -44,6 +46,7 @@ describe('Clusters', () => {
afterEach(() => {
cluster.destroy();
mock.restore();
jest.clearAllMocks();
});
describe('class constructor', () => {
......@@ -55,6 +58,10 @@ describe('Clusters', () => {
it('should call initPolling on construct', () => {
expect(cluster.initPolling).toHaveBeenCalled();
});
it('should call initProjectSelectDropdown on construct', () => {
expect(initProjectSelectDropdown).toHaveBeenCalled();
});
});
describe('toggle', () => {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment