summaryrefslogtreecommitdiff
path: root/app/assets/javascripts
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets/javascripts')
-rw-r--r--app/assets/javascripts/ide/components/commit_sidebar/actions.vue2
-rw-r--r--app/assets/javascripts/ide/components/commit_sidebar/new_merge_request_option.vue34
-rw-r--r--app/assets/javascripts/ide/components/commit_sidebar/radio_group.vue2
-rw-r--r--app/assets/javascripts/ide/components/nav_dropdown.vue10
-rw-r--r--app/assets/javascripts/ide/components/nav_dropdown_button.vue11
-rw-r--r--app/assets/javascripts/ide/components/nav_form.vue10
-rw-r--r--app/assets/javascripts/ide/constants.js3
-rw-r--r--app/assets/javascripts/ide/queries/getUserPermissions.query.graphql8
-rw-r--r--app/assets/javascripts/ide/services/gql.js8
-rw-r--r--app/assets/javascripts/ide/services/index.js23
-rw-r--r--app/assets/javascripts/ide/stores/actions/merge_request.js14
-rw-r--r--app/assets/javascripts/ide/stores/getters.js16
-rw-r--r--app/assets/javascripts/ide/stores/modules/commit/actions.js2
-rw-r--r--app/assets/javascripts/ide/stores/modules/commit/getters.js6
-rw-r--r--app/assets/javascripts/pages/admin/application_settings/index.js4
-rw-r--r--app/assets/javascripts/repository/components/table/index.vue7
-rw-r--r--app/assets/javascripts/repository/components/table/row.vue8
17 files changed, 141 insertions, 27 deletions
diff --git a/app/assets/javascripts/ide/components/commit_sidebar/actions.vue b/app/assets/javascripts/ide/components/commit_sidebar/actions.vue
index d9cd4f3acf1..2581c3e9928 100644
--- a/app/assets/javascripts/ide/components/commit_sidebar/actions.vue
+++ b/app/assets/javascripts/ide/components/commit_sidebar/actions.vue
@@ -70,7 +70,7 @@ export default {
:title="$options.currentBranchPermissionsTooltip"
>
<span
- class="ide-radio-label"
+ class="ide-option-label"
data-qa-selector="commit_to_current_branch_radio"
v-html="commitToCurrentBranchText"
></span>
diff --git a/app/assets/javascripts/ide/components/commit_sidebar/new_merge_request_option.vue b/app/assets/javascripts/ide/components/commit_sidebar/new_merge_request_option.vue
index daa44a42765..0812599c25c 100644
--- a/app/assets/javascripts/ide/components/commit_sidebar/new_merge_request_option.vue
+++ b/app/assets/javascripts/ide/components/commit_sidebar/new_merge_request_option.vue
@@ -1,16 +1,27 @@
<script>
import { createNamespacedHelpers } from 'vuex';
+import { GlTooltipDirective } from '@gitlab/ui';
+import { s__ } from '~/locale';
-const {
- mapState: mapCommitState,
- mapActions: mapCommitActions,
- mapGetters: mapCommitGetters,
-} = createNamespacedHelpers('commit');
+const { mapActions: mapCommitActions, mapGetters: mapCommitGetters } = createNamespacedHelpers(
+ 'commit',
+);
export default {
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ },
computed: {
- ...mapCommitState(['shouldCreateMR']),
- ...mapCommitGetters(['shouldHideNewMrOption']),
+ ...mapCommitGetters(['shouldHideNewMrOption', 'shouldDisableNewMrOption', 'shouldCreateMR']),
+ tooltipText() {
+ if (this.shouldDisableNewMrOption) {
+ return s__(
+ 'IDE|This option is disabled because you are not allowed to create merge requests in this project.',
+ );
+ }
+
+ return '';
+ },
},
methods: {
...mapCommitActions(['toggleShouldCreateMR']),
@@ -21,14 +32,19 @@ export default {
<template>
<fieldset v-if="!shouldHideNewMrOption">
<hr class="my-2" />
- <label class="mb-0 js-ide-commit-new-mr">
+ <label
+ v-gl-tooltip="tooltipText"
+ class="mb-0 js-ide-commit-new-mr"
+ :class="{ 'is-disabled': shouldDisableNewMrOption }"
+ >
<input
+ :disabled="shouldDisableNewMrOption"
:checked="shouldCreateMR"
type="checkbox"
data-qa-selector="start_new_mr_checkbox"
@change="toggleShouldCreateMR"
/>
- <span class="prepend-left-10">
+ <span class="prepend-left-10 ide-option-label">
{{ __('Start a new merge request') }}
</span>
</label>
diff --git a/app/assets/javascripts/ide/components/commit_sidebar/radio_group.vue b/app/assets/javascripts/ide/components/commit_sidebar/radio_group.vue
index 07073f5f879..a9591805261 100644
--- a/app/assets/javascripts/ide/components/commit_sidebar/radio_group.vue
+++ b/app/assets/javascripts/ide/components/commit_sidebar/radio_group.vue
@@ -67,7 +67,7 @@ export default {
@change="updateCommitAction($event.target.value)"
/>
<span class="prepend-left-10">
- <span v-if="label" class="ide-radio-label"> {{ label }} </span> <slot v-else></slot>
+ <span v-if="label" class="ide-option-label"> {{ label }} </span> <slot v-else></slot>
</span>
</label>
<div v-if="commitAction === value && showInput" class="ide-commit-new-branch">
diff --git a/app/assets/javascripts/ide/components/nav_dropdown.vue b/app/assets/javascripts/ide/components/nav_dropdown.vue
index 2e290de0943..2307efd1d24 100644
--- a/app/assets/javascripts/ide/components/nav_dropdown.vue
+++ b/app/assets/javascripts/ide/components/nav_dropdown.vue
@@ -1,5 +1,6 @@
<script>
import $ from 'jquery';
+import { mapGetters } from 'vuex';
import NavForm from './nav_form.vue';
import NavDropdownButton from './nav_dropdown_button.vue';
@@ -13,6 +14,9 @@ export default {
isVisibleDropdown: false,
};
},
+ computed: {
+ ...mapGetters(['canReadMergeRequests']),
+ },
mounted() {
this.addDropdownListeners();
},
@@ -42,7 +46,9 @@ export default {
<template>
<div ref="dropdown" class="btn-group ide-nav-dropdown dropdown">
- <nav-dropdown-button />
- <div class="dropdown-menu dropdown-menu-left p-0"><nav-form v-if="isVisibleDropdown" /></div>
+ <nav-dropdown-button :show-merge-requests="canReadMergeRequests" />
+ <div class="dropdown-menu dropdown-menu-left p-0">
+ <nav-form v-if="isVisibleDropdown" :show-merge-requests="canReadMergeRequests" />
+ </div>
</div>
</template>
diff --git a/app/assets/javascripts/ide/components/nav_dropdown_button.vue b/app/assets/javascripts/ide/components/nav_dropdown_button.vue
index f1d44443125..4cd320d5d66 100644
--- a/app/assets/javascripts/ide/components/nav_dropdown_button.vue
+++ b/app/assets/javascripts/ide/components/nav_dropdown_button.vue
@@ -10,6 +10,13 @@ export default {
Icon,
DropdownButton,
},
+ props: {
+ showMergeRequests: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
+ },
computed: {
...mapState(['currentBranchId', 'currentMergeRequestId']),
mergeRequestLabel() {
@@ -25,10 +32,10 @@ export default {
<template>
<dropdown-button>
<span class="row">
- <span class="col-7 text-truncate">
+ <span class="col-auto text-truncate" :class="{ 'col-7': showMergeRequests }">
<icon :size="16" :aria-label="__('Current Branch')" name="branch" /> {{ branchLabel }}
</span>
- <span class="col-5 pl-0 text-truncate">
+ <span v-if="showMergeRequests" class="col-5 pl-0 text-truncate">
<icon :size="16" :aria-label="__('Merge Request')" name="merge-request" />
{{ mergeRequestLabel }}
</span>
diff --git a/app/assets/javascripts/ide/components/nav_form.vue b/app/assets/javascripts/ide/components/nav_form.vue
index 2ccc84ea5d5..195504a6861 100644
--- a/app/assets/javascripts/ide/components/nav_form.vue
+++ b/app/assets/javascripts/ide/components/nav_form.vue
@@ -11,12 +11,19 @@ export default {
BranchesSearchList,
MergeRequestSearchList,
},
+ props: {
+ showMergeRequests: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
+ },
};
</script>
<template>
<div class="ide-nav-form p-0">
- <tabs stop-propagation>
+ <tabs v-if="showMergeRequests" stop-propagation>
<tab active>
<template slot="title">
{{ __('Branches') }}
@@ -30,5 +37,6 @@ export default {
<merge-request-search-list />
</tab>
</tabs>
+ <branches-search-list v-else />
</div>
</template>
diff --git a/app/assets/javascripts/ide/constants.js b/app/assets/javascripts/ide/constants.js
index 673ac1bfa9a..54d3e79411f 100644
--- a/app/assets/javascripts/ide/constants.js
+++ b/app/assets/javascripts/ide/constants.js
@@ -8,6 +8,9 @@ export const MAX_BODY_LENGTH = 72;
export const FILE_VIEW_MODE_EDITOR = 'editor';
export const FILE_VIEW_MODE_PREVIEW = 'preview';
+export const PERMISSION_CREATE_MR = 'createMergeRequestIn';
+export const PERMISSION_READ_MR = 'readMergeRequest';
+
export const activityBarViews = {
edit: 'ide-tree',
commit: 'commit-section',
diff --git a/app/assets/javascripts/ide/queries/getUserPermissions.query.graphql b/app/assets/javascripts/ide/queries/getUserPermissions.query.graphql
new file mode 100644
index 00000000000..48f63995f44
--- /dev/null
+++ b/app/assets/javascripts/ide/queries/getUserPermissions.query.graphql
@@ -0,0 +1,8 @@
+query getUserPermissions($projectPath: ID!) {
+ project(fullPath: $projectPath) {
+ userPermissions {
+ createMergeRequestIn,
+ readMergeRequest
+ }
+ }
+}
diff --git a/app/assets/javascripts/ide/services/gql.js b/app/assets/javascripts/ide/services/gql.js
new file mode 100644
index 00000000000..8a7f27328ba
--- /dev/null
+++ b/app/assets/javascripts/ide/services/gql.js
@@ -0,0 +1,8 @@
+import createGqClient, { fetchPolicies } from '~/lib/graphql';
+
+export default createGqClient(
+ {},
+ {
+ fetchPolicy: fetchPolicies.NO_CACHE,
+ },
+);
diff --git a/app/assets/javascripts/ide/services/index.js b/app/assets/javascripts/ide/services/index.js
index a5134c64705..84a2b2bd58e 100644
--- a/app/assets/javascripts/ide/services/index.js
+++ b/app/assets/javascripts/ide/services/index.js
@@ -1,6 +1,18 @@
import axios from '~/lib/utils/axios_utils';
import { joinPaths, escapeFileUrl } from '~/lib/utils/url_utility';
import Api from '~/api';
+import getUserPermissions from '../queries/getUserPermissions.query.graphql';
+import gqClient from './gql';
+
+const fetchApiProjectData = projectPath => Api.project(projectPath).then(({ data }) => data);
+
+const fetchGqlProjectData = projectPath =>
+ gqClient
+ .query({
+ query: getUserPermissions,
+ variables: { projectPath },
+ })
+ .then(({ data }) => data.project);
export default {
getFileData(endpoint) {
@@ -47,7 +59,16 @@ export default {
.then(({ data }) => data);
},
getProjectData(namespace, project) {
- return Api.project(`${namespace}/${project}`);
+ const projectPath = `${namespace}/${project}`;
+
+ return Promise.all([fetchApiProjectData(projectPath), fetchGqlProjectData(projectPath)]).then(
+ ([apiProjectData, gqlProjectData]) => ({
+ data: {
+ ...apiProjectData,
+ ...gqlProjectData,
+ },
+ }),
+ );
},
getProjectMergeRequests(projectId, params = {}) {
return Api.projectMergeRequests(projectId, params);
diff --git a/app/assets/javascripts/ide/stores/actions/merge_request.js b/app/assets/javascripts/ide/stores/actions/merge_request.js
index aa44067edf8..9e9c6fc42b3 100644
--- a/app/assets/javascripts/ide/stores/actions/merge_request.js
+++ b/app/assets/javascripts/ide/stores/actions/merge_request.js
@@ -2,10 +2,17 @@ import flash from '~/flash';
import { __ } from '~/locale';
import service from '../../services';
import * as types from '../mutation_types';
-import { activityBarViews } from '../../constants';
+import { activityBarViews, PERMISSION_READ_MR } from '../../constants';
-export const getMergeRequestsForBranch = ({ commit, state }, { projectId, branchId } = {}) =>
- service
+export const getMergeRequestsForBranch = (
+ { commit, state, getters },
+ { projectId, branchId } = {},
+) => {
+ if (!getters.findProjectPermissions(projectId)[PERMISSION_READ_MR]) {
+ return Promise.resolve();
+ }
+
+ return service
.getProjectMergeRequests(`${projectId}`, {
source_branch: branchId,
source_project_id: state.projects[projectId].id,
@@ -36,6 +43,7 @@ export const getMergeRequestsForBranch = ({ commit, state }, { projectId, branch
);
throw e;
});
+};
export const getMergeRequestData = (
{ commit, dispatch, state },
diff --git a/app/assets/javascripts/ide/stores/getters.js b/app/assets/javascripts/ide/stores/getters.js
index 2fc574cd343..257062d118c 100644
--- a/app/assets/javascripts/ide/stores/getters.js
+++ b/app/assets/javascripts/ide/stores/getters.js
@@ -1,5 +1,10 @@
import { getChangesCountForFiles, filePathMatches } from './utils';
-import { activityBarViews, packageJsonPath } from '../constants';
+import {
+ activityBarViews,
+ packageJsonPath,
+ PERMISSION_READ_MR,
+ PERMISSION_CREATE_MR,
+} from '../constants';
export const activeFile = state => state.openFiles.find(file => file.active) || null;
@@ -141,5 +146,14 @@ export const getDiffInfo = (state, getters) => path => {
};
};
+export const findProjectPermissions = (state, getters) => projectId =>
+ getters.findProject(projectId)?.userPermissions || {};
+
+export const canReadMergeRequests = (state, getters) =>
+ Boolean(getters.findProjectPermissions(state.currentProjectId)[PERMISSION_READ_MR]);
+
+export const canCreateMergeRequests = (state, getters) =>
+ Boolean(getters.findProjectPermissions(state.currentProjectId)[PERMISSION_CREATE_MR]);
+
// prevent babel-plugin-rewire from generating an invalid default during karma tests
export default () => {};
diff --git a/app/assets/javascripts/ide/stores/modules/commit/actions.js b/app/assets/javascripts/ide/stores/modules/commit/actions.js
index 0740e0523a9..3be350db3da 100644
--- a/app/assets/javascripts/ide/stores/modules/commit/actions.js
+++ b/app/assets/javascripts/ide/stores/modules/commit/actions.js
@@ -158,7 +158,7 @@ export const commitChanges = ({ commit, state, getters, dispatch, rootState, roo
commit(rootTypes.SET_LAST_COMMIT_MSG, '', { root: true });
}, 5000);
- if (state.shouldCreateMR) {
+ if (getters.shouldCreateMR) {
const { currentProject } = rootGetters;
const targetBranch = getters.isCreatingNewBranch
? rootState.currentBranchId
diff --git a/app/assets/javascripts/ide/stores/modules/commit/getters.js b/app/assets/javascripts/ide/stores/modules/commit/getters.js
index de289e27199..e421d44b6de 100644
--- a/app/assets/javascripts/ide/stores/modules/commit/getters.js
+++ b/app/assets/javascripts/ide/stores/modules/commit/getters.js
@@ -54,5 +54,11 @@ export const shouldHideNewMrOption = (_state, getters, _rootState, rootGetters)
(!rootGetters.hasMergeRequest && rootGetters.isOnDefaultBranch)) &&
rootGetters.canPushToBranch;
+export const shouldDisableNewMrOption = (state, getters, rootState, rootGetters) =>
+ !rootGetters.canCreateMergeRequests;
+
+export const shouldCreateMR = (state, getters) =>
+ state.shouldCreateMR && !getters.shouldDisableNewMrOption;
+
// prevent babel-plugin-rewire from generating an invalid default during karma tests
export default () => {};
diff --git a/app/assets/javascripts/pages/admin/application_settings/index.js b/app/assets/javascripts/pages/admin/application_settings/index.js
index 089dedd14cb..78b7e29ae53 100644
--- a/app/assets/javascripts/pages/admin/application_settings/index.js
+++ b/app/assets/javascripts/pages/admin/application_settings/index.js
@@ -3,9 +3,7 @@ import projectSelect from '~/project_select';
import selfMonitor from '~/self_monitor';
document.addEventListener('DOMContentLoaded', () => {
- if (gon.features && gon.features.selfMonitoringProject) {
- selfMonitor();
- }
+ selfMonitor();
// Initialize expandable settings panels
initSettingsPanels();
projectSelect();
diff --git a/app/assets/javascripts/repository/components/table/index.vue b/app/assets/javascripts/repository/components/table/index.vue
index 29a3340b83d..2ba170998e8 100644
--- a/app/assets/javascripts/repository/components/table/index.vue
+++ b/app/assets/javascripts/repository/components/table/index.vue
@@ -71,7 +71,12 @@ export default {
<template>
<div class="tree-content-holder">
<div class="table-holder bordered-box">
- <table :aria-label="tableCaption" class="table tree-table qa-file-tree" aria-live="polite">
+ <table
+ :aria-label="tableCaption"
+ class="table tree-table"
+ aria-live="polite"
+ data-qa-selector="file_tree_table"
+ >
<table-header v-once />
<tbody>
<parent-row
diff --git a/app/assets/javascripts/repository/components/table/row.vue b/app/assets/javascripts/repository/components/table/row.vue
index 8703796b116..c905c39bbba 100644
--- a/app/assets/javascripts/repository/components/table/row.vue
+++ b/app/assets/javascripts/repository/components/table/row.vue
@@ -139,7 +139,13 @@ export default {
class="d-inline-block align-text-bottom fa-fw"
/>
<i v-else :aria-label="type" role="img" :class="iconName" class="fa fa-fw"></i>
- <component :is="linkComponent" :to="routerLinkTo" :href="url" class="str-truncated">
+ <component
+ :is="linkComponent"
+ :to="routerLinkTo"
+ :href="url"
+ class="str-truncated"
+ data-qa-selector="file_name_link"
+ >
{{ fullPath }}
</component>
<!-- eslint-disable-next-line @gitlab/vue-i18n/no-bare-strings -->