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>2022-01-20 12:16:11 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2022-01-20 12:16:11 +0300
commitedaa33dee2ff2f7ea3fac488d41558eb5f86d68c (patch)
tree11f143effbfeba52329fb7afbd05e6e2a3790241 /app/assets/javascripts/issues/show
parentd8a5691316400a0f7ec4f83832698f1988eb27c1 (diff)
Add latest changes from gitlab-org/gitlab@14-7-stable-eev14.7.0-rc42
Diffstat (limited to 'app/assets/javascripts/issues/show')
-rw-r--r--app/assets/javascripts/issues/show/components/app.vue8
-rw-r--r--app/assets/javascripts/issues/show/components/fields/type.vue10
-rw-r--r--app/assets/javascripts/issues/show/components/header_actions.vue13
-rw-r--r--app/assets/javascripts/issues/show/components/sentry_error_stack_trace.vue43
-rw-r--r--app/assets/javascripts/issues/show/constants.js26
-rw-r--r--app/assets/javascripts/issues/show/index.js (renamed from app/assets/javascripts/issues/show/incident.js)90
-rw-r--r--app/assets/javascripts/issues/show/issue.js86
7 files changed, 145 insertions, 131 deletions
diff --git a/app/assets/javascripts/issues/show/components/app.vue b/app/assets/javascripts/issues/show/components/app.vue
index eeaf865a35f..0490728c6bc 100644
--- a/app/assets/javascripts/issues/show/components/app.vue
+++ b/app/assets/javascripts/issues/show/components/app.vue
@@ -6,7 +6,7 @@ import { IssuableStatus, IssuableStatusText, IssuableType } from '~/issues/const
import Poll from '~/lib/utils/poll';
import { visitUrl } from '~/lib/utils/url_utility';
import { __, sprintf } from '~/locale';
-import { IssueTypePath, IncidentTypePath, IncidentType, POLLING_DELAY } from '../constants';
+import { ISSUE_TYPE_PATH, INCIDENT_TYPE_PATH, INCIDENT_TYPE, POLLING_DELAY } from '../constants';
import eventHub from '../event_hub';
import getIssueStateQuery from '../queries/get_issue_state.query.graphql';
import Service from '../services/index';
@@ -378,15 +378,15 @@ export default {
.then((data) => {
if (
!window.location.pathname.includes(data.web_url) &&
- issueState.issueType !== IncidentType
+ issueState.issueType !== INCIDENT_TYPE
) {
visitUrl(data.web_url);
}
if (issueState.isDirty) {
const URI =
- issueState.issueType === IncidentType
- ? data.web_url.replace(IssueTypePath, IncidentTypePath)
+ issueState.issueType === INCIDENT_TYPE
+ ? data.web_url.replace(ISSUE_TYPE_PATH, INCIDENT_TYPE_PATH)
: data.web_url;
visitUrl(URI);
}
diff --git a/app/assets/javascripts/issues/show/components/fields/type.vue b/app/assets/javascripts/issues/show/components/fields/type.vue
index 9110a6924b4..75d0b9e5e76 100644
--- a/app/assets/javascripts/issues/show/components/fields/type.vue
+++ b/app/assets/javascripts/issues/show/components/fields/type.vue
@@ -2,7 +2,7 @@
import { GlFormGroup, GlDropdown, GlDropdownItem, GlIcon } from '@gitlab/ui';
import { capitalize } from 'lodash';
import { __ } from '~/locale';
-import { IssuableTypes, IncidentType } from '../../constants';
+import { issuableTypes, INCIDENT_TYPE } from '../../constants';
import getIssueStateQuery from '../../queries/get_issue_state.query.graphql';
import updateIssueStateMutation from '../../queries/update_issue_state.mutation.graphql';
@@ -12,7 +12,7 @@ export const i18n = {
export default {
i18n,
- IssuableTypes,
+ issuableTypes,
components: {
GlFormGroup,
GlIcon,
@@ -45,7 +45,7 @@ export default {
return capitalize(issueType);
},
shouldShowIncident() {
- return this.issueType === IncidentType || this.canCreateIncident;
+ return this.issueType === INCIDENT_TYPE || this.canCreateIncident;
},
},
methods: {
@@ -59,7 +59,7 @@ export default {
});
},
isShown(type) {
- return type.value !== IncidentType || this.shouldShowIncident;
+ return type.value !== INCIDENT_TYPE || this.shouldShowIncident;
},
},
};
@@ -81,7 +81,7 @@ export default {
toggle-class="dropdown-menu-toggle"
>
<gl-dropdown-item
- v-for="type in $options.IssuableTypes"
+ v-for="type in $options.issuableTypes"
v-show="isShown(type)"
:key="type.value"
:is-checked="issueState.issueType === type.value"
diff --git a/app/assets/javascripts/issues/show/components/header_actions.vue b/app/assets/javascripts/issues/show/components/header_actions.vue
index 700ef92a0f3..8ba08472ea0 100644
--- a/app/assets/javascripts/issues/show/components/header_actions.vue
+++ b/app/assets/javascripts/issues/show/components/header_actions.vue
@@ -11,9 +11,8 @@ import {
import { mapActions, mapGetters, mapState } from 'vuex';
import createFlash, { FLASH_TYPES } from '~/flash';
import { EVENT_ISSUABLE_VUE_APP_CHANGE } from '~/issuable/constants';
-import { IssuableType } from '~/vue_shared/issuable/show/constants';
-import { IssuableStatus } from '~/issues/constants';
-import { IssueStateEvent } from '~/issues/show/constants';
+import { IssuableStatus, IssueType } from '~/issues/constants';
+import { ISSUE_STATE_EVENT_CLOSE, ISSUE_STATE_EVENT_REOPEN } from '~/issues/show/constants';
import { capitalizeFirstCharacter } from '~/lib/utils/text_utility';
import { visitUrl } from '~/lib/utils/url_utility';
import { s__, __, sprintf } from '~/locale';
@@ -83,7 +82,7 @@ export default {
default: '',
},
issueType: {
- default: IssuableType.Issue,
+ default: IssueType.Issue,
},
newIssuePath: {
default: '',
@@ -106,8 +105,8 @@ export default {
},
issueTypeText() {
const issueTypeTexts = {
- [IssuableType.Issue]: s__('HeaderAction|issue'),
- [IssuableType.Incident]: s__('HeaderAction|incident'),
+ [IssueType.Issue]: s__('HeaderAction|issue'),
+ [IssueType.Incident]: s__('HeaderAction|incident'),
};
return issueTypeTexts[this.issueType] ?? this.issueType;
@@ -163,7 +162,7 @@ export default {
input: {
iid: this.iid.toString(),
projectPath: this.projectPath,
- stateEvent: this.isClosed ? IssueStateEvent.Reopen : IssueStateEvent.Close,
+ stateEvent: this.isClosed ? ISSUE_STATE_EVENT_REOPEN : ISSUE_STATE_EVENT_CLOSE,
},
},
})
diff --git a/app/assets/javascripts/issues/show/components/sentry_error_stack_trace.vue b/app/assets/javascripts/issues/show/components/sentry_error_stack_trace.vue
new file mode 100644
index 00000000000..1530e9a15b5
--- /dev/null
+++ b/app/assets/javascripts/issues/show/components/sentry_error_stack_trace.vue
@@ -0,0 +1,43 @@
+<script>
+import { GlLoadingIcon } from '@gitlab/ui';
+import { mapActions, mapState, mapGetters } from 'vuex';
+import Stacktrace from '~/error_tracking/components/stacktrace.vue';
+
+export default {
+ name: 'SentryErrorStackTrace',
+ components: {
+ Stacktrace,
+ GlLoadingIcon,
+ },
+ props: {
+ issueStackTracePath: {
+ type: String,
+ required: true,
+ },
+ },
+ computed: {
+ ...mapState('details', ['loadingStacktrace', 'stacktraceData']),
+ ...mapGetters('details', ['stacktrace']),
+ },
+ mounted() {
+ this.startPollingStacktrace(this.issueStackTracePath);
+ },
+ methods: {
+ ...mapActions('details', ['startPollingStacktrace']),
+ },
+};
+</script>
+
+<template>
+ <div>
+ <div :class="{ 'border-bottom-0': loadingStacktrace }" class="card card-slim mt-4 mb-0">
+ <div class="card-header border-bottom-0">
+ <h5 class="card-title my-1">{{ __('Stack trace') }}</h5>
+ </div>
+ </div>
+ <div v-if="loadingStacktrace" class="card">
+ <gl-loading-icon class="py-2" label="Fetching stack trace" size="sm" />
+ </div>
+ <stacktrace v-else :entries="stacktrace" />
+ </div>
+</template>
diff --git a/app/assets/javascripts/issues/show/constants.js b/app/assets/javascripts/issues/show/constants.js
index 35f3bcdad70..a100aaf88ad 100644
--- a/app/assets/javascripts/issues/show/constants.js
+++ b/app/assets/javascripts/issues/show/constants.js
@@ -1,22 +1,20 @@
import { __ } from '~/locale';
-export const IssueStateEvent = {
- Close: 'CLOSE',
- Reopen: 'REOPEN',
-};
-
-export const STATUS_PAGE_PUBLISHED = __('Published on status page');
+export const INCIDENT_TYPE = 'incident';
+export const INCIDENT_TYPE_PATH = 'issues/incident';
+export const ISSUE_STATE_EVENT_CLOSE = 'CLOSE';
+export const ISSUE_STATE_EVENT_REOPEN = 'REOPEN';
+export const ISSUE_TYPE_PATH = 'issues';
export const JOIN_ZOOM_MEETING = __('Join Zoom meeting');
+export const POLLING_DELAY = 2000;
+export const STATUS_PAGE_PUBLISHED = __('Published on status page');
-export const IssuableTypes = [
+export const issuableTypes = [
{ value: 'issue', text: __('Issue'), icon: 'issue-type-issue' },
{ value: 'incident', text: __('Incident'), icon: 'issue-type-incident' },
];
-export const IssueTypePath = 'issues';
-export const IncidentTypePath = 'issues/incident';
-export const IncidentType = 'incident';
-
-export const issueState = { issueType: undefined, isDirty: false };
-
-export const POLLING_DELAY = 2000;
+export const issueState = {
+ issueType: undefined,
+ isDirty: false,
+};
diff --git a/app/assets/javascripts/issues/show/incident.js b/app/assets/javascripts/issues/show/index.js
index a260c31e1da..7f5a0e32f72 100644
--- a/app/assets/javascripts/issues/show/incident.js
+++ b/app/assets/javascripts/issues/show/index.js
@@ -1,11 +1,15 @@
import Vue from 'vue';
+import { mapGetters } from 'vuex';
+import errorTrackingStore from '~/error_tracking/store';
import { parseBoolean } from '~/lib/utils/common_utils';
-import issuableApp from './components/app.vue';
-import incidentTabs from './components/incidents/incident_tabs.vue';
-import { issueState, IncidentType } from './constants';
+import { scrollToTargetOnResize } from '~/lib/utils/resize_observer';
+import IssueApp from './components/app.vue';
+import HeaderActions from './components/header_actions.vue';
+import IncidentTabs from './components/incidents/incident_tabs.vue';
+import SentryErrorStackTrace from './components/sentry_error_stack_trace.vue';
+import { INCIDENT_TYPE, issueState } from './constants';
import apolloProvider from './graphql';
import getIssueStateQuery from './queries/get_issue_state.query.graphql';
-import HeaderActions from './components/header_actions.vue';
const bootstrapApollo = (state = {}) => {
return apolloProvider.clients.defaultClient.cache.writeQuery({
@@ -16,7 +20,7 @@ const bootstrapApollo = (state = {}) => {
});
};
-export function initIncidentApp(issuableData = {}) {
+export function initIncidentApp(issueData = {}) {
const el = document.getElementById('js-issuable-app');
if (!el) {
@@ -34,18 +38,15 @@ export function initIncidentApp(issuableData = {}) {
projectId,
slaFeatureAvailable,
uploadMetricsFeatureAvailable,
- } = issuableData;
+ } = issueData;
const fullPath = `${projectNamespace}/${projectPath}`;
return new Vue({
el,
apolloProvider,
- components: {
- issuableApp,
- },
provide: {
- issueType: IncidentType,
+ issueType: INCIDENT_TYPE,
canCreateIncident,
canUpdate,
fullPath,
@@ -55,10 +56,10 @@ export function initIncidentApp(issuableData = {}) {
uploadMetricsFeatureAvailable: parseBoolean(uploadMetricsFeatureAvailable),
},
render(createElement) {
- return createElement('issuable-app', {
+ return createElement(IssueApp, {
props: {
- ...issuableData,
- descriptionComponent: incidentTabs,
+ ...issueData,
+ descriptionComponent: IncidentTabs,
showTitleBorder: false,
},
});
@@ -66,7 +67,46 @@ export function initIncidentApp(issuableData = {}) {
});
}
-export function initIncidentHeaderActions(store) {
+export function initIssueApp(issueData, store) {
+ const el = document.getElementById('js-issuable-app');
+
+ if (!el) {
+ return undefined;
+ }
+
+ if (gon?.features?.fixCommentScroll) {
+ scrollToTargetOnResize();
+ }
+
+ bootstrapApollo({ ...issueState, issueType: el.dataset.issueType });
+
+ const { canCreateIncident, ...issueProps } = issueData;
+
+ return new Vue({
+ el,
+ apolloProvider,
+ store,
+ provide: {
+ canCreateIncident,
+ },
+ computed: {
+ ...mapGetters(['getNoteableData']),
+ },
+ render(createElement) {
+ return createElement(IssueApp, {
+ props: {
+ ...issueProps,
+ isConfidential: this.getNoteableData?.confidential,
+ isLocked: this.getNoteableData?.discussion_locked,
+ issuableStatus: this.getNoteableData?.state,
+ id: this.getNoteableData?.id,
+ },
+ });
+ },
+ });
+}
+
+export function initHeaderActions(store, type = '') {
const el = document.querySelector('.js-issue-header-actions');
if (!el) {
@@ -75,12 +115,15 @@ export function initIncidentHeaderActions(store) {
bootstrapApollo({ ...issueState, issueType: el.dataset.issueType });
+ const canCreate =
+ type === INCIDENT_TYPE ? el.dataset.canCreateIncident : el.dataset.canCreateIssue;
+
return new Vue({
el,
apolloProvider,
store,
provide: {
- canCreateIssue: parseBoolean(el.dataset.canCreateIncident),
+ canCreateIssue: parseBoolean(canCreate),
canDestroyIssue: parseBoolean(el.dataset.canDestroyIssue),
canPromoteToEpic: parseBoolean(el.dataset.canPromoteToEpic),
canReopenIssue: parseBoolean(el.dataset.canReopenIssue),
@@ -99,3 +142,20 @@ export function initIncidentHeaderActions(store) {
render: (createElement) => createElement(HeaderActions),
});
}
+
+export function initSentryErrorStackTrace() {
+ const el = document.querySelector('#js-sentry-error-stack-trace');
+
+ if (!el) {
+ return undefined;
+ }
+
+ const { issueStackTracePath } = el.dataset;
+
+ return new Vue({
+ el,
+ store: errorTrackingStore,
+ render: (createElement) =>
+ createElement(SentryErrorStackTrace, { props: { issueStackTracePath } }),
+ });
+}
diff --git a/app/assets/javascripts/issues/show/issue.js b/app/assets/javascripts/issues/show/issue.js
deleted file mode 100644
index 60e90934af8..00000000000
--- a/app/assets/javascripts/issues/show/issue.js
+++ /dev/null
@@ -1,86 +0,0 @@
-import Vue from 'vue';
-import { mapGetters } from 'vuex';
-import { parseBoolean } from '~/lib/utils/common_utils';
-import IssuableApp from './components/app.vue';
-import HeaderActions from './components/header_actions.vue';
-import { issueState } from './constants';
-import apolloProvider from './graphql';
-import getIssueStateQuery from './queries/get_issue_state.query.graphql';
-
-const bootstrapApollo = (state = {}) => {
- return apolloProvider.clients.defaultClient.cache.writeQuery({
- query: getIssueStateQuery,
- data: {
- issueState: state,
- },
- });
-};
-
-export function initIssuableApp(issuableData, store) {
- const el = document.getElementById('js-issuable-app');
-
- if (!el) {
- return undefined;
- }
-
- bootstrapApollo({ ...issueState, issueType: el.dataset.issueType });
-
- const { canCreateIncident, ...issuableProps } = issuableData;
-
- return new Vue({
- el,
- apolloProvider,
- store,
- provide: {
- canCreateIncident,
- },
- computed: {
- ...mapGetters(['getNoteableData']),
- },
- render(createElement) {
- return createElement(IssuableApp, {
- props: {
- ...issuableProps,
- isConfidential: this.getNoteableData?.confidential,
- isLocked: this.getNoteableData?.discussion_locked,
- issuableStatus: this.getNoteableData?.state,
- id: this.getNoteableData?.id,
- },
- });
- },
- });
-}
-
-export function initIssueHeaderActions(store) {
- const el = document.querySelector('.js-issue-header-actions');
-
- if (!el) {
- return undefined;
- }
-
- bootstrapApollo({ ...issueState, issueType: el.dataset.issueType });
-
- return new Vue({
- el,
- apolloProvider,
- store,
- provide: {
- canCreateIssue: parseBoolean(el.dataset.canCreateIssue),
- canDestroyIssue: parseBoolean(el.dataset.canDestroyIssue),
- canPromoteToEpic: parseBoolean(el.dataset.canPromoteToEpic),
- canReopenIssue: parseBoolean(el.dataset.canReopenIssue),
- canReportSpam: parseBoolean(el.dataset.canReportSpam),
- canUpdateIssue: parseBoolean(el.dataset.canUpdateIssue),
- iid: el.dataset.iid,
- isIssueAuthor: parseBoolean(el.dataset.isIssueAuthor),
- issuePath: el.dataset.issuePath,
- issueType: el.dataset.issueType,
- newIssuePath: el.dataset.newIssuePath,
- projectPath: el.dataset.projectPath,
- projectId: el.dataset.projectId,
- reportAbusePath: el.dataset.reportAbusePath,
- submitAsSpamPath: el.dataset.submitAsSpamPath,
- },
- render: (createElement) => createElement(HeaderActions),
- });
-}