Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-07-04 12:11:02 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-07-04 12:11:02 +0300
commit5f95234f7babb69685710dbfc637f29eeac2a917 (patch)
tree703240ac11f4565a81c505aa10821fbbd506d888 /app/assets/javascripts/boards
parent18160560396d57c07a9525eb033e66afb1f07674 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets/javascripts/boards')
-rw-r--r--app/assets/javascripts/boards/components/board_card_inner.vue9
-rw-r--r--app/assets/javascripts/boards/components/board_list.vue82
-rw-r--r--app/assets/javascripts/boards/components/board_new_issue.vue73
-rw-r--r--app/assets/javascripts/boards/constants.js26
-rw-r--r--app/assets/javascripts/boards/graphql/issue_create.mutation.graphql4
-rw-r--r--app/assets/javascripts/boards/stores/actions.js4
6 files changed, 180 insertions, 18 deletions
diff --git a/app/assets/javascripts/boards/components/board_card_inner.vue b/app/assets/javascripts/boards/components/board_card_inner.vue
index befd04c29ae..dc72936fd33 100644
--- a/app/assets/javascripts/boards/components/board_card_inner.vue
+++ b/app/assets/javascripts/boards/components/board_card_inner.vue
@@ -78,6 +78,9 @@ export default {
},
computed: {
...mapState(['isShowingLabels', 'allowSubEpics']),
+ isLoading() {
+ return this.item.isLoading || this.item.iid === '-1';
+ },
cappedAssignees() {
// e.g. maxRender is 4,
// Render up to all 4 assignees if there are only 4 assigness
@@ -243,7 +246,7 @@ export default {
<a
:href="item.path || item.webUrl || ''"
:title="item.title"
- :class="{ 'gl-text-gray-400!': item.isLoading }"
+ :class="{ 'gl-text-gray-400!': isLoading }"
class="js-no-trigger gl-text-body gl-hover-text-gray-900"
@mousemove.stop
>{{ item.title }}</a
@@ -272,9 +275,9 @@ export default {
<div
class="gl-display-flex align-items-start flex-wrap-reverse board-card-number-container gl-overflow-hidden"
>
- <gl-loading-icon v-if="item.isLoading" size="lg" class="gl-mt-5" />
+ <gl-loading-icon v-if="isLoading" size="lg" class="gl-mt-5" />
<span
- v-if="item.referencePath"
+ v-if="item.referencePath && !isLoading"
class="board-card-number gl-overflow-hidden gl-display-flex gl-mr-3 gl-mt-3 gl-font-sm gl-text-secondary"
:class="{ 'gl-font-base': isEpicBoard }"
>
diff --git a/app/assets/javascripts/boards/components/board_list.vue b/app/assets/javascripts/boards/components/board_list.vue
index af309ba9912..b4249c63b4d 100644
--- a/app/assets/javascripts/boards/components/board_list.vue
+++ b/app/assets/javascripts/boards/components/board_list.vue
@@ -22,6 +22,7 @@ import {
removeItemFromList,
updateEpicsCount,
updateIssueCountAndWeight,
+ setError,
} from '../graphql/cache_updates';
import { shouldCloneCard, moveItemVariables } from '../boards_util';
import eventHub from '../eventhub';
@@ -33,7 +34,7 @@ export default {
name: 'BoardList',
i18n: {
loading: __('Loading'),
- loadingMoreboardItems: __('Loading more'),
+ loadingMoreBoardItems: __('Loading more'),
showingAllIssues: __('Showing all issues'),
showingAllEpics: __('Showing all epics'),
},
@@ -83,6 +84,7 @@ export default {
isLoadingMore: false,
toListId: null,
toList: {},
+ addItemToListInProgress: false,
};
},
apollo: {
@@ -213,7 +215,8 @@ export default {
return !this.disabled;
},
treeRootWrapper() {
- return this.canMoveIssue && !this.listsFlags[this.list.id]?.addItemToListInProgress
+ return this.canMoveIssue &&
+ (!this.listsFlags[this.list.id]?.addItemToListInProgress || this.addItemToListInProgress)
? Draggable
: 'ul';
},
@@ -468,14 +471,14 @@ export default {
this.updateCountAndWeight({ fromListId, toListId, issuable, cache });
},
- updateCountAndWeight({ fromListId, toListId, issuable, isAddingIssue, cache }) {
+ updateCountAndWeight({ fromListId, toListId, issuable, isAddingItem, cache }) {
if (!this.isEpicBoard) {
updateIssueCountAndWeight({
fromListId,
toListId,
filterParams: this.filterParams,
issuable,
- shouldClone: isAddingIssue || this.shouldCloneCard,
+ shouldClone: isAddingItem || this.shouldCloneCard,
cache,
});
} else {
@@ -486,7 +489,7 @@ export default {
fromListId,
filterParams,
issuable,
- shouldClone: this.shouldCloneCard,
+ shouldClone: isAddingItem || this.shouldCloneCard,
cache,
});
}
@@ -538,6 +541,59 @@ export default {
},
});
},
+ async addListItem(input) {
+ this.toggleForm();
+ this.addItemToListInProgress = true;
+ try {
+ await this.$apollo.mutate({
+ mutation: listIssuablesQueries[this.issuableType].createMutation,
+ variables: {
+ input: this.isEpicBoard ? input : { ...input, moveAfterId: this.boardListItems[0]?.id },
+ withColor: this.isEpicBoard && this.glFeatures.epicColorHighlight,
+ },
+ update: (cache, { data: { createIssuable } }) => {
+ const { issuable } = createIssuable;
+ addItemToList({
+ query: listIssuablesQueries[this.issuableType].query,
+ variables: { ...this.listQueryVariables, id: this.currentList.id },
+ issuable,
+ newIndex: 0,
+ boardType: this.boardType,
+ issuableType: this.issuableType,
+ cache,
+ });
+ this.updateCountAndWeight({
+ fromListId: null,
+ toListId: this.list.id,
+ issuable,
+ isAddingItem: true,
+ cache,
+ });
+ },
+ optimisticResponse: {
+ createIssuable: {
+ errors: [],
+ issuable: {
+ ...listIssuablesQueries[this.issuableType].optimisticResponse,
+ title: input.title,
+ },
+ },
+ },
+ });
+ } catch (error) {
+ setError({
+ message: sprintf(
+ __('An error occurred while creating the %{issuableType}. Please try again.'),
+ {
+ issuableType: this.isEpicBoard ? 'epic' : 'issue',
+ },
+ ),
+ error,
+ });
+ } finally {
+ this.addItemToListInProgress = false;
+ }
+ },
},
};
</script>
@@ -556,8 +612,18 @@ export default {
>
<gl-loading-icon size="sm" />
</div>
- <board-new-issue v-if="issueCreateFormVisible" :list="list" />
- <board-new-epic v-if="epicCreateFormVisible" :list="list" />
+ <board-new-issue
+ v-if="issueCreateFormVisible"
+ :list="list"
+ :board-id="boardId"
+ @addNewIssue="addListItem"
+ />
+ <board-new-epic
+ v-if="epicCreateFormVisible"
+ :list="list"
+ :board-id="boardId"
+ @addNewEpic="addListItem"
+ />
<component
:is="treeRootWrapper"
v-show="!loading"
@@ -610,7 +676,7 @@ export default {
<gl-loading-icon
v-if="loadingMore"
size="sm"
- :label="$options.i18n.loadingMoreboardItems"
+ :label="$options.i18n.loadingMoreBoardItems"
/>
<span v-if="showingAllItems">{{ showingAllItemsText }}</span>
<span v-else>{{ paginatedIssueText }}</span>
diff --git a/app/assets/javascripts/boards/components/board_new_issue.vue b/app/assets/javascripts/boards/components/board_new_issue.vue
index 54fa4afcd78..b68444fb011 100644
--- a/app/assets/javascripts/boards/components/board_new_issue.vue
+++ b/app/assets/javascripts/boards/components/board_new_issue.vue
@@ -1,33 +1,72 @@
<script>
import { mapActions, mapGetters } from 'vuex';
-import { getMilestone } from 'ee_else_ce/boards/boards_util';
+import { s__ } from '~/locale';
+import { getMilestone, formatIssueInput, getBoardQuery } from 'ee_else_ce/boards/boards_util';
import BoardNewIssueMixin from 'ee_else_ce/boards/mixins/board_new_issue';
import { toggleFormEventPrefix } from '../constants';
import eventHub from '../eventhub';
+import { setError } from '../graphql/cache_updates';
import BoardNewItem from './board_new_item.vue';
import ProjectSelect from './project_select.vue';
export default {
name: 'BoardNewIssue',
+ i18n: {
+ errorFetchingBoard: s__('Boards|An error occurred while fetching board. Please try again.'),
+ },
components: {
BoardNewItem,
ProjectSelect,
},
mixins: [BoardNewIssueMixin],
- inject: ['fullPath', 'isGroupBoard'],
+ inject: ['boardType', 'groupId', 'fullPath', 'isGroupBoard', 'isEpicBoard', 'isApolloBoard'],
props: {
list: {
type: Object,
required: true,
},
+ boardId: {
+ type: String,
+ required: true,
+ },
},
data() {
return {
selectedProject: {},
+ board: {},
};
},
+ apollo: {
+ board: {
+ query() {
+ return getBoardQuery(this.boardType, this.isEpicBoard);
+ },
+ variables() {
+ return {
+ fullPath: this.fullPath,
+ boardId: this.boardId,
+ };
+ },
+ skip() {
+ return !this.isApolloBoard;
+ },
+ update(data) {
+ const { board } = data.workspace;
+ return {
+ ...board,
+ labels: board.labels?.nodes,
+ };
+ },
+ error(error) {
+ setError({
+ error,
+ message: this.$options.i18n.errorFetchingBoard,
+ });
+ },
+ },
+ },
computed: {
...mapGetters(['getBoardItemsByList']),
formEventPrefix() {
@@ -46,8 +85,20 @@ export default {
const labels = this.list.label ? [this.list.label] : [];
const assignees = this.list.assignee ? [this.list.assignee] : [];
const milestone = getMilestone(this.list);
- const firstItemId = this.getBoardItemsByList(this.list.id)[0]?.id;
+ if (this.isApolloBoard) {
+ return this.addNewIssueToList({
+ issueInput: {
+ title,
+ labelIds: labels?.map((l) => l.id),
+ assigneeIds: assignees?.map((a) => a?.id),
+ milestoneId: milestone?.id,
+ projectPath: this.projectPath,
+ },
+ });
+ }
+
+ const firstItemId = this.getBoardItemsByList(this.list.id)[0]?.id;
return this.addListNewIssue({
list: this.list,
issueInput: {
@@ -62,6 +113,22 @@ export default {
this.cancel();
});
},
+ addNewIssueToList({ issueInput }) {
+ const { labels, assignee, milestone, weight } = this.board;
+ const config = {
+ labels,
+ assigneeId: assignee?.id || null,
+ milestoneId: milestone?.id || null,
+ weight,
+ };
+ const input = formatIssueInput(issueInput, config);
+
+ if (!this.isGroupBoard) {
+ input.projectPath = this.fullPath;
+ }
+
+ this.$emit('addNewIssue', input);
+ },
cancel() {
eventHub.$emit(`${this.formEventPrefix}${this.list.id}`);
},
diff --git a/app/assets/javascripts/boards/constants.js b/app/assets/javascripts/boards/constants.js
index d4d1bc7804e..cb607e5220e 100644
--- a/app/assets/javascripts/boards/constants.js
+++ b/app/assets/javascripts/boards/constants.js
@@ -1,6 +1,7 @@
import boardListsQuery from 'ee_else_ce/boards/graphql/board_lists.query.graphql';
import { TYPE_EPIC, TYPE_ISSUE, WORKSPACE_GROUP, WORKSPACE_PROJECT } from '~/issues/constants';
import { s__, __ } from '~/locale';
+import { TYPENAME_ISSUE } from '~/graphql_shared/constants';
import updateEpicSubscriptionMutation from '~/sidebar/queries/update_epic_subscription.mutation.graphql';
import updateEpicTitleMutation from '~/sidebar/queries/update_epic_title.mutation.graphql';
import createBoardListMutation from './graphql/board_list_create.mutation.graphql';
@@ -11,6 +12,7 @@ import toggleListCollapsedMutation from './graphql/client/board_toggle_collapsed
import issueSetSubscriptionMutation from './graphql/issue_set_subscription.mutation.graphql';
import issueSetTitleMutation from './graphql/issue_set_title.mutation.graphql';
import issueMoveListMutation from './graphql/issue_move_list.mutation.graphql';
+import issueCreateMutation from './graphql/issue_create.mutation.graphql';
import groupBoardQuery from './graphql/group_board.query.graphql';
import projectBoardQuery from './graphql/project_board.query.graphql';
import listIssuesQuery from './graphql/lists_issues.query.graphql';
@@ -126,6 +128,30 @@ export const listIssuablesQueries = {
[TYPE_ISSUE]: {
query: listIssuesQuery,
moveMutation: issueMoveListMutation,
+ createMutation: issueCreateMutation,
+ optimisticResponse: {
+ assignees: { nodes: [], __typename: 'UserCoreConnection' },
+ confidential: false,
+ dueDate: null,
+ emailsDisabled: false,
+ hidden: false,
+ humanTimeEstimate: null,
+ humanTotalTimeSpent: null,
+ id: 'gid://gitlab/Issue/-1',
+ iid: '-1',
+ labels: { nodes: [], __typename: 'LabelConnection' },
+ milestone: null,
+ referencePath: '',
+ relativePosition: null,
+ severity: 'UNKNOWN',
+ timeEstimate: 0,
+ title: '',
+ totalTimeSpent: 0,
+ type: 'ISSUE',
+ webUrl: '',
+ weight: null,
+ __typename: TYPENAME_ISSUE,
+ },
},
};
diff --git a/app/assets/javascripts/boards/graphql/issue_create.mutation.graphql b/app/assets/javascripts/boards/graphql/issue_create.mutation.graphql
index 643d5dcfe4c..55cb34c0930 100644
--- a/app/assets/javascripts/boards/graphql/issue_create.mutation.graphql
+++ b/app/assets/javascripts/boards/graphql/issue_create.mutation.graphql
@@ -1,8 +1,8 @@
#import "ee_else_ce/boards/graphql/issue.fragment.graphql"
mutation CreateIssue($input: CreateIssueInput!) {
- createIssue(input: $input) {
- issue {
+ createIssuable: createIssue(input: $input) {
+ issuable: issue {
...Issue
}
errors
diff --git a/app/assets/javascripts/boards/stores/actions.js b/app/assets/javascripts/boards/stores/actions.js
index d96d92948be..e044283534a 100644
--- a/app/assets/javascripts/boards/stores/actions.js
+++ b/app/assets/javascripts/boards/stores/actions.js
@@ -743,11 +743,11 @@ export default {
},
})
.then(({ data }) => {
- if (data.createIssue.errors.length) {
+ if (data.createIssuable.errors.length) {
throw new Error();
}
- const rawIssue = data.createIssue?.issue;
+ const rawIssue = data.createIssuable?.issuable;
const formattedIssue = formatIssue(rawIssue);
dispatch('removeListItem', { listId: list.id, itemId: placeholderId });
dispatch('addListItem', { list, item: formattedIssue, position: 0 });