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>2021-12-09 21:14:48 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2021-12-09 21:14:48 +0300
commitf6115a0f2ce347bab74ff5951cf828196d715b66 (patch)
tree213cc1923cb8af7bc5a4f3e0c49cff3271544d6d /app/assets/javascripts/issues
parent750deb250143d48aba32fb437ba8838fbef3fde3 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets/javascripts/issues')
-rw-r--r--app/assets/javascripts/issues/related_merge_requests/components/related_merge_requests.vue120
-rw-r--r--app/assets/javascripts/issues/related_merge_requests/index.js24
-rw-r--r--app/assets/javascripts/issues/related_merge_requests/store/actions.js36
-rw-r--r--app/assets/javascripts/issues/related_merge_requests/store/index.js14
-rw-r--r--app/assets/javascripts/issues/related_merge_requests/store/mutation_types.js4
-rw-r--r--app/assets/javascripts/issues/related_merge_requests/store/mutations.js19
-rw-r--r--app/assets/javascripts/issues/related_merge_requests/store/state.js7
-rw-r--r--app/assets/javascripts/issues/sentry_error_stack_trace/components/sentry_error_stack_trace.vue43
-rw-r--r--app/assets/javascripts/issues/sentry_error_stack_trace/index.js22
-rw-r--r--app/assets/javascripts/issues/show.js4
10 files changed, 291 insertions, 2 deletions
diff --git a/app/assets/javascripts/issues/related_merge_requests/components/related_merge_requests.vue b/app/assets/javascripts/issues/related_merge_requests/components/related_merge_requests.vue
new file mode 100644
index 00000000000..e8d0d538362
--- /dev/null
+++ b/app/assets/javascripts/issues/related_merge_requests/components/related_merge_requests.vue
@@ -0,0 +1,120 @@
+<script>
+import { GlLink, GlLoadingIcon, GlIcon } from '@gitlab/ui';
+import { mapState, mapActions } from 'vuex';
+import { sprintf, __, n__ } from '~/locale';
+import RelatedIssuableItem from '~/vue_shared/components/issue/related_issuable_item.vue';
+import { parseIssuableData } from '~/issues/show/utils/parse_data';
+
+export default {
+ name: 'RelatedMergeRequests',
+ components: {
+ GlIcon,
+ GlLink,
+ GlLoadingIcon,
+ RelatedIssuableItem,
+ },
+ props: {
+ endpoint: {
+ type: String,
+ required: true,
+ },
+ projectNamespace: {
+ type: String,
+ required: true,
+ },
+ projectPath: {
+ type: String,
+ required: true,
+ },
+ },
+ computed: {
+ ...mapState(['isFetchingMergeRequests', 'mergeRequests', 'totalCount']),
+ closingMergeRequestsText() {
+ if (!this.hasClosingMergeRequest) {
+ return '';
+ }
+
+ const mrText = n__(
+ 'When this merge request is accepted',
+ 'When these merge requests are accepted',
+ this.totalCount,
+ );
+
+ return sprintf(__('%{mrText}, this issue will be closed automatically.'), { mrText });
+ },
+ },
+ mounted() {
+ this.setInitialState({ apiEndpoint: this.endpoint });
+ this.fetchMergeRequests();
+ },
+ created() {
+ this.hasClosingMergeRequest = parseIssuableData().hasClosingMergeRequest;
+ },
+ methods: {
+ ...mapActions(['setInitialState', 'fetchMergeRequests']),
+ getAssignees(mr) {
+ if (mr.assignees) {
+ return mr.assignees;
+ }
+
+ return mr.assignee ? [mr.assignee] : [];
+ },
+ },
+};
+</script>
+
+<template>
+ <div v-if="isFetchingMergeRequests || (!isFetchingMergeRequests && totalCount)">
+ <div class="card card-slim gl-mt-5">
+ <div class="card-header">
+ <div
+ class="card-title gl-relative gl-display-flex gl-align-items-center gl-line-height-20 gl-font-weight-bold gl-m-0"
+ >
+ <gl-link
+ class="anchor gl-absolute gl-text-decoration-none"
+ href="#related-merge-requests"
+ aria-labelledby="related-merge-requests"
+ />
+ <h3 id="related-merge-requests" class="gl-font-base gl-m-0">
+ {{ __('Related merge requests') }}
+ </h3>
+ <template v-if="totalCount">
+ <gl-icon name="merge-request" class="gl-ml-5 gl-mr-2 gl-text-gray-500" />
+ <span data-testid="count">{{ totalCount }}</span>
+ </template>
+ </div>
+ </div>
+ <gl-loading-icon
+ v-if="isFetchingMergeRequests"
+ size="sm"
+ label="Fetching related merge requests"
+ class="gl-py-3"
+ />
+ <ul v-else class="content-list related-items-list">
+ <li v-for="mr in mergeRequests" :key="mr.id" class="list-item gl-m-0! gl-p-0!">
+ <related-issuable-item
+ :id-key="mr.id"
+ :display-reference="mr.reference"
+ :title="mr.title"
+ :milestone="mr.milestone"
+ :assignees="getAssignees(mr)"
+ :created-at="mr.created_at"
+ :closed-at="mr.closed_at"
+ :merged-at="mr.merged_at"
+ :path="mr.web_url"
+ :state="mr.state"
+ :is-merge-request="true"
+ :pipeline-status="mr.head_pipeline && mr.head_pipeline.detailed_status"
+ path-id-separator="!"
+ />
+ </li>
+ </ul>
+ </div>
+ <div
+ v-if="hasClosingMergeRequest && !isFetchingMergeRequests"
+ class="issue-closed-by-widget second-block"
+ >
+ {{ closingMergeRequestsText }}
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/issues/related_merge_requests/index.js b/app/assets/javascripts/issues/related_merge_requests/index.js
new file mode 100644
index 00000000000..ce33cf7df1d
--- /dev/null
+++ b/app/assets/javascripts/issues/related_merge_requests/index.js
@@ -0,0 +1,24 @@
+import Vue from 'vue';
+import RelatedMergeRequests from './components/related_merge_requests.vue';
+import createStore from './store';
+
+export default function initRelatedMergeRequests() {
+ const relatedMergeRequestsElement = document.querySelector('#js-related-merge-requests');
+
+ if (relatedMergeRequestsElement) {
+ const { endpoint, projectPath, projectNamespace } = relatedMergeRequestsElement.dataset;
+
+ // eslint-disable-next-line no-new
+ new Vue({
+ el: relatedMergeRequestsElement,
+ components: {
+ RelatedMergeRequests,
+ },
+ store: createStore(),
+ render: (createElement) =>
+ createElement('related-merge-requests', {
+ props: { endpoint, projectNamespace, projectPath },
+ }),
+ });
+ }
+}
diff --git a/app/assets/javascripts/issues/related_merge_requests/store/actions.js b/app/assets/javascripts/issues/related_merge_requests/store/actions.js
new file mode 100644
index 00000000000..94abb50de89
--- /dev/null
+++ b/app/assets/javascripts/issues/related_merge_requests/store/actions.js
@@ -0,0 +1,36 @@
+import createFlash from '~/flash';
+import axios from '~/lib/utils/axios_utils';
+import { normalizeHeaders } from '~/lib/utils/common_utils';
+import { __ } from '~/locale';
+import * as types from './mutation_types';
+
+const REQUEST_PAGE_COUNT = 100;
+
+export const setInitialState = ({ commit }, props) => {
+ commit(types.SET_INITIAL_STATE, props);
+};
+
+export const requestData = ({ commit }) => commit(types.REQUEST_DATA);
+
+export const receiveDataSuccess = ({ commit }, data) => commit(types.RECEIVE_DATA_SUCCESS, data);
+
+export const receiveDataError = ({ commit }) => commit(types.RECEIVE_DATA_ERROR);
+
+export const fetchMergeRequests = ({ state, dispatch }) => {
+ dispatch('requestData');
+
+ return axios
+ .get(`${state.apiEndpoint}?per_page=${REQUEST_PAGE_COUNT}`)
+ .then((res) => {
+ const { headers, data } = res;
+ const total = Number(normalizeHeaders(headers)['X-TOTAL']) || 0;
+
+ dispatch('receiveDataSuccess', { data, total });
+ })
+ .catch(() => {
+ dispatch('receiveDataError');
+ createFlash({
+ message: __('Something went wrong while fetching related merge requests.'),
+ });
+ });
+};
diff --git a/app/assets/javascripts/issues/related_merge_requests/store/index.js b/app/assets/javascripts/issues/related_merge_requests/store/index.js
new file mode 100644
index 00000000000..925cc36cd76
--- /dev/null
+++ b/app/assets/javascripts/issues/related_merge_requests/store/index.js
@@ -0,0 +1,14 @@
+import Vue from 'vue';
+import Vuex from 'vuex';
+import * as actions from './actions';
+import mutations from './mutations';
+import createState from './state';
+
+Vue.use(Vuex);
+
+export default () =>
+ new Vuex.Store({
+ state: createState(),
+ actions,
+ mutations,
+ });
diff --git a/app/assets/javascripts/issues/related_merge_requests/store/mutation_types.js b/app/assets/javascripts/issues/related_merge_requests/store/mutation_types.js
new file mode 100644
index 00000000000..31d4fe032e1
--- /dev/null
+++ b/app/assets/javascripts/issues/related_merge_requests/store/mutation_types.js
@@ -0,0 +1,4 @@
+export const SET_INITIAL_STATE = 'SET_INITIAL_STATE';
+export const REQUEST_DATA = 'REQUEST_DATA';
+export const RECEIVE_DATA_SUCCESS = 'RECEIVE_DATA_SUCCESS';
+export const RECEIVE_DATA_ERROR = 'RECEIVE_DATA_ERROR';
diff --git a/app/assets/javascripts/issues/related_merge_requests/store/mutations.js b/app/assets/javascripts/issues/related_merge_requests/store/mutations.js
new file mode 100644
index 00000000000..11ca28a5fb9
--- /dev/null
+++ b/app/assets/javascripts/issues/related_merge_requests/store/mutations.js
@@ -0,0 +1,19 @@
+import * as types from './mutation_types';
+
+export default {
+ [types.SET_INITIAL_STATE](state, { apiEndpoint }) {
+ state.apiEndpoint = apiEndpoint;
+ },
+ [types.REQUEST_DATA](state) {
+ state.isFetchingMergeRequests = true;
+ },
+ [types.RECEIVE_DATA_SUCCESS](state, { data, total }) {
+ state.isFetchingMergeRequests = false;
+ state.mergeRequests = data;
+ state.totalCount = total;
+ },
+ [types.RECEIVE_DATA_ERROR](state) {
+ state.isFetchingMergeRequests = false;
+ state.hasErrorFetchingMergeRequests = true;
+ },
+};
diff --git a/app/assets/javascripts/issues/related_merge_requests/store/state.js b/app/assets/javascripts/issues/related_merge_requests/store/state.js
new file mode 100644
index 00000000000..bc3468a025b
--- /dev/null
+++ b/app/assets/javascripts/issues/related_merge_requests/store/state.js
@@ -0,0 +1,7 @@
+export default () => ({
+ apiEndpoint: '',
+ isFetchingMergeRequests: false,
+ hasErrorFetchingMergeRequests: false,
+ mergeRequests: [],
+ totalCount: 0,
+});
diff --git a/app/assets/javascripts/issues/sentry_error_stack_trace/components/sentry_error_stack_trace.vue b/app/assets/javascripts/issues/sentry_error_stack_trace/components/sentry_error_stack_trace.vue
new file mode 100644
index 00000000000..1530e9a15b5
--- /dev/null
+++ b/app/assets/javascripts/issues/sentry_error_stack_trace/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/sentry_error_stack_trace/index.js b/app/assets/javascripts/issues/sentry_error_stack_trace/index.js
new file mode 100644
index 00000000000..8e9ee25e7a8
--- /dev/null
+++ b/app/assets/javascripts/issues/sentry_error_stack_trace/index.js
@@ -0,0 +1,22 @@
+import Vue from 'vue';
+import store from '~/error_tracking/store';
+import SentryErrorStackTrace from './components/sentry_error_stack_trace.vue';
+
+export default function initSentryErrorStacktrace() {
+ const sentryErrorStackTraceEl = document.querySelector('#js-sentry-error-stack-trace');
+ if (sentryErrorStackTraceEl) {
+ const { issueStackTracePath } = sentryErrorStackTraceEl.dataset;
+ // eslint-disable-next-line no-new
+ new Vue({
+ el: sentryErrorStackTraceEl,
+ components: {
+ SentryErrorStackTrace,
+ },
+ store,
+ render: (createElement) =>
+ createElement('sentry-error-stack-trace', {
+ props: { issueStackTracePath },
+ }),
+ });
+ }
+}
diff --git a/app/assets/javascripts/issues/show.js b/app/assets/javascripts/issues/show.js
index 33b1c47b4fe..0c02d137f29 100644
--- a/app/assets/javascripts/issues/show.js
+++ b/app/assets/javascripts/issues/show.js
@@ -8,8 +8,8 @@ import { initIssuableApp, initIssueHeaderActions } from '~/issues/show/issue';
import { parseIssuableData } from '~/issues/show/utils/parse_data';
import initNotesApp from '~/notes';
import { store } from '~/notes/stores';
-import initRelatedMergeRequestsApp from '~/related_merge_requests';
-import initSentryErrorStackTraceApp from '~/sentry_error_stack_trace';
+import initRelatedMergeRequestsApp from '~/issues/related_merge_requests';
+import initSentryErrorStackTraceApp from '~/issues/sentry_error_stack_trace';
import initIssuableHeaderWarning from '~/issuable/init_issuable_header_warning';
import ZenMode from '~/zen_mode';