Commit 13b5f925 authored by GitLab Bot's avatar GitLab Bot

Automatic merge of gitlab-org/gitlab-ce master

parents f6d8206f f97a73fa
...@@ -182,7 +182,7 @@ export default class CreateMergeRequestDropdown { ...@@ -182,7 +182,7 @@ export default class CreateMergeRequestDropdown {
} }
enable() { enable() {
if (!canCreateConfidentialMergeRequest()) return; if (isConfidentialIssue() && !canCreateConfidentialMergeRequest()) return;
this.createMergeRequestButton.classList.remove('disabled'); this.createMergeRequestButton.classList.remove('disabled');
this.createMergeRequestButton.removeAttribute('disabled'); this.createMergeRequestButton.removeAttribute('disabled');
......
<script> <script>
import { GlDropdown, GlDropdownDivider, GlDropdownHeader, GlDropdownItem } from '@gitlab/ui';
import { __ } from '../../locale';
import Icon from '../../vue_shared/components/icon.vue';
import getRefMixin from '../mixins/get_ref'; import getRefMixin from '../mixins/get_ref';
import getProjectShortPath from '../queries/getProjectShortPath.query.graphql'; import getProjectShortPath from '../queries/getProjectShortPath.query.graphql';
import getProjectPath from '../queries/getProjectPath.query.graphql';
import getPermissions from '../queries/getPermissions.query.graphql';
const ROW_TYPES = {
header: 'header',
divider: 'divider',
};
export default { export default {
components: {
GlDropdown,
GlDropdownDivider,
GlDropdownHeader,
GlDropdownItem,
Icon,
},
apollo: { apollo: {
projectShortPath: { projectShortPath: {
query: getProjectShortPath, query: getProjectShortPath,
}, },
projectPath: {
query: getProjectPath,
},
userPermissions: {
query: getPermissions,
variables() {
return {
projectPath: this.projectPath,
};
},
update: data => data.project.userPermissions,
},
}, },
mixins: [getRefMixin], mixins: [getRefMixin],
props: { props: {
...@@ -15,10 +44,52 @@ export default { ...@@ -15,10 +44,52 @@ export default {
required: false, required: false,
default: '/', default: '/',
}, },
canCollaborate: {
type: Boolean,
required: false,
default: false,
},
canEditTree: {
type: Boolean,
required: false,
default: false,
},
newBranchPath: {
type: String,
required: false,
default: null,
},
newTagPath: {
type: String,
required: false,
default: null,
},
newBlobPath: {
type: String,
required: false,
default: null,
},
forkNewBlobPath: {
type: String,
required: false,
default: null,
},
forkNewDirectoryPath: {
type: String,
required: false,
default: null,
},
forkUploadBlobPath: {
type: String,
required: false,
default: null,
},
}, },
data() { data() {
return { return {
projectShortPath: '', projectShortPath: '',
projectPath: '',
userPermissions: {},
}; };
}, },
computed: { computed: {
...@@ -39,11 +110,112 @@ export default { ...@@ -39,11 +110,112 @@ export default {
[{ name: this.projectShortPath, path: '/', to: `/tree/${this.ref}/` }], [{ name: this.projectShortPath, path: '/', to: `/tree/${this.ref}/` }],
); );
}, },
canCreateMrFromFork() {
return this.userPermissions.forkProject && this.userPermissions.createMergeRequestIn;
},
dropdownItems() {
const items = [];
if (this.canEditTree) {
items.push(
{
type: ROW_TYPES.header,
text: __('This directory'),
},
{
attrs: {
href: this.newBlobPath,
class: 'qa-new-file-option',
},
text: __('New file'),
},
{
attrs: {
href: '#modal-upload-blob',
'data-target': '#modal-upload-blob',
'data-toggle': 'modal',
},
text: __('Upload file'),
},
{
attrs: {
href: '#modal-create-new-dir',
'data-target': '#modal-create-new-dir',
'data-toggle': 'modal',
},
text: __('New directory'),
},
);
} else if (this.canCreateMrFromFork) {
items.push(
{
attrs: {
href: this.forkNewBlobPath,
'data-method': 'post',
},
text: __('New file'),
},
{
attrs: {
href: this.forkUploadBlobPath,
'data-method': 'post',
},
text: __('Upload file'),
},
{
attrs: {
href: this.forkNewDirectoryPath,
'data-method': 'post',
},
text: __('New directory'),
},
);
}
if (this.userPermissions.pushCode) {
items.push(
{
type: ROW_TYPES.divider,
},
{
type: ROW_TYPES.header,
text: __('This repository'),
},
{
attrs: {
href: this.newBranchPath,
},
text: __('New branch'),
},
{
attrs: {
href: this.newTagPath,
},
text: __('New tag'),
},
);
}
return items;
},
renderAddToTreeDropdown() {
return this.canCollaborate || this.canCreateMrFromFork;
},
}, },
methods: { methods: {
isLast(i) { isLast(i) {
return i === this.pathLinks.length - 1; return i === this.pathLinks.length - 1;
}, },
getComponent(type) {
switch (type) {
case ROW_TYPES.divider:
return 'gl-dropdown-divider';
case ROW_TYPES.header:
return 'gl-dropdown-header';
default:
return 'gl-dropdown-item';
}
},
}, },
}; };
</script> </script>
...@@ -56,6 +228,20 @@ export default { ...@@ -56,6 +228,20 @@ export default {
{{ link.name }} {{ link.name }}
</router-link> </router-link>
</li> </li>
<li v-if="renderAddToTreeDropdown" class="breadcrumb-item">
<gl-dropdown toggle-class="add-to-tree qa-add-to-tree ml-1">
<template slot="button-content">
<span class="sr-only">{{ __('Add to tree') }}</span>
<icon name="plus" :size="16" class="float-left" />
<icon name="arrow-down" :size="16" class="float-left" />
</template>
<template v-for="(item, i) in dropdownItems">
<component :is="getComponent(item.type)" :key="i" v-bind="item.attrs">
{{ item.text }}
</component>
</template>
</gl-dropdown>
</li>
</ol> </ol>
</nav> </nav>
</template> </template>
...@@ -5,6 +5,7 @@ import Breadcrumbs from './components/breadcrumbs.vue'; ...@@ -5,6 +5,7 @@ import Breadcrumbs from './components/breadcrumbs.vue';
import LastCommit from './components/last_commit.vue'; import LastCommit from './components/last_commit.vue';
import apolloProvider from './graphql'; import apolloProvider from './graphql';
import { setTitle } from './utils/title'; import { setTitle } from './utils/title';
import { parseBoolean } from '../lib/utils/common_utils';
export default function setupVueRepositoryList() { export default function setupVueRepositoryList() {
const el = document.getElementById('js-tree-list'); const el = document.getElementById('js-tree-list');
...@@ -36,19 +37,42 @@ export default function setupVueRepositoryList() { ...@@ -36,19 +37,42 @@ export default function setupVueRepositoryList() {
.forEach(elem => elem.classList.toggle('hidden', !isRoot)); .forEach(elem => elem.classList.toggle('hidden', !isRoot));
}); });
// eslint-disable-next-line no-new const breadcrumbEl = document.getElementById('js-repo-breadcrumb');
new Vue({
el: document.getElementById('js-repo-breadcrumb'), if (breadcrumbEl) {
router, const {
apolloProvider, canCollaborate,
render(h) { canEditTree,
return h(Breadcrumbs, { newBranchPath,
props: { newTagPath,
currentPath: this.$route.params.pathMatch, newBlobPath,
}, forkNewBlobPath,
}); forkNewDirectoryPath,
}, forkUploadBlobPath,
}); } = breadcrumbEl.dataset;
// eslint-disable-next-line no-new
new Vue({
el: breadcrumbEl,
router,
apolloProvider,
render(h) {
return h(Breadcrumbs, {
props: {
currentPath: this.$route.params.pathMatch,
canCollaborate: parseBoolean(canCollaborate),
canEditTree: parseBoolean(canEditTree),
newBranchPath,
newTagPath,
newBlobPath,
forkNewBlobPath,
forkNewDirectoryPath,
forkUploadBlobPath,
},
});
},
});
}
// eslint-disable-next-line no-new // eslint-disable-next-line no-new
new Vue({ new Vue({
......
query getPermissions($projectPath: ID!) {
project(fullPath: $projectPath) {
userPermissions {
pushCode
forkProject
createMergeRequestIn
}
}
}
...@@ -154,6 +154,38 @@ module TreeHelper ...@@ -154,6 +154,38 @@ module TreeHelper
"logs-path" => logs_path "logs-path" => logs_path
} }
end end
def breadcrumb_data_attributes
attrs = {
can_collaborate: can_collaborate_with_project?(@project).to_s,
new_blob_path: project_new_blob_path(@project, @id),
new_branch_path: new_project_branch_path(@project),
new_tag_path: new_project_tag_path(@project),
can_edit_tree: can_edit_tree?.to_s
}
if can?(current_user, :fork_project, @project) && can?(current_user, :create_merge_request_in, @project)
continue_param = {
to: project_new_blob_path(@project, @id),
notice: edit_in_new_fork_notice,
notice_now: edit_in_new_fork_notice_now
}
attrs.merge!(
fork_new_blob_path: project_forks_path(@project, namespace_key: current_user.namespace.id, continue: continue_param),
fork_new_directory_path: project_forks_path(@project, namespace_key: current_user.namespace.id, continue: continue_param.merge({
to: request.fullpath,
notice: _("%{edit_in_new_fork_notice} Try to create a new directory again.") % { edit_in_new_fork_notice: edit_in_new_fork_notice }
})),
fork_upload_blob_path: project_forks_path(@project, namespace_key: current_user.namespace.id, continue: continue_param.merge({
to: request.fullpath,
notice: _("%{edit_in_new_fork_notice} Try to upload a file again.") % { edit_in_new_fork_notice: edit_in_new_fork_notice }
}))
)
end
attrs
end
end end
TreeHelper.prepend(::EE::TreeHelper) TreeHelper.prepend(::EE::TreeHelper)
...@@ -20,6 +20,9 @@ ...@@ -20,6 +20,9 @@
- if vue_file_list_enabled? - if vue_file_list_enabled?
#js-tree-list{ data: { project_path: @project.full_path, project_short_path: @project.path, ref: ref, full_name: @project.name_with_namespace } } #js-tree-list{ data: { project_path: @project.full_path, project_short_path: @project.path, ref: ref, full_name: @project.name_with_namespace } }
- if can_edit_tree?
= render 'projects/blob/upload', title: _('Upload New File'), placeholder: _('Upload New File'), button_title: _('Upload file'), form_path: project_create_blob_path(@project, @id), method: :post
= render 'projects/blob/new_dir'
- if @tree.readme - if @tree.readme
= render "projects/tree/readme", readme: @tree.readme = render "projects/tree/readme", readme: @tree.readme
- else - else
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
- addtotree_toggle_attributes = { title: _("You can only add files when you are on a branch"), data: { container: 'body' }, class: 'disabled has-tooltip' } - addtotree_toggle_attributes = { title: _("You can only add files when you are on a branch"), data: { container: 'body' }, class: 'disabled has-tooltip' }
- if vue_file_list_enabled? - if vue_file_list_enabled?
#js-repo-breadcrumb #js-repo-breadcrumb{ data: breadcrumb_data_attributes }
- else - else
%ul.breadcrumb.repo-breadcrumb %ul.breadcrumb.repo-breadcrumb
%li.breadcrumb-item %li.breadcrumb-item
......
---
title: Update example Prometheus scrape config
merge_request: 30739
author:
type: other
...@@ -134,17 +134,57 @@ To use an external Prometheus server: ...@@ -134,17 +134,57 @@ To use an external Prometheus server:
```yaml ```yaml
scrape_configs: scrape_configs:
- job_name: 'gitlab_exporters' - job_name: nginx
static_configs: static_configs:
- targets: ['1.1.1.1:9168', '1.1.1.1:9236', '1.1.1.1:9236', '1.1.1.1:9100', '1.1.1.1:9121', '1.1.1.1:9187'] - targets:
- 1.1.1.1:8060
- job_name: 'gitlab_metrics' - job_name: redis
metrics_path: /-/metrics static_configs:
- targets:
- 1.1.1.1:9121
- job_name: postgres
static_configs:
- targets:
- 1.1.1.1:9187
- job_name: node
static_configs:
- targets:
- 1.1.1.1:9100
- job_name: gitlab-workhorse
static_configs:
- targets:
- 1.1.1.1:9229
- job_name: gitlab-rails
metrics_path: "/-/metrics"
static_configs:
- targets:
- 1.1.1.1:8080
- job_name: gitlab-sidekiq
static_configs:
- targets:
- 1.1.1.1:8082
- job_name: gitlab_monitor_database
metrics_path: "/database"
static_configs:
- targets:
- 1.1.1.1:9168
- job_name: gitlab_monitor_sidekiq
metrics_path: "/sidekiq"
static_configs:
- targets:
- 1.1.1.1:9168
- job_name: gitlab_monitor_process
metrics_path: "/process"
static_configs:
- targets:
- 1.1.1.1:9168
- job_name: gitaly
static_configs: static_configs:
- targets: ['1.1.1.1:443'] - targets:
- 1.1.1.1:9236
``` ```
1. Restart the Prometheus server. 1. Reload the Prometheus server.
## Viewing performance metrics ## Viewing performance metrics
......
...@@ -257,7 +257,7 @@ sudo gitlab-rake gitlab:exclusive_lease:clear[project_housekeeping:4] ...@@ -257,7 +257,7 @@ sudo gitlab-rake gitlab:exclusive_lease:clear[project_housekeeping:4]
To check the status of migrations, you can use the following rake task: To check the status of migrations, you can use the following rake task:
```bash ```bash
sudo gitlab-rake db:migrations:status sudo gitlab-rake db:migrate:status
``` ```
This will output a table with a `Status` of `up` or `down` for This will output a table with a `Status` of `up` or `down` for
......
...@@ -194,9 +194,15 @@ msgstr[1] "" ...@@ -194,9 +194,15 @@ msgstr[1] ""
msgid "%{edit_in_new_fork_notice} Try to cherry-pick this commit again." msgid "%{edit_in_new_fork_notice} Try to cherry-pick this commit again."
msgstr "" msgstr ""
msgid "%{edit_in_new_fork_notice} Try to create a new directory again."
msgstr ""
msgid "%{edit_in_new_fork_notice} Try to revert this commit again." msgid "%{edit_in_new_fork_notice} Try to revert this commit again."
msgstr "" msgstr ""
msgid "%{edit_in_new_fork_notice} Try to upload a file again."
msgstr ""
msgid "%{filePath} deleted" msgid "%{filePath} deleted"
msgstr "" msgstr ""
...@@ -866,6 +872,9 @@ msgstr "" ...@@ -866,6 +872,9 @@ msgstr ""
msgid "Add to review" msgid "Add to review"
msgstr "" msgstr ""
msgid "Add to tree"
msgstr ""
msgid "Add user(s) to the group:" msgid "Add user(s) to the group:"
msgstr "" msgstr ""
......
import axios from '~/lib/utils/axios_utils'; import axios from '~/lib/utils/axios_utils';
import MockAdapter from 'axios-mock-adapter'; import MockAdapter from 'axios-mock-adapter';
import CreateMergeRequestDropdown from '~/create_merge_request_dropdown'; import CreateMergeRequestDropdown from '~/create_merge_request_dropdown';
import confidentialState from '~/confidential_merge_request/state';
import { TEST_HOST } from './helpers/test_constants'; import { TEST_HOST } from './helpers/test_constants';
describe('CreateMergeRequestDropdown', () => { describe('CreateMergeRequestDropdown', () => {
...@@ -66,4 +67,37 @@ describe('CreateMergeRequestDropdown', () => { ...@@ -66,4 +67,37 @@ describe('CreateMergeRequestDropdown', () => {
); );
}); });
}); });
describe('enable', () => {
beforeEach(() => {
dropdown.createMergeRequestButton.classList.add('disabled');
});
afterEach(() => {
confidentialState.selectedProject = {};
});
it('enables button when not confidential issue', () => {
dropdown.enable();
expect(dropdown.createMergeRequestButton.classList).not.toContain('disabled');
});
it('enables when can create confidential issue', () => {
document.querySelector('.js-create-mr').setAttribute('data-is-confidential', 'true');
confidentialState.selectedProject = { name: 'test' };
dropdown.enable();
expect(dropdown.createMergeRequestButton.classList).not.toContain('disabled');
});
it('does not enable when can not create confidential issue', () => {
document.querySelector('.js-create-mr').setAttribute('data-is-confidential', 'true');
dropdown.enable();
expect(dropdown.createMergeRequestButton.classList).toContain('disabled');
});
});
}); });
import { shallowMount, RouterLinkStub } from '@vue/test-utils'; import { shallowMount, RouterLinkStub } from '@vue/test-utils';
import { GlDropdown } from '@gitlab/ui';
import Breadcrumbs from '~/repository/components/breadcrumbs.vue'; import Breadcrumbs from '~/repository/components/breadcrumbs.vue';
let vm; let vm;
function factory(currentPath) { function factory(currentPath, extraProps = {}) {
vm = shallowMount(Breadcrumbs, { vm = shallowMount(Breadcrumbs, {
propsData: { propsData: {
currentPath, currentPath,
...extraProps,
}, },
stubs: { stubs: {
RouterLink: RouterLinkStub, RouterLink: RouterLinkStub,
...@@ -41,4 +43,20 @@ describe('Repository breadcrumbs component', () => { ...@@ -41,4 +43,20 @@ describe('Repository breadcrumbs component', () => {
.attributes('aria-current'), .attributes('aria-current'),
).toEqual('page'); ).toEqual('page');
}); });
it('does not render add to tree dropdown when permissions are false', () => {
factory('/', { canCollaborate: false });
vm.setData({ userPermissions: { forkProject: false, createMergeRequestIn: false } });
expect(vm.find(GlDropdown).exists()).toBe(false);
});
it('renders add to tree dropdown when permissions are true', () => {
factory('/', { canCollaborate: true });
vm.setData({ userPermissions: { forkProject: true, createMergeRequestIn: true } });
expect(vm.find(GlDropdown).exists()).toBe(true);
});
}); });
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