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:
Diffstat (limited to 'app/assets/javascripts/issue_show/components/app.vue')
-rw-r--r--app/assets/javascripts/issue_show/components/app.vue79
1 files changed, 74 insertions, 5 deletions
diff --git a/app/assets/javascripts/issue_show/components/app.vue b/app/assets/javascripts/issue_show/components/app.vue
index 8cf2cda64a4..09acfd1cfae 100644
--- a/app/assets/javascripts/issue_show/components/app.vue
+++ b/app/assets/javascripts/issue_show/components/app.vue
@@ -1,9 +1,10 @@
<script>
+import { GlIcon, GlIntersectionObserver } from '@gitlab/ui';
import Visibility from 'visibilityjs';
import { __, s__, sprintf } from '~/locale';
import createFlash from '~/flash';
-import { visitUrl } from '../../lib/utils/url_utility';
-import Poll from '../../lib/utils/poll';
+import { visitUrl } from '~/lib/utils/url_utility';
+import Poll from '~/lib/utils/poll';
import eventHub from '../event_hub';
import Service from '../services/index';
import Store from '../stores';
@@ -12,10 +13,13 @@ import descriptionComponent from './description.vue';
import editedComponent from './edited.vue';
import formComponent from './form.vue';
import PinnedLinks from './pinned_links.vue';
-import recaptchaModalImplementor from '../../vue_shared/mixins/recaptcha_modal_implementor';
+import recaptchaModalImplementor from '~/vue_shared/mixins/recaptcha_modal_implementor';
+import { IssuableStatus, IssuableStatusText, IssuableType } from '../constants';
export default {
components: {
+ GlIcon,
+ GlIntersectionObserver,
descriptionComponent,
titleComponent,
editedComponent,
@@ -58,12 +62,22 @@ export default {
zoomMeetingUrl: {
type: String,
required: false,
- default: null,
+ default: '',
+ },
+ publishedIncidentUrl: {
+ type: String,
+ required: false,
+ default: '',
},
issuableRef: {
type: String,
required: true,
},
+ issuableStatus: {
+ type: String,
+ required: false,
+ default: '',
+ },
initialTitleHtml: {
type: String,
required: true,
@@ -157,6 +171,7 @@ export default {
state: store.state,
showForm: false,
templatesRequested: false,
+ isStickyHeaderShowing: false,
};
},
computed: {
@@ -191,6 +206,18 @@ export default {
defaultErrorMessage() {
return sprintf(s__('Error updating %{issuableType}'), { issuableType: this.issuableType });
},
+ isOpenStatus() {
+ return this.issuableStatus === IssuableStatus.Open;
+ },
+ statusIcon() {
+ return this.isOpenStatus ? 'issue-open-m' : 'mobile-issue-close';
+ },
+ statusText() {
+ return IssuableStatusText[this.issuableStatus];
+ },
+ shouldShowStickyHeader() {
+ return this.isStickyHeaderShowing && this.issuableType === IssuableType.Issue;
+ },
},
created() {
this.service = new Service(this.endpoint);
@@ -344,6 +371,14 @@ export default {
);
});
},
+
+ hideStickyHeader() {
+ this.isStickyHeaderShowing = false;
+ },
+
+ showStickyHeader() {
+ this.isStickyHeaderShowing = true;
+ },
},
};
</script>
@@ -380,7 +415,40 @@ export default {
:title-text="state.titleText"
:show-inline-edit-button="showInlineEditButton"
/>
- <pinned-links :zoom-meeting-url="zoomMeetingUrl" />
+
+ <gl-intersection-observer @appear="hideStickyHeader" @disappear="showStickyHeader">
+ <transition name="issuable-header-slide">
+ <div
+ v-if="shouldShowStickyHeader"
+ class="issue-sticky-header gl-fixed gl-z-index-2 gl-bg-white gl-border-1 gl-border-b-solid gl-border-b-gray-200 gl-py-3"
+ data-testid="issue-sticky-header"
+ >
+ <div
+ class="issue-sticky-header-text gl-display-flex gl-align-items-center gl-mx-auto gl-px-5"
+ >
+ <p
+ class="issuable-status-box status-box gl-my-0"
+ :class="[isOpenStatus ? 'status-box-open' : 'status-box-issue-closed']"
+ >
+ <gl-icon :name="statusIcon" class="gl-display-block d-sm-none gl-h-6!" />
+ <span class="gl-display-none d-sm-block">{{ statusText }}</span>
+ </p>
+ <p
+ class="gl-font-weight-bold gl-overflow-hidden gl-white-space-nowrap gl-text-overflow-ellipsis gl-my-0"
+ :title="state.titleText"
+ >
+ {{ state.titleText }}
+ </p>
+ </div>
+ </div>
+ </transition>
+ </gl-intersection-observer>
+
+ <pinned-links
+ :zoom-meeting-url="zoomMeetingUrl"
+ :published-incident-url="publishedIncidentUrl"
+ />
+
<description-component
v-if="state.descriptionHtml"
:can-update="canUpdate"
@@ -393,6 +461,7 @@ export default {
:lock-version="state.lock_version"
@taskListUpdateFailed="updateStoreState"
/>
+
<edited-component
v-if="hasUpdated"
:updated-at="state.updatedAt"