Commit 99d03dd8 authored by Rajat Jain's avatar Rajat Jain

Autocomplete confidential only epics & issues

Passing `confidential_only=true` as a query param in the
autocomplete endpoints. Enabling the backend to only fetch
confidential epics and confidential issues.
parent 42f861cc
......@@ -2,6 +2,8 @@
import { GlFormGroup, GlFormRadioGroup, GlLoadingIcon } from '@gitlab/ui';
import { __ } from '~/locale';
import RelatedIssuableInput from './related_issuable_input.vue';
import { mergeUrlParams } from '~/lib/utils/url_utility';
import {
issuableTypesMap,
itemAddFailureTypesMap,
......@@ -67,6 +69,11 @@ export default {
required: false,
default: '',
},
confidential: {
type: Boolean,
required: false,
default: false,
},
},
data() {
return {
......@@ -102,6 +109,21 @@ export default {
// Only other failure is MAX_NUMBER_OF_CHILD_EPICS at the moment
return addRelatedItemErrorMap[this.itemAddFailureType];
},
transformedAutocompleteSources() {
if (!this.confidential) {
return this.autoCompleteSources;
}
if (!this.autoCompleteSources?.issues || !this.autoCompleteSources?.epics) {
return this.autoCompleteSources;
}
return {
...this.autoCompleteSources,
issues: mergeUrlParams({ confidential_only: true }, this.autoCompleteSources.issues),
epics: mergeUrlParams({ confidential_only: true }, this.autoCompleteSources.epics),
};
},
},
methods: {
onPendingIssuableRemoveRequest(params) {
......@@ -149,11 +171,12 @@ export default {
<related-issuable-input
ref="relatedIssuableInput"
input-id="add-related-issues-form-input"
:confidential="confidential"
:focus-on-mount="true"
:references="pendingReferences"
:path-id-separator="pathIdSeparator"
:input-value="inputValue"
:auto-complete-sources="autoCompleteSources"
:auto-complete-sources="transformedAutocompleteSources"
:auto-complete-options="{ issues: true, epics: true }"
:issuable-type="issuableType"
@pendingIssuableRemoveRequest="onPendingIssuableRemoveRequest"
......
......@@ -2,7 +2,12 @@
import $ from 'jquery';
import GfmAutoComplete from 'ee_else_ce/gfm_auto_complete';
import issueToken from './issue_token.vue';
import { autoCompleteTextMap, inputPlaceholderTextMap, issuableTypesMap } from '../constants';
import {
autoCompleteTextMap,
inputPlaceholderConfidentialTextMap,
inputPlaceholderTextMap,
issuableTypesMap,
} from '../constants';
const SPACE_FACTOR = 1;
......@@ -51,6 +56,11 @@ export default {
required: false,
default: issuableTypesMap.ISSUE,
},
confidential: {
type: Boolean,
required: false,
default: false,
},
},
data() {
return {
......@@ -61,9 +71,12 @@ export default {
},
computed: {
inputPlaceholder() {
const { issuableType, allowAutoComplete } = this;
const { issuableType, allowAutoComplete, confidential } = this;
const inputPlaceholderMapping = confidential
? inputPlaceholderConfidentialTextMap
: inputPlaceholderTextMap;
const allowAutoCompleteText = autoCompleteTextMap[allowAutoComplete][issuableType];
return `${inputPlaceholderTextMap[issuableType]}${allowAutoCompleteText}`;
return `${inputPlaceholderMapping[issuableType]}${allowAutoCompleteText}`;
},
allowAutoComplete() {
return Object.keys(this.autoCompleteSources).length > 0;
......
......@@ -37,6 +37,12 @@ export const inputPlaceholderTextMap = {
[issuableTypesMap.MERGE_REQUEST]: __('Enter merge request URLs'),
};
export const inputPlaceholderConfidentialTextMap = {
[issuableTypesMap.ISSUE]: __('Paste confidential issue link'),
[issuableTypesMap.EPIC]: __('Paste confidential epic link'),
[issuableTypesMap.MERGE_REQUEST]: __('Enter merge request URLs'),
};
export const relatedIssuesRemoveErrorMap = {
[issuableTypesMap.ISSUE]: __('An error occurred while removing issues.'),
[issuableTypesMap.EPIC]: __('An error occurred while removing epics.'),
......
<script>
import { mapState } from 'vuex';
import { GlDeprecatedButton, GlLoadingIcon } from '@gitlab/ui';
import { __ } from '~/locale';
......@@ -21,6 +23,7 @@ export default {
};
},
computed: {
...mapState(['parentItem']),
isSubmitButtonDisabled() {
return this.inputValue.length === 0 || this.isSubmitting;
},
......@@ -51,7 +54,9 @@ export default {
<input
ref="input"
v-model="inputValue"
:placeholder="__('New epic title')"
:placeholder="
parentItem.confidential ? __('New confidential epic title ') : __('New epic title')
"
type="text"
class="form-control"
@keyup.escape.exact="onFormCancel"
......
......@@ -33,7 +33,7 @@ export default {
};
},
computed: {
...mapState(['projectsFetchInProgress', 'itemCreateInProgress', 'projects']),
...mapState(['projectsFetchInProgress', 'itemCreateInProgress', 'projects', 'parentItem']),
dropdownToggleText() {
if (this.selectedProject) {
return this.selectedProject.name_with_namespace;
......@@ -121,7 +121,9 @@ export default {
<gl-form-input
ref="titleInput"
v-model.trim="title"
:placeholder="__('New issue title')"
:placeholder="
parentItem.confidential ? __('New confidential issue title') : __('New issue title')
"
autofocus
/>
</div>
......
......@@ -167,6 +167,7 @@ export default {
:has-error="itemAddFailure"
:item-add-failure-type="itemAddFailureType"
:item-add-failure-message="itemAddFailureMessage"
:confidential="parentItem.confidential"
@pendingIssuableRemoveRequest="handlePendingItemRemove"
@addIssuableFormInput="handleAddItemFormInput"
@addIssuableFormBlur="handleAddItemFormBlur"
......
......@@ -43,6 +43,7 @@ export default () => {
id,
iid: Number(iid),
title: initialData.initialTitleText,
confidential: initialData.confidential,
reference: `${initialData.fullPath}${initialData.issuableRef}`,
userPermissions: {
adminEpic: initialData.canAdmin,
......
---
title: Autocomplete confidential only epics & issues
merge_request: 36687
author:
type: changed
......@@ -32,6 +32,17 @@ const findRadioInput = (inputs, value) => inputs.filter(input => input.element.v
const findRadioInputs = wrapper => wrapper.findAll('[name="linked-issue-type-radio"]');
const constructWrapper = props => {
return shallowMount(AddIssuableForm, {
propsData: {
inputValue: '',
pendingReferences: [],
pathIdSeparator,
...props,
},
});
};
describe('AddIssuableForm', () => {
let wrapper;
......@@ -243,4 +254,40 @@ describe('AddIssuableForm', () => {
});
});
});
describe('computed', () => {
describe('transformedAutocompleteSources', () => {
const autoCompleteSources = {
issues: 'http://localhost/autocomplete/issues',
epics: 'http://localhost/autocomplete/epics',
};
it('returns autocomplete object', () => {
wrapper = constructWrapper({
autoCompleteSources,
});
expect(wrapper.vm.transformedAutocompleteSources).toBe(autoCompleteSources);
wrapper = constructWrapper({
autoCompleteSources,
confidential: false,
});
expect(wrapper.vm.transformedAutocompleteSources).toBe(autoCompleteSources);
});
it('returns autocomplete sources with query `confidential_only`, when it is confidential', () => {
wrapper = constructWrapper({
autoCompleteSources,
confidential: true,
});
const actualSources = wrapper.vm.transformedAutocompleteSources;
expect(actualSources.epics).toContain('?confidential_only=true');
expect(actualSources.issues).toContain('?confidential_only=true');
});
});
});
});
import { shallowMount } from '@vue/test-utils';
import { createLocalVue, shallowMount } from '@vue/test-utils';
import Vuex from 'vuex';
import { GlDeprecatedButton } from '@gitlab/ui';
import CreateEpicForm from 'ee/related_items_tree/components/create_epic_form.vue';
import createDefaultStore from 'ee/related_items_tree/store';
import { mockInitialConfig, mockParentItem } from '../mock_data';
const localVue = createLocalVue();
localVue.use(Vuex);
const createComponent = (isSubmitting = false) => {
const store = createDefaultStore();
store.dispatch('setInitialConfig', mockInitialConfig);
store.dispatch('setInitialParentItem', mockParentItem);
const createComponent = (isSubmitting = false) =>
shallowMount(CreateEpicForm, {
return shallowMount(CreateEpicForm, {
localVue,
store,
propsData: {
isSubmitting,
},
});
};
describe('RelatedItemsTree', () => {
describe('CreateEpicForm', () => {
......
......@@ -15551,6 +15551,12 @@ msgstr ""
msgid "New changes were added. %{linkStart}Reload the page to review them%{linkEnd}"
msgstr ""
msgid "New confidential epic title "
msgstr ""
msgid "New confidential issue title"
msgstr ""
msgid "New deploy key"
msgstr ""
......@@ -16831,6 +16837,12 @@ msgstr ""
msgid "Paste a machine public key here. Read more about how to generate it %{link_start}here%{link_end}"
msgstr ""
msgid "Paste confidential epic link"
msgstr ""
msgid "Paste confidential issue link"
msgstr ""
msgid "Paste epic link"
msgstr ""
......
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