diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-11-22 06:10:55 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-11-22 06:10:55 +0300 |
commit | e0b6b475f203ebbe63a903328369c1363a747498 (patch) | |
tree | db5dd8ef36a7a5c81c39d94a53dd4d3ad39151fc /app/assets/javascripts/work_items | |
parent | 981548e28502956e47ac43c978cc36908636c265 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets/javascripts/work_items')
5 files changed, 89 insertions, 17 deletions
diff --git a/app/assets/javascripts/work_items/components/work_item_detail.vue b/app/assets/javascripts/work_items/components/work_item_detail.vue index 8bc78170872..5316fb9b84f 100644 --- a/app/assets/javascripts/work_items/components/work_item_detail.vue +++ b/app/assets/javascripts/work_items/components/work_item_detail.vue @@ -519,6 +519,7 @@ export default { <work-item-tree v-if="workItemType === $options.WORK_ITEM_TYPE_VALUE_OBJECTIVE" :work-item-type="workItemType" + :work-item-id="workItem.id" /> <gl-empty-state v-if="error" diff --git a/app/assets/javascripts/work_items/components/work_item_links/work_item_links_form.vue b/app/assets/javascripts/work_items/components/work_item_links/work_item_links_form.vue index 095ea86e0d8..22bbfd36a20 100644 --- a/app/assets/javascripts/work_items/components/work_item_links/work_item_links_form.vue +++ b/app/assets/javascripts/work_items/components/work_item_links/work_item_links_form.vue @@ -9,7 +9,16 @@ import projectWorkItemTypesQuery from '~/work_items/graphql/project_work_item_ty import projectWorkItemsQuery from '../../graphql/project_work_items.query.graphql'; import updateWorkItemMutation from '../../graphql/update_work_item.mutation.graphql'; import createWorkItemMutation from '../../graphql/create_work_item.mutation.graphql'; -import { FORM_TYPES, TASK_TYPE_NAME } from '../../constants'; +import { + FORM_TYPES, + WORK_ITEMS_TYPE_MAP, + WORK_ITEM_TYPE_ENUM_TASK, + I18N_WORK_ITEM_CREATE_BUTTON_LABEL, + I18N_WORK_ITEM_SEARCH_INPUT_PLACEHOLDER, + I18N_WORK_ITEM_ADD_BUTTON_LABEL, + I18N_WORK_ITEM_ADD_MULTIPLE_BUTTON_LABEL, + sprintfWorkItem, +} from '../../constants'; export default { components: { @@ -52,6 +61,11 @@ export default { type: String, required: true, }, + childrenType: { + type: String, + required: false, + default: WORK_ITEM_TYPE_ENUM_TASK, + }, }, apollo: { workItemTypes: { @@ -71,7 +85,7 @@ export default { return { projectPath: this.projectPath, searchTerm: this.search?.title || this.search, - types: ['TASK'], + types: [this.childrenType], in: this.search ? 'TITLE' : undefined, }; }, @@ -79,7 +93,9 @@ export default { return !this.searchStarted; }, update(data) { - return data.workspace.workItems.nodes.filter((wi) => !this.childrenIds.includes(wi.id)); + return data.workspace.workItems.nodes.filter( + (wi) => !this.childrenIds.includes(wi.id) && this.issuableGid !== wi.id, + ); }, }, }, @@ -99,7 +115,7 @@ export default { let workItemInput = { title: this.search?.title || this.search, projectPath: this.projectPath, - workItemTypeId: this.taskWorkItemType, + workItemTypeId: this.childWorkItemType, hierarchyWidget: { parentId: this.issuableGid, }, @@ -122,19 +138,22 @@ export default { isCreateForm() { return this.formType === FORM_TYPES.create; }, + childrenTypeName() { + return WORK_ITEMS_TYPE_MAP[this.childrenType]?.name; + }, addOrCreateButtonLabel() { if (this.isCreateForm) { - return this.$options.i18n.createChildOptionLabel; + return sprintfWorkItem(I18N_WORK_ITEM_CREATE_BUTTON_LABEL, this.childrenTypeName); } else if (this.workItemsToAdd.length > 1) { - return this.$options.i18n.addTasksButtonLabel; + return sprintfWorkItem(I18N_WORK_ITEM_ADD_MULTIPLE_BUTTON_LABEL, this.childrenTypeName); } - return this.$options.i18n.addTaskButtonLabel; + return sprintfWorkItem(I18N_WORK_ITEM_ADD_BUTTON_LABEL, this.childrenTypeName); }, addOrCreateMethod() { return this.isCreateForm ? this.createChild : this.addChild; }, - taskWorkItemType() { - return this.workItemTypes.find((type) => type.name === TASK_TYPE_NAME)?.id; + childWorkItemType() { + return this.workItemTypes.find((type) => type.name === this.childrenTypeName)?.id; }, parentIterationId() { return this.parentIteration?.id; @@ -154,6 +173,9 @@ export default { isLoading() { return this.$apollo.queries.availableWorkItems.loading; }, + addInputPlaceholder() { + return sprintfWorkItem(I18N_WORK_ITEM_SEARCH_INPUT_PLACEHOLDER, this.childrenTypeName); + }, }, created() { this.debouncedSearchKeyUpdate = debounce(this.setSearchKey, DEFAULT_DEBOUNCE_AND_THROTTLE_MS); @@ -253,17 +275,13 @@ export default { }, i18n: { inputLabel: __('Title'), - addTaskButtonLabel: s__('WorkItem|Add task'), - addTasksButtonLabel: s__('WorkItem|Add tasks'), addChildErrorMessage: s__( 'WorkItem|Something went wrong when trying to add a child. Please try again.', ), - createChildOptionLabel: s__('WorkItem|Create task'), createChildErrorMessage: s__( 'WorkItem|Something went wrong when trying to create a child. Please try again.', ), createPlaceholder: s__('WorkItem|Add a title'), - addPlaceholder: s__('WorkItem|Search existing tasks'), fieldValidationMessage: __('Maximum of 255 characters'), }, }; @@ -296,7 +314,7 @@ export default { v-model="workItemsToAdd" :dropdown-items="availableWorkItems" :loading="isLoading" - :placeholder="$options.i18n.addPlaceholder" + :placeholder="addInputPlaceholder" menu-class="gl-dropdown-menu-wide dropdown-reduced-height gl-min-h-7!" class="gl-mb-4" data-testid="work-item-token-select-input" diff --git a/app/assets/javascripts/work_items/components/work_item_links/work_item_tree.vue b/app/assets/javascripts/work_items/components/work_item_links/work_item_tree.vue index 49430cc4064..9c09ee3a66a 100644 --- a/app/assets/javascripts/work_items/components/work_item_links/work_item_tree.vue +++ b/app/assets/javascripts/work_items/components/work_item_links/work_item_tree.vue @@ -2,26 +2,42 @@ import { GlButton } from '@gitlab/ui'; import { s__ } from '~/locale'; -import { WORK_ITEMS_TREE_TEXT_MAP } from '../../constants'; +import { + FORM_TYPES, + WORK_ITEMS_TREE_TEXT_MAP, + WORK_ITEM_TYPE_ENUM_OBJECTIVE, + WORK_ITEM_TYPE_ENUM_KEY_RESULT, +} from '../../constants'; import OkrActionsSplitButton from './okr_actions_split_button.vue'; +import WorkItemLinksForm from './work_item_links_form.vue'; export default { + FORM_TYPES, WORK_ITEMS_TREE_TEXT_MAP, + WORK_ITEM_TYPE_ENUM_OBJECTIVE, + WORK_ITEM_TYPE_ENUM_KEY_RESULT, components: { GlButton, OkrActionsSplitButton, + WorkItemLinksForm, }, props: { workItemType: { type: String, required: true, }, + workItemId: { + type: String, + required: true, + }, }, data() { return { isShownAddForm: false, isOpen: true, error: null, + formType: null, + childType: null, }; }, computed: { @@ -36,9 +52,11 @@ export default { toggle() { this.isOpen = !this.isOpen; }, - showAddForm() { + showAddForm(formType, childType) { this.isOpen = true; this.isShownAddForm = true; + this.formType = formType; + this.childType = childType; this.$nextTick(() => { this.$refs.wiLinksForm.$refs.wiTitleInput?.$el.focus(); }); @@ -64,7 +82,20 @@ export default { {{ $options.WORK_ITEMS_TREE_TEXT_MAP[workItemType].title }} </h5> </div> - <okr-actions-split-button /> + <okr-actions-split-button + @showCreateObjectiveForm=" + showAddForm($options.FORM_TYPES.create, $options.WORK_ITEM_TYPE_ENUM_OBJECTIVE) + " + @showAddObjectiveForm=" + showAddForm($options.FORM_TYPES.add, $options.WORK_ITEM_TYPE_ENUM_OBJECTIVE) + " + @showCreateKeyResultForm=" + showAddForm($options.FORM_TYPES.create, $options.WORK_ITEM_TYPE_ENUM_KEY_RESULT) + " + @showAddKeyResultForm=" + showAddForm($options.FORM_TYPES.add, $options.WORK_ITEM_TYPE_ENUM_KEY_RESULT) + " + /> <div class="gl-border-l-1 gl-border-l-solid gl-border-l-gray-100 gl-pl-3 gl-ml-3"> <gl-button category="tertiary" @@ -87,6 +118,15 @@ export default { {{ $options.WORK_ITEMS_TREE_TEXT_MAP[workItemType].empty }} </p> </div> + <work-item-links-form + v-if="isShownAddForm" + ref="wiLinksForm" + data-testid="add-tree-form" + :issuable-gid="workItemId" + :form-type="formType" + :children-type="childType" + @cancel="hideAddForm" + /> </div> </div> </template> diff --git a/app/assets/javascripts/work_items/constants.js b/app/assets/javascripts/work_items/constants.js index 582532b51fd..cdb69586969 100644 --- a/app/assets/javascripts/work_items/constants.js +++ b/app/assets/javascripts/work_items/constants.js @@ -28,6 +28,7 @@ export const WORK_ITEM_TYPE_ENUM_TASK = 'TASK'; export const WORK_ITEM_TYPE_ENUM_TEST_CASE = 'TEST_CASE'; export const WORK_ITEM_TYPE_ENUM_REQUIREMENTS = 'REQUIREMENTS'; export const WORK_ITEM_TYPE_ENUM_OBJECTIVE = 'OBJECTIVE'; +export const WORK_ITEM_TYPE_ENUM_KEY_RESULT = 'KEY_RESULT'; export const WORK_ITEM_TYPE_VALUE_OBJECTIVE = 'Objective'; @@ -64,6 +65,13 @@ export const I18N_WORK_ITEM_FETCH_ITERATIONS_ERROR = s__( 'WorkItem|Something went wrong when fetching iterations. Please try again.', ); +export const I18N_WORK_ITEM_CREATE_BUTTON_LABEL = s__('WorkItem|Create %{workItemType}'); +export const I18N_WORK_ITEM_ADD_BUTTON_LABEL = s__('WorkItem|Add %{workItemType}'); +export const I18N_WORK_ITEM_ADD_MULTIPLE_BUTTON_LABEL = s__('WorkItem|Add %{workItemType}s'); +export const I18N_WORK_ITEM_SEARCH_INPUT_PLACEHOLDER = s__( + 'WorkItem|Search existing %{workItemType}s', +); + export const sprintfWorkItem = (msg, workItemTypeArg) => { const workItemType = workItemTypeArg || s__('WorkItem|Work item'); return capitalizeFirstCharacter( @@ -107,6 +115,10 @@ export const WORK_ITEMS_TYPE_MAP = { icon: `issue-type-issue`, name: s__('WorkItem|Objective'), }, + [WORK_ITEM_TYPE_ENUM_KEY_RESULT]: { + icon: `issue-type-issue`, + name: s__('WorkItem|Key result'), + }, }; export const WORK_ITEMS_TREE_TEXT_MAP = { diff --git a/app/assets/javascripts/work_items/index.js b/app/assets/javascripts/work_items/index.js index 4fbcdfe2b96..e4d37382309 100644 --- a/app/assets/javascripts/work_items/index.js +++ b/app/assets/javascripts/work_items/index.js @@ -15,6 +15,7 @@ export const initWorkItemsRoot = () => { apolloProvider, provide: { fullPath, + projectPath: fullPath, hasIssueWeightsFeature: parseBoolean(hasIssueWeightsFeature), issuesListPath, hasIterationsFeature: parseBoolean(hasIterationsFeature), |