diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-01-20 12:16:11 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-01-20 12:16:11 +0300 |
commit | edaa33dee2ff2f7ea3fac488d41558eb5f86d68c (patch) | |
tree | 11f143effbfeba52329fb7afbd05e6e2a3790241 /app/assets/javascripts/issues/show | |
parent | d8a5691316400a0f7ec4f83832698f1988eb27c1 (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.vue | 8 | ||||
-rw-r--r-- | app/assets/javascripts/issues/show/components/fields/type.vue | 10 | ||||
-rw-r--r-- | app/assets/javascripts/issues/show/components/header_actions.vue | 13 | ||||
-rw-r--r-- | app/assets/javascripts/issues/show/components/sentry_error_stack_trace.vue | 43 | ||||
-rw-r--r-- | app/assets/javascripts/issues/show/constants.js | 26 | ||||
-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.js | 86 |
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), - }); -} |