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-10-04 15:17:55 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-10-04 15:17:55 +0300
commit49d36ce6e3484aea8131dd892a02f8304ee61aa1 (patch)
treeee7d8403c0ebacf5b5953ebbf1a838dd957eac6b /app/assets/javascripts
parentb68afda3299d372ef0b3745e0603a9d51369650b (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets/javascripts')
-rw-r--r--app/assets/javascripts/ci/job_details/components/log/line.vue2
-rw-r--r--app/assets/javascripts/ci/job_details/components/log/line_header.vue2
-rw-r--r--app/assets/javascripts/ci/job_details/components/log/line_number.vue5
-rw-r--r--app/assets/javascripts/ci/job_details/store/utils.js81
-rw-r--r--app/assets/javascripts/issues/show/components/description.vue14
-rw-r--r--app/assets/javascripts/jira_connect/subscriptions/constants.js8
-rw-r--r--app/assets/javascripts/members/components/action_dropdowns/remove_member_dropdown_item.vue2
-rw-r--r--app/assets/javascripts/members/components/action_dropdowns/user_action_dropdown.vue1
-rw-r--r--app/assets/javascripts/pages/groups/work_items/show/index.js4
-rw-r--r--app/assets/javascripts/pages/projects/work_items/index.js2
-rw-r--r--app/assets/javascripts/repository/components/table/index.vue2
-rw-r--r--app/assets/javascripts/repository/components/table/row.vue2
-rw-r--r--app/assets/javascripts/super_sidebar/components/user_name_group.vue2
-rw-r--r--app/assets/javascripts/work_items/components/notes/work_item_add_note.vue7
-rw-r--r--app/assets/javascripts/work_items/components/notes/work_item_note.vue15
-rw-r--r--app/assets/javascripts/work_items/components/work_item_actions.vue7
-rw-r--r--app/assets/javascripts/work_items/components/work_item_created_updated.vue11
-rw-r--r--app/assets/javascripts/work_items/components/work_item_description.vue7
-rw-r--r--app/assets/javascripts/work_items/components/work_item_detail.vue21
-rw-r--r--app/assets/javascripts/work_items/components/work_item_labels.vue7
-rw-r--r--app/assets/javascripts/work_items/components/work_item_links/work_item_children_wrapper.vue25
-rw-r--r--app/assets/javascripts/work_items/components/work_item_links/work_item_links.vue15
-rw-r--r--app/assets/javascripts/work_items/components/work_item_links/work_item_links_form.vue10
-rw-r--r--app/assets/javascripts/work_items/components/work_item_relationships/work_item_relationships.vue6
-rw-r--r--app/assets/javascripts/work_items/components/work_item_todos.vue10
-rw-r--r--app/assets/javascripts/work_items/components/work_item_type_icon.vue5
-rw-r--r--app/assets/javascripts/work_items/graphql/cache_utils.js15
-rw-r--r--app/assets/javascripts/work_items/graphql/group_work_item_by_iid.query.graphql12
-rw-r--r--app/assets/javascripts/work_items/index.js19
-rw-r--r--app/assets/javascripts/work_items/pages/create_work_item.vue5
30 files changed, 213 insertions, 111 deletions
diff --git a/app/assets/javascripts/ci/job_details/components/log/line.vue b/app/assets/javascripts/ci/job_details/components/log/line.vue
index eba8727c939..416f75372f9 100644
--- a/app/assets/javascripts/ci/job_details/components/log/line.vue
+++ b/app/assets/javascripts/ci/job_details/components/log/line.vue
@@ -56,7 +56,7 @@ export default {
if (window.location.hash) {
const hash = getLocationHash();
- const lineToMatch = `L${line.lineNumber + 1}`;
+ const lineToMatch = `L${line.lineNumber}`;
if (hash === lineToMatch) {
applyHashHighlight = true;
diff --git a/app/assets/javascripts/ci/job_details/components/log/line_header.vue b/app/assets/javascripts/ci/job_details/components/log/line_header.vue
index f2e9e09c334..658a94e6af4 100644
--- a/app/assets/javascripts/ci/job_details/components/log/line_header.vue
+++ b/app/assets/javascripts/ci/job_details/components/log/line_header.vue
@@ -46,7 +46,7 @@ export default {
},
mounted() {
const hash = getLocationHash();
- const lineToMatch = `L${this.line.lineNumber + 1}`;
+ const lineToMatch = `L${this.line.lineNumber}`;
if (hash === lineToMatch) {
this.applyHashHighlight = true;
diff --git a/app/assets/javascripts/ci/job_details/components/log/line_number.vue b/app/assets/javascripts/ci/job_details/components/log/line_number.vue
index 7ca9154d2fe..30b4c80f3fa 100644
--- a/app/assets/javascripts/ci/job_details/components/log/line_number.vue
+++ b/app/assets/javascripts/ci/job_details/components/log/line_number.vue
@@ -14,8 +14,7 @@ export default {
render(h, { props }) {
const { lineNumber, path } = props;
- const parsedLineNumber = lineNumber + 1;
- const lineId = `L${parsedLineNumber}`;
+ const lineId = `L${lineNumber}`;
const lineHref = `${path}#${lineId}`;
return h(
@@ -27,7 +26,7 @@ export default {
href: lineHref,
},
},
- parsedLineNumber,
+ lineNumber,
);
},
};
diff --git a/app/assets/javascripts/ci/job_details/store/utils.js b/app/assets/javascripts/ci/job_details/store/utils.js
index ccd04d52e30..b18a3fa162d 100644
--- a/app/assets/javascripts/ci/job_details/store/utils.js
+++ b/app/assets/javascripts/ci/job_details/store/utils.js
@@ -19,20 +19,17 @@ export const parseLine = (line = {}, lineNumber) => ({
* @param Number lineNumber
*/
export const parseHeaderLine = (line = {}, lineNumber, hash) => {
+ let isClosed = parseBoolean(line.section_options?.collapsed);
+
// if a hash is present in the URL then we ensure
// all sections are visible so we can scroll to the hash
// in the DOM
if (hash) {
- return {
- isClosed: false,
- isHeader: true,
- line: parseLine(line, lineNumber),
- lines: [],
- };
+ isClosed = false;
}
return {
- isClosed: parseBoolean(line.section_options?.collapsed),
+ isClosed,
isHeader: true,
line: parseLine(line, lineNumber),
lines: [],
@@ -80,27 +77,28 @@ export const isCollapsibleSection = (acc = [], last = {}, section = {}) =>
section.section === last.line.section;
/**
- * Returns the lineNumber of the last line in
- * a parsed log
+ * Returns the next line number in the parsed log
*
* @param Array acc
* @returns Number
*/
-export const getIncrementalLineNumber = (acc) => {
- let lineNumberValue;
- const lastIndex = acc.length - 1;
- const lastElement = acc[lastIndex];
+export const getNextLineNumber = (acc) => {
+ if (!acc?.length) {
+ return 1;
+ }
+
+ const lastElement = acc[acc.length - 1];
const nestedLines = lastElement.lines;
if (lastElement.isHeader && !nestedLines.length && lastElement.line) {
- lineNumberValue = lastElement.line.lineNumber;
- } else if (lastElement.isHeader && nestedLines.length) {
- lineNumberValue = nestedLines[nestedLines.length - 1].lineNumber;
- } else {
- lineNumberValue = lastElement.lineNumber;
+ return lastElement.line.lineNumber + 1;
}
- return lineNumberValue === 0 ? 1 : lineNumberValue + 1;
+ if (lastElement.isHeader && nestedLines.length) {
+ return nestedLines[nestedLines.length - 1].lineNumber + 1;
+ }
+
+ return lastElement.lineNumber + 1;
};
/**
@@ -119,31 +117,28 @@ export const getIncrementalLineNumber = (acc) => {
* @returns Array parsed log lines
*/
export const logLinesParser = (lines = [], prevLogLines = [], hash = '') =>
- lines.reduce(
- (acc, line, index) => {
- const lineNumber = acc.length > 0 ? getIncrementalLineNumber(acc) : index;
-
- const last = acc[acc.length - 1];
-
- // If the object is an header, we parse it into another structure
- if (line.section_header) {
- acc.push(parseHeaderLine(line, lineNumber, hash));
- } else if (isCollapsibleSection(acc, last, line)) {
- // if the object belongs to a nested section, we append it to the new `lines` array of the
- // previously formatted header
- last.lines.push(parseLine(line, lineNumber));
- } else if (line.section_duration) {
- // if the line has section_duration, we look for the correct header to add it
- addDurationToHeader(acc, line);
- } else {
- // otherwise it's a regular line
- acc.push(parseLine(line, lineNumber));
- }
+ lines.reduce((acc, line) => {
+ const lineNumber = getNextLineNumber(acc);
+
+ const last = acc[acc.length - 1];
+
+ // If the object is an header, we parse it into another structure
+ if (line.section_header) {
+ acc.push(parseHeaderLine(line, lineNumber, hash));
+ } else if (isCollapsibleSection(acc, last, line)) {
+ // if the object belongs to a nested section, we append it to the new `lines` array of the
+ // previously formatted header
+ last.lines.push(parseLine(line, lineNumber));
+ } else if (line.section_duration) {
+ // if the line has section_duration, we look for the correct header to add it
+ addDurationToHeader(acc, line);
+ } else {
+ // otherwise it's a regular line
+ acc.push(parseLine(line, lineNumber));
+ }
- return acc;
- },
- [...prevLogLines],
- );
+ return acc;
+ }, prevLogLines);
/**
* Finds the repeated offset, removes the old one
diff --git a/app/assets/javascripts/issues/show/components/description.vue b/app/assets/javascripts/issues/show/components/description.vue
index acbba216601..5735a518a3e 100644
--- a/app/assets/javascripts/issues/show/components/description.vue
+++ b/app/assets/javascripts/issues/show/components/description.vue
@@ -362,7 +362,12 @@ export default {
},
},
update: (cache, { data: { workItemCreate } }) =>
- addHierarchyChild(cache, this.fullPath, String(this.issueIid), workItemCreate.workItem),
+ addHierarchyChild({
+ cache,
+ fullPath: this.fullPath,
+ iid: String(this.issueIid),
+ workItem: workItemCreate.workItem,
+ }),
});
const { workItem, errors } = data.workItemCreate;
@@ -392,7 +397,12 @@ export default {
mutation: deleteWorkItemMutation,
variables: { input: { id } },
update: (cache) =>
- removeHierarchyChild(cache, this.fullPath, String(this.issueIid), { id }),
+ removeHierarchyChild({
+ cache,
+ fullPath: this.fullPath,
+ iid: String(this.issueIid),
+ workItem: { id },
+ }),
});
if (data.workItemDelete.errors?.length) {
diff --git a/app/assets/javascripts/jira_connect/subscriptions/constants.js b/app/assets/javascripts/jira_connect/subscriptions/constants.js
index 72fd25a6230..1a10360ed30 100644
--- a/app/assets/javascripts/jira_connect/subscriptions/constants.js
+++ b/app/assets/javascripts/jira_connect/subscriptions/constants.js
@@ -37,11 +37,11 @@ export const I18N_OAUTH_FAILED_MESSAGE = s__(
export const INTEGRATIONS_DOC_LINK = helpPagePath('integration/jira/development_panel', {
anchor: 'use-the-integration',
});
-export const OAUTH_SELF_MANAGED_DOC_LINK = helpPagePath('integration/jira/connect-app', {
- anchor: 'connect-the-gitlab-for-jira-cloud-app-for-self-managed-instances',
+export const OAUTH_SELF_MANAGED_DOC_LINK = helpPagePath('administration/settings/jira_cloud_app', {
+ anchor: 'set-up-oauth-authentication',
});
-export const FAILED_TO_UPDATE_DOC_LINK = helpPagePath('integration/jira/connect-app', {
- anchor: 'failed-to-update-the-gitlab-instance-for-self-managed-instances',
+export const FAILED_TO_UPDATE_DOC_LINK = helpPagePath('administration/settings/jira_cloud_app', {
+ anchor: 'failed-to-update-the-gitlab-instance',
});
export const GITLAB_COM_BASE_PATH = 'https://gitlab.com';
diff --git a/app/assets/javascripts/members/components/action_dropdowns/remove_member_dropdown_item.vue b/app/assets/javascripts/members/components/action_dropdowns/remove_member_dropdown_item.vue
index 920febb0e67..68bfb99a139 100644
--- a/app/assets/javascripts/members/components/action_dropdowns/remove_member_dropdown_item.vue
+++ b/app/assets/javascripts/members/components/action_dropdowns/remove_member_dropdown_item.vue
@@ -77,7 +77,7 @@ export default {
<template>
<gl-disclosure-dropdown-item
- data-qa-selector="delete_member_dropdown_item"
+ data-testid="delete-member-dropdown-item"
@action="showRemoveMemberModal(modalData)"
>
<template #list-item>
diff --git a/app/assets/javascripts/members/components/action_dropdowns/user_action_dropdown.vue b/app/assets/javascripts/members/components/action_dropdowns/user_action_dropdown.vue
index 25dc4831b11..a8c97060915 100644
--- a/app/assets/javascripts/members/components/action_dropdowns/user_action_dropdown.vue
+++ b/app/assets/javascripts/members/components/action_dropdowns/user_action_dropdown.vue
@@ -109,7 +109,6 @@ export default {
no-caret
placement="right"
data-testid="user-action-dropdown"
- data-qa-selector="user_action_dropdown"
>
<disable-two-factor-dropdown-item
v-if="permissions.canDisableTwoFactor"
diff --git a/app/assets/javascripts/pages/groups/work_items/show/index.js b/app/assets/javascripts/pages/groups/work_items/show/index.js
new file mode 100644
index 00000000000..c091fbcc2b2
--- /dev/null
+++ b/app/assets/javascripts/pages/groups/work_items/show/index.js
@@ -0,0 +1,4 @@
+import { WORKSPACE_GROUP } from '~/issues/constants';
+import { initWorkItemsRoot } from '~/work_items';
+
+initWorkItemsRoot(WORKSPACE_GROUP);
diff --git a/app/assets/javascripts/pages/projects/work_items/index.js b/app/assets/javascripts/pages/projects/work_items/index.js
index 11c257611f0..b44ca708b28 100644
--- a/app/assets/javascripts/pages/projects/work_items/index.js
+++ b/app/assets/javascripts/pages/projects/work_items/index.js
@@ -1,3 +1,3 @@
-import { initWorkItemsRoot } from '~/work_items/index';
+import { initWorkItemsRoot } from '~/work_items';
initWorkItemsRoot();
diff --git a/app/assets/javascripts/repository/components/table/index.vue b/app/assets/javascripts/repository/components/table/index.vue
index 557e9cd168f..3da7daa3eec 100644
--- a/app/assets/javascripts/repository/components/table/index.vue
+++ b/app/assets/javascripts/repository/components/table/index.vue
@@ -118,7 +118,7 @@ export default {
class="table tree-table"
:class="{ 'gl-table-layout-fixed': !showParentRow }"
aria-live="polite"
- data-qa-selector="file_tree_table"
+ data-testid="file-tree-table"
>
<table-header v-once />
<tbody>
diff --git a/app/assets/javascripts/repository/components/table/row.vue b/app/assets/javascripts/repository/components/table/row.vue
index a76d822317a..526757e6147 100644
--- a/app/assets/javascripts/repository/components/table/row.vue
+++ b/app/assets/javascripts/repository/components/table/row.vue
@@ -219,7 +219,7 @@ export default {
'is-submodule': isSubmodule,
}"
class="tree-item-link str-truncated"
- data-qa-selector="file_name_link"
+ data-testid="file-name-link"
>
<file-icon
:file-name="fullPath"
diff --git a/app/assets/javascripts/super_sidebar/components/user_name_group.vue b/app/assets/javascripts/super_sidebar/components/user_name_group.vue
index 3c8059387fa..c9971639e74 100644
--- a/app/assets/javascripts/super_sidebar/components/user_name_group.vue
+++ b/app/assets/javascripts/super_sidebar/components/user_name_group.vue
@@ -41,7 +41,7 @@ export default {
item.extraAttrs = {
...USER_MENU_TRACKING_DEFAULTS,
'data-track-label': 'user_profile',
- 'data-testid': 'user_profile_link',
+ 'data-testid': 'user-profile-link',
};
}
diff --git a/app/assets/javascripts/work_items/components/notes/work_item_add_note.vue b/app/assets/javascripts/work_items/components/notes/work_item_add_note.vue
index a17fa691404..f39a12bb6f9 100644
--- a/app/assets/javascripts/work_items/components/notes/work_item_add_note.vue
+++ b/app/assets/javascripts/work_items/components/notes/work_item_add_note.vue
@@ -5,6 +5,7 @@ import { ASC } from '~/notes/constants';
import { __ } from '~/locale';
import { clearDraft } from '~/lib/utils/autosave';
import createNoteMutation from '../../graphql/notes/create_work_item_note.mutation.graphql';
+import groupWorkItemByIidQuery from '../../graphql/group_work_item_by_iid.query.graphql';
import workItemByIidQuery from '../../graphql/work_item_by_iid.query.graphql';
import { TRACKING_CATEGORY_SHOW, i18n } from '../../constants';
import WorkItemNoteSignedOut from './work_item_note_signed_out.vue';
@@ -21,7 +22,7 @@ export default {
WorkItemCommentForm,
},
mixins: [Tracking.mixin()],
- inject: ['fullPath'],
+ inject: ['fullPath', 'isGroup'],
props: {
workItemId: {
type: String,
@@ -90,7 +91,9 @@ export default {
},
apollo: {
workItem: {
- query: workItemByIidQuery,
+ query() {
+ return this.isGroup ? groupWorkItemByIidQuery : workItemByIidQuery;
+ },
variables() {
return {
fullPath: this.fullPath,
diff --git a/app/assets/javascripts/work_items/components/notes/work_item_note.vue b/app/assets/javascripts/work_items/components/notes/work_item_note.vue
index b5e3ea68725..0c1dac60bba 100644
--- a/app/assets/javascripts/work_items/components/notes/work_item_note.vue
+++ b/app/assets/javascripts/work_items/components/notes/work_item_note.vue
@@ -3,7 +3,6 @@ import { GlAvatarLink, GlAvatar } from '@gitlab/ui';
import * as Sentry from '@sentry/browser';
import toast from '~/vue_shared/plugins/global_toast';
import { __ } from '~/locale';
-import { i18n, TRACKING_CATEGORY_SHOW } from '~/work_items/constants';
import Tracking from '~/tracking';
import { updateDraft, clearDraft } from '~/lib/utils/autosave';
import { renderMarkdown } from '~/notes/utils';
@@ -11,15 +10,17 @@ import { getLocationHash } from '~/lib/utils/url_utility';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import EditedAt from '~/issues/show/components/edited.vue';
import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue';
-import NoteBody from '~/work_items/components/notes/work_item_note_body.vue';
import NoteHeader from '~/notes/components/note_header.vue';
-import NoteActions from '~/work_items/components/notes/work_item_note_actions.vue';
-import updateWorkItemMutation from '~/work_items/graphql/update_work_item.mutation.graphql';
+import { i18n, TRACKING_CATEGORY_SHOW } from '../../constants';
+import groupWorkItemByIidQuery from '../../graphql/group_work_item_by_iid.query.graphql';
+import updateWorkItemMutation from '../../graphql/update_work_item.mutation.graphql';
import updateWorkItemNoteMutation from '../../graphql/notes/update_work_item_note.mutation.graphql';
import workItemByIidQuery from '../../graphql/work_item_by_iid.query.graphql';
import { isAssigneesWidget } from '../../utils';
import WorkItemCommentForm from './work_item_comment_form.vue';
+import NoteActions from './work_item_note_actions.vue';
import WorkItemNoteAwardsList from './work_item_note_awards_list.vue';
+import NoteBody from './work_item_note_body.vue';
export default {
name: 'WorkItemNoteThread',
@@ -35,7 +36,7 @@ export default {
EditedAt,
},
mixins: [Tracking.mixin()],
- inject: ['fullPath'],
+ inject: ['fullPath', 'isGroup'],
props: {
workItemId: {
type: String,
@@ -169,7 +170,9 @@ export default {
},
apollo: {
workItem: {
- query: workItemByIidQuery,
+ query() {
+ return this.isGroup ? groupWorkItemByIidQuery : workItemByIidQuery;
+ },
variables() {
return {
fullPath: this.fullPath,
diff --git a/app/assets/javascripts/work_items/components/work_item_actions.vue b/app/assets/javascripts/work_items/components/work_item_actions.vue
index 18aa4d55086..b19236e5961 100644
--- a/app/assets/javascripts/work_items/components/work_item_actions.vue
+++ b/app/assets/javascripts/work_items/components/work_item_actions.vue
@@ -15,7 +15,8 @@ import { __, s__ } from '~/locale';
import Tracking from '~/tracking';
import toast from '~/vue_shared/plugins/global_toast';
import { isLoggedIn } from '~/lib/utils/common_utils';
-import workItemByIidQuery from '~/work_items/graphql/work_item_by_iid.query.graphql';
+import groupWorkItemByIidQuery from '../graphql/group_work_item_by_iid.query.graphql';
+import workItemByIidQuery from '../graphql/work_item_by_iid.query.graphql';
import {
sprintfWorkItem,
@@ -70,7 +71,7 @@ export default {
copyCreateNoteEmailTestId: TEST_ID_COPY_CREATE_NOTE_EMAIL_ACTION,
deleteActionTestId: TEST_ID_DELETE_ACTION,
promoteActionTestId: TEST_ID_PROMOTE_ACTION,
- inject: ['fullPath'],
+ inject: ['fullPath', 'isGroup'],
props: {
workItemId: {
type: String,
@@ -256,7 +257,7 @@ export default {
},
updateWorkItemNotificationsWidgetCache({ cache, issue }) {
const query = {
- query: workItemByIidQuery,
+ query: this.isGroup ? groupWorkItemByIidQuery : workItemByIidQuery,
variables: { fullPath: this.fullPath, iid: this.workItemIid },
};
// Read the work item object
diff --git a/app/assets/javascripts/work_items/components/work_item_created_updated.vue b/app/assets/javascripts/work_items/components/work_item_created_updated.vue
index 14e55134048..ac1496cbc37 100644
--- a/app/assets/javascripts/work_items/components/work_item_created_updated.vue
+++ b/app/assets/javascripts/work_items/components/work_item_created_updated.vue
@@ -3,10 +3,11 @@ import { GlAvatarLink, GlSprintf, GlLoadingIcon } from '@gitlab/ui';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import { WORKSPACE_PROJECT } from '~/issues/constants';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
-import WorkItemStateBadge from '~/work_items/components/work_item_state_badge.vue';
import ConfidentialityBadge from '~/vue_shared/components/confidentiality_badge.vue';
-import WorkItemTypeIcon from '~/work_items/components/work_item_type_icon.vue';
+import groupWorkItemByIidQuery from '../graphql/group_work_item_by_iid.query.graphql';
import workItemByIidQuery from '../graphql/work_item_by_iid.query.graphql';
+import WorkItemStateBadge from './work_item_state_badge.vue';
+import WorkItemTypeIcon from './work_item_type_icon.vue';
export default {
components: {
@@ -18,7 +19,7 @@ export default {
ConfidentialityBadge,
GlLoadingIcon,
},
- inject: ['fullPath'],
+ inject: ['fullPath', 'isGroup'],
props: {
workItemIid: {
type: String,
@@ -59,7 +60,9 @@ export default {
},
apollo: {
workItem: {
- query: workItemByIidQuery,
+ query() {
+ return this.isGroup ? groupWorkItemByIidQuery : workItemByIidQuery;
+ },
variables() {
return {
fullPath: this.fullPath,
diff --git a/app/assets/javascripts/work_items/components/work_item_description.vue b/app/assets/javascripts/work_items/components/work_item_description.vue
index 58bf524f450..b1596183f6c 100644
--- a/app/assets/javascripts/work_items/components/work_item_description.vue
+++ b/app/assets/javascripts/work_items/components/work_item_description.vue
@@ -10,6 +10,7 @@ import Tracking from '~/tracking';
import MarkdownEditor from '~/vue_shared/components/markdown/markdown_editor.vue';
import { autocompleteDataSources, markdownPreviewPath } from '../utils';
import updateWorkItemMutation from '../graphql/update_work_item.mutation.graphql';
+import groupWorkItemByIidQuery from '../graphql/group_work_item_by_iid.query.graphql';
import workItemByIidQuery from '../graphql/work_item_by_iid.query.graphql';
import { i18n, TRACKING_CATEGORY_SHOW, WIDGET_TYPE_DESCRIPTION } from '../constants';
import WorkItemDescriptionRendered from './work_item_description_rendered.vue';
@@ -25,7 +26,7 @@ export default {
WorkItemDescriptionRendered,
},
mixins: [Tracking.mixin()],
- inject: ['fullPath'],
+ inject: ['fullPath', 'isGroup'],
props: {
workItemId: {
type: String,
@@ -55,7 +56,9 @@ export default {
},
apollo: {
workItem: {
- query: workItemByIidQuery,
+ query() {
+ return this.isGroup ? groupWorkItemByIidQuery : workItemByIidQuery;
+ },
variables() {
return {
fullPath: this.fullPath,
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 29fa60926c3..ff1b45c4b9e 100644
--- a/app/assets/javascripts/work_items/components/work_item_detail.vue
+++ b/app/assets/javascripts/work_items/components/work_item_detail.vue
@@ -16,7 +16,6 @@ import { getParameterByName, updateHistory, setUrlParams } from '~/lib/utils/url
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import { isLoggedIn } from '~/lib/utils/common_utils';
-import WorkItemTypeIcon from '~/work_items/components/work_item_type_icon.vue';
import AbuseCategorySelector from '~/abuse_reports/components/abuse_category_selector.vue';
import ConfidentialityBadge from '~/vue_shared/components/confidentiality_badge.vue';
import { WORKSPACE_PROJECT } from '~/issues/constants';
@@ -37,6 +36,7 @@ import {
import workItemUpdatedSubscription from '../graphql/work_item_updated.subscription.graphql';
import updateWorkItemMutation from '../graphql/update_work_item.mutation.graphql';
import updateWorkItemTaskMutation from '../graphql/update_work_item_task.mutation.graphql';
+import groupWorkItemByIidQuery from '../graphql/group_work_item_by_iid.query.graphql';
import workItemByIidQuery from '../graphql/work_item_by_iid.query.graphql';
import { findHierarchyWidgetChildren } from '../utils';
@@ -52,6 +52,7 @@ import WorkItemDetailModal from './work_item_detail_modal.vue';
import WorkItemAwardEmoji from './work_item_award_emoji.vue';
import WorkItemStateToggleButton from './work_item_state_toggle_button.vue';
import WorkItemRelationships from './work_item_relationships/work_item_relationships.vue';
+import WorkItemTypeIcon from './work_item_type_icon.vue';
export default {
i18n,
@@ -84,7 +85,7 @@ export default {
WorkItemRelationships,
},
mixins: [glFeatureFlagMixin()],
- inject: ['fullPath', 'reportAbusePath'],
+ inject: ['fullPath', 'isGroup', 'reportAbusePath'],
props: {
isModal: {
type: Boolean,
@@ -118,7 +119,9 @@ export default {
},
apollo: {
workItem: {
- query: workItemByIidQuery,
+ query() {
+ return this.isGroup ? groupWorkItemByIidQuery : workItemByIidQuery;
+ },
variables() {
return {
fullPath: this.fullPath,
@@ -189,8 +192,8 @@ export default {
canAssignUnassignUser() {
return this.workItemAssignees && this.canSetWorkItemMetadata;
},
- fullPath() {
- return this.workItem?.project.fullPath;
+ projectFullPath() {
+ return this.workItem?.project?.fullPath;
},
workItemsMvc2Enabled() {
return this.glFeatures.workItemsMvc2;
@@ -460,7 +463,7 @@ export default {
v-if="showWorkItemCurrentUserTodos"
:work-item-id="workItem.id"
:work-item-iid="workItemIid"
- :work-item-fullpath="workItem.project.fullPath"
+ :work-item-fullpath="projectFullPath"
:current-user-todos="currentUserTodos"
@error="updateError = $event"
/>
@@ -535,7 +538,7 @@ export default {
v-if="showWorkItemCurrentUserTodos"
:work-item-id="workItem.id"
:work-item-iid="workItemIid"
- :work-item-fullpath="workItem.project.fullPath"
+ :work-item-fullpath="projectFullPath"
:current-user-todos="currentUserTodos"
@error="updateError = $event"
/>
@@ -585,7 +588,7 @@ export default {
<work-item-award-emoji
v-if="workItemAwardEmoji"
:work-item-id="workItem.id"
- :work-item-fullpath="workItem.project.fullPath"
+ :work-item-fullpath="projectFullPath"
:award-emoji="workItemAwardEmoji.awardEmoji"
:work-item-iid="workItemIid"
@error="updateError = $event"
@@ -607,7 +610,7 @@ export default {
v-if="showWorkItemLinkedItems"
:work-item-id="workItem.id"
:work-item-iid="workItemIid"
- :work-item-full-path="workItem.project.fullPath"
+ :work-item-full-path="projectFullPath"
:work-item-type="workItem.workItemType.name"
@showModal="openInModal"
/>
diff --git a/app/assets/javascripts/work_items/components/work_item_labels.vue b/app/assets/javascripts/work_items/components/work_item_labels.vue
index 1405a12a101..c42186d1c27 100644
--- a/app/assets/javascripts/work_items/components/work_item_labels.vue
+++ b/app/assets/javascripts/work_items/components/work_item_labels.vue
@@ -8,6 +8,7 @@ import LabelItem from '~/sidebar/components/labels/labels_select_widget/label_it
import { DEFAULT_DEBOUNCE_AND_THROTTLE_MS } from '~/lib/utils/constants';
import { isScopedLabel } from '~/lib/utils/common_utils';
import updateWorkItemMutation from '../graphql/update_work_item.mutation.graphql';
+import groupWorkItemByIidQuery from '../graphql/group_work_item_by_iid.query.graphql';
import workItemByIidQuery from '../graphql/work_item_by_iid.query.graphql';
import { i18n, I18N_WORK_ITEM_ERROR_FETCHING_LABELS, TRACKING_CATEGORY_SHOW } from '../constants';
import { isLabelsWidget } from '../utils';
@@ -37,7 +38,7 @@ export default {
LabelItem,
},
mixins: [Tracking.mixin()],
- inject: ['fullPath'],
+ inject: ['fullPath', 'isGroup'],
props: {
workItemId: {
type: String,
@@ -65,7 +66,9 @@ export default {
},
apollo: {
workItem: {
- query: workItemByIidQuery,
+ query() {
+ return this.isGroup ? groupWorkItemByIidQuery : workItemByIidQuery;
+ },
variables() {
return {
fullPath: this.fullPath,
diff --git a/app/assets/javascripts/work_items/components/work_item_links/work_item_children_wrapper.vue b/app/assets/javascripts/work_items/components/work_item_links/work_item_children_wrapper.vue
index 9d9414b5399..b74afbde44a 100644
--- a/app/assets/javascripts/work_items/components/work_item_links/work_item_children_wrapper.vue
+++ b/app/assets/javascripts/work_items/components/work_item_links/work_item_children_wrapper.vue
@@ -13,6 +13,7 @@ import { findHierarchyWidgets } from '../../utils';
import { addHierarchyChild, removeHierarchyChild } from '../../graphql/cache_utils';
import reorderWorkItem from '../../graphql/reorder_work_item.mutation.graphql';
import updateWorkItemMutation from '../../graphql/update_work_item.mutation.graphql';
+import groupWorkItemByIidQuery from '../../graphql/group_work_item_by_iid.query.graphql';
import workItemByIidQuery from '../../graphql/work_item_by_iid.query.graphql';
import WorkItemLinkChild from './work_item_link_child.vue';
@@ -20,7 +21,7 @@ export default {
components: {
WorkItemLinkChild,
},
- inject: ['fullPath'],
+ inject: ['fullPath', 'isGroup'],
props: {
workItemType: {
type: String,
@@ -83,7 +84,14 @@ export default {
const { data } = await this.$apollo.mutate({
mutation: updateWorkItemMutation,
variables: { input: { id: child.id, hierarchyWidget: { parentId: null } } },
- update: (cache) => removeHierarchyChild(cache, this.fullPath, this.workItemIid, child),
+ update: (cache) =>
+ removeHierarchyChild({
+ cache,
+ fullPath: this.fullPath,
+ iid: this.workItemIid,
+ isGroup: this.isGroup,
+ workItem: child,
+ }),
});
if (data.workItemUpdate.errors.length) {
@@ -109,7 +117,14 @@ export default {
const { data } = await this.$apollo.mutate({
mutation: updateWorkItemMutation,
variables: { input: { id: child.id, hierarchyWidget: { parentId: this.workItemId } } },
- update: (cache) => addHierarchyChild(cache, this.fullPath, this.workItemIid, child),
+ update: (cache) =>
+ addHierarchyChild({
+ cache,
+ fullPath: this.fullPath,
+ iid: this.workItemIid,
+ isGroup: this.isGroup,
+ workItem: child,
+ }),
});
if (data.workItemUpdate.errors.length) {
@@ -124,7 +139,7 @@ export default {
},
addWorkItemQuery({ iid }) {
this.$apollo.addSmartQuery('prefetchedWorkItem', {
- query: workItemByIidQuery,
+ query: this.isGroup ? groupWorkItemByIidQuery : workItemByIidQuery,
variables: {
fullPath: this.fullPath,
iid,
@@ -206,7 +221,7 @@ export default {
update: (store) => {
store.updateQuery(
{
- query: workItemByIidQuery,
+ query: this.isGroup ? groupWorkItemByIidQuery : workItemByIidQuery,
variables: { fullPath: this.fullPath, iid: this.workItemIid },
},
(sourceData) =>
diff --git a/app/assets/javascripts/work_items/components/work_item_links/work_item_links.vue b/app/assets/javascripts/work_items/components/work_item_links/work_item_links.vue
index eb836007e75..c7dd7c5023d 100644
--- a/app/assets/javascripts/work_items/components/work_item_links/work_item_links.vue
+++ b/app/assets/javascripts/work_items/components/work_item_links/work_item_links.vue
@@ -18,6 +18,7 @@ import AbuseCategorySelector from '~/abuse_reports/components/abuse_category_sel
import { FORM_TYPES, WIDGET_ICONS, WORK_ITEM_STATUS_TEXT } from '../../constants';
import { findHierarchyWidgetChildren } from '../../utils';
import { removeHierarchyChild } from '../../graphql/cache_utils';
+import groupWorkItemByIidQuery from '../../graphql/group_work_item_by_iid.query.graphql';
import workItemByIidQuery from '../../graphql/work_item_by_iid.query.graphql';
import WidgetWrapper from '../widget_wrapper.vue';
import WorkItemDetailModal from '../work_item_detail_modal.vue';
@@ -39,7 +40,7 @@ export default {
directives: {
GlTooltip: GlTooltipDirective,
},
- inject: ['fullPath', 'reportAbusePath'],
+ inject: ['fullPath', 'isGroup', 'reportAbusePath'],
props: {
issuableId: {
type: Number,
@@ -52,7 +53,9 @@ export default {
},
apollo: {
workItem: {
- query: workItemByIidQuery,
+ query() {
+ return this.isGroup ? groupWorkItemByIidQuery : workItemByIidQuery;
+ },
variables() {
return {
fullPath: this.fullPath,
@@ -171,7 +174,13 @@ export default {
},
handleWorkItemDeleted(child) {
const { defaultClient: cache } = this.$apollo.provider.clients;
- removeHierarchyChild(cache, this.fullPath, this.iid, child);
+ removeHierarchyChild({
+ cache,
+ fullPath: this.fullPath,
+ iid: this.iid,
+ isGroup: this.isGroup,
+ workItem: child,
+ });
this.$toast.show(s__('WorkItem|Task deleted'));
},
updateWorkItemIdUrlQuery({ iid } = {}) {
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 456dee8dab1..2e5ba42c2e1 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
@@ -37,7 +37,7 @@ export default {
GlTooltip,
WorkItemTokenInput,
},
- inject: ['fullPath', 'hasIterationsFeature'],
+ inject: ['fullPath', 'hasIterationsFeature', 'isGroup'],
props: {
issuableGid: {
type: String,
@@ -260,7 +260,13 @@ export default {
input: this.workItemInput,
},
update: (cache, { data }) =>
- addHierarchyChild(cache, this.fullPath, this.workItemIid, data.workItemCreate.workItem),
+ addHierarchyChild({
+ cache,
+ fullPath: this.fullPath,
+ iid: this.workItemIid,
+ isGroup: this.isGroup,
+ workItem: data.workItemCreate.workItem,
+ }),
})
.then(({ data }) => {
if (data.workItemCreate?.errors?.length) {
diff --git a/app/assets/javascripts/work_items/components/work_item_relationships/work_item_relationships.vue b/app/assets/javascripts/work_items/components/work_item_relationships/work_item_relationships.vue
index d32e3d3a5e5..6f02ea507e5 100644
--- a/app/assets/javascripts/work_items/components/work_item_relationships/work_item_relationships.vue
+++ b/app/assets/javascripts/work_items/components/work_item_relationships/work_item_relationships.vue
@@ -3,6 +3,7 @@ import { GlLoadingIcon, GlIcon, GlButton } from '@gitlab/ui';
import { s__ } from '~/locale';
+import groupWorkItemByIidQuery from '../../graphql/group_work_item_by_iid.query.graphql';
import workItemByIidQuery from '../../graphql/work_item_by_iid.query.graphql';
import { WIDGET_TYPE_LINKED_ITEMS, LINKED_CATEGORIES_MAP } from '../../constants';
@@ -19,6 +20,7 @@ export default {
WorkItemRelationshipList,
WorkItemAddRelationshipForm,
},
+ inject: ['isGroup'],
props: {
workItemId: {
type: String,
@@ -41,7 +43,9 @@ export default {
},
apollo: {
workItem: {
- query: workItemByIidQuery,
+ query() {
+ return this.isGroup ? groupWorkItemByIidQuery : workItemByIidQuery;
+ },
variables() {
return {
fullPath: this.workItemFullPath,
diff --git a/app/assets/javascripts/work_items/components/work_item_todos.vue b/app/assets/javascripts/work_items/components/work_item_todos.vue
index b21abf21be5..e6d7f2067ba 100644
--- a/app/assets/javascripts/work_items/components/work_item_todos.vue
+++ b/app/assets/javascripts/work_items/components/work_item_todos.vue
@@ -4,9 +4,10 @@ import { produce } from 'immer';
import { s__ } from '~/locale';
import { updateGlobalTodoCount } from '~/sidebar/utils';
-import workItemByIidQuery from '~/work_items/graphql/work_item_by_iid.query.graphql';
-import createWorkItemTodosMutation from '~/work_items/graphql/create_work_item_todos.mutation.graphql';
-import markDoneWorkItemTodosMutation from '~/work_items/graphql/mark_done_work_item_todos.mutation.graphql';
+import groupWorkItemByIidQuery from '../graphql/group_work_item_by_iid.query.graphql';
+import workItemByIidQuery from '../graphql/work_item_by_iid.query.graphql';
+import createWorkItemTodosMutation from '../graphql/create_work_item_todos.mutation.graphql';
+import markDoneWorkItemTodosMutation from '../graphql/mark_done_work_item_todos.mutation.graphql';
import {
TODO_ADD_ICON,
@@ -28,6 +29,7 @@ export default {
GlIcon,
GlButton,
},
+ inject: ['isGroup'],
props: {
workItemId: {
type: String,
@@ -148,7 +150,7 @@ export default {
},
updateWorkItemCurrentTodosWidgetCache({ cache, todos }) {
const query = {
- query: workItemByIidQuery,
+ query: this.isGroup ? groupWorkItemByIidQuery : workItemByIidQuery,
variables: { fullPath: this.workItemFullpath, iid: this.workItemIid },
};
diff --git a/app/assets/javascripts/work_items/components/work_item_type_icon.vue b/app/assets/javascripts/work_items/components/work_item_type_icon.vue
index 5426f3965b3..76a73093206 100644
--- a/app/assets/javascripts/work_items/components/work_item_type_icon.vue
+++ b/app/assets/javascripts/work_items/components/work_item_type_icon.vue
@@ -36,6 +36,11 @@ export default {
return this.workItemType.toUpperCase().split(' ').join('_');
},
iconName() {
+ // TODO Delete this conditional once we have an `issue-type-epic` icon
+ if (this.workItemIconName === 'issue-type-epic') {
+ return 'epic';
+ }
+
return (
this.workItemIconName ||
WORK_ITEMS_TYPE_MAP[this.workItemTypeUppercase]?.icon ||
diff --git a/app/assets/javascripts/work_items/graphql/cache_utils.js b/app/assets/javascripts/work_items/graphql/cache_utils.js
index 14eedf5cdd8..aeeffea24e7 100644
--- a/app/assets/javascripts/work_items/graphql/cache_utils.js
+++ b/app/assets/javascripts/work_items/graphql/cache_utils.js
@@ -1,5 +1,6 @@
import { produce } from 'immer';
import { WIDGET_TYPE_NOTES } from '~/work_items/constants';
+import groupWorkItemByIidQuery from '~/work_items/graphql/group_work_item_by_iid.query.graphql';
import workItemByIidQuery from '~/work_items/graphql/work_item_by_iid.query.graphql';
import { findHierarchyWidgetChildren } from '~/work_items/utils';
@@ -127,8 +128,11 @@ export const updateCacheAfterRemovingAwardEmojiFromNote = (currentNotes, note) =
});
};
-export const addHierarchyChild = (cache, fullPath, iid, workItem) => {
- const queryArgs = { query: workItemByIidQuery, variables: { fullPath, iid } };
+export const addHierarchyChild = ({ cache, fullPath, iid, isGroup, workItem }) => {
+ const queryArgs = {
+ query: isGroup ? groupWorkItemByIidQuery : workItemByIidQuery,
+ variables: { fullPath, iid },
+ };
const sourceData = cache.readQuery(queryArgs);
if (!sourceData) {
@@ -143,8 +147,11 @@ export const addHierarchyChild = (cache, fullPath, iid, workItem) => {
});
};
-export const removeHierarchyChild = (cache, fullPath, iid, workItem) => {
- const queryArgs = { query: workItemByIidQuery, variables: { fullPath, iid } };
+export const removeHierarchyChild = ({ cache, fullPath, iid, isGroup, workItem }) => {
+ const queryArgs = {
+ query: isGroup ? groupWorkItemByIidQuery : workItemByIidQuery,
+ variables: { fullPath, iid },
+ };
const sourceData = cache.readQuery(queryArgs);
if (!sourceData) {
diff --git a/app/assets/javascripts/work_items/graphql/group_work_item_by_iid.query.graphql b/app/assets/javascripts/work_items/graphql/group_work_item_by_iid.query.graphql
new file mode 100644
index 00000000000..f23bafa20c3
--- /dev/null
+++ b/app/assets/javascripts/work_items/graphql/group_work_item_by_iid.query.graphql
@@ -0,0 +1,12 @@
+#import "./work_item.fragment.graphql"
+
+query groupWorkItemByIid($fullPath: ID!, $iid: String) {
+ workspace: group(fullPath: $fullPath) @persist {
+ id
+ workItems(iid: $iid) {
+ nodes {
+ ...WorkItem
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/work_items/index.js b/app/assets/javascripts/work_items/index.js
index 70bda7d3783..0b7f9290d6e 100644
--- a/app/assets/javascripts/work_items/index.js
+++ b/app/assets/javascripts/work_items/index.js
@@ -1,17 +1,25 @@
import Vue from 'vue';
import VueApollo from 'vue-apollo';
+import { WORKSPACE_GROUP } from '~/issues/constants';
import { parseBoolean } from '~/lib/utils/common_utils';
import { apolloProvider } from '~/graphql_shared/issuable_client';
import App from './components/app.vue';
+import WorkItemRoot from './pages/work_item_root.vue';
import { createRouter } from './router';
Vue.use(VueApollo);
-export const initWorkItemsRoot = () => {
+export const initWorkItemsRoot = (workspace) => {
const el = document.querySelector('#js-work-items');
+
+ if (!el) {
+ return undefined;
+ }
+
const {
fullPath,
hasIssueWeightsFeature,
+ iid,
issuesListPath,
registerPath,
signInPath,
@@ -22,6 +30,8 @@ export const initWorkItemsRoot = () => {
reportAbusePath,
} = el.dataset;
+ const Component = workspace === WORKSPACE_GROUP ? WorkItemRoot : App;
+
return new Vue({
el,
name: 'WorkItemsRoot',
@@ -29,6 +39,7 @@ export const initWorkItemsRoot = () => {
apolloProvider,
provide: {
fullPath,
+ isGroup: workspace === WORKSPACE_GROUP,
hasIssueWeightsFeature: parseBoolean(hasIssueWeightsFeature),
hasOkrsFeature: parseBoolean(hasOkrsFeature),
issuesListPath,
@@ -40,7 +51,11 @@ export const initWorkItemsRoot = () => {
reportAbusePath,
},
render(createElement) {
- return createElement(App);
+ return createElement(Component, {
+ props: {
+ iid: workspace === WORKSPACE_GROUP ? iid : undefined,
+ },
+ });
},
});
};
diff --git a/app/assets/javascripts/work_items/pages/create_work_item.vue b/app/assets/javascripts/work_items/pages/create_work_item.vue
index b5705b21b5a..31e790254d9 100644
--- a/app/assets/javascripts/work_items/pages/create_work_item.vue
+++ b/app/assets/javascripts/work_items/pages/create_work_item.vue
@@ -10,6 +10,7 @@ import {
} from '../constants';
import createWorkItemMutation from '../graphql/create_work_item.mutation.graphql';
import projectWorkItemTypesQuery from '../graphql/project_work_item_types.query.graphql';
+import groupWorkItemByIidQuery from '../graphql/group_work_item_by_iid.query.graphql';
import workItemByIidQuery from '../graphql/work_item_by_iid.query.graphql';
import ItemTitle from '../components/item_title.vue';
@@ -22,7 +23,7 @@ export default {
ItemTitle,
GlFormSelect,
},
- inject: ['fullPath'],
+ inject: ['fullPath', 'isGroup'],
props: {
initialTitle: {
type: String,
@@ -94,7 +95,7 @@ export default {
const { workItem } = workItemCreate;
store.writeQuery({
- query: workItemByIidQuery,
+ query: this.isGroup ? groupWorkItemByIidQuery : workItemByIidQuery,
variables: {
fullPath: this.fullPath,
iid: workItem.iid,