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')
-rw-r--r--app/assets/javascripts/issue_show/components/app.vue25
-rw-r--r--app/assets/javascripts/issue_show/components/description.vue19
-rw-r--r--app/assets/javascripts/issue_show/components/edit_actions.vue35
-rw-r--r--app/assets/javascripts/issue_show/components/fields/description_template.vue21
-rw-r--r--app/assets/javascripts/issue_show/components/incidents/graphql/queries/get_alert.graphql20
-rw-r--r--app/assets/javascripts/issue_show/components/incidents/highlight_bar.vue42
-rw-r--r--app/assets/javascripts/issue_show/components/incidents/incident_tabs.vue71
-rw-r--r--app/assets/javascripts/issue_show/components/locked_warning.vue1
-rw-r--r--app/assets/javascripts/issue_show/components/pinned_links.vue19
-rw-r--r--app/assets/javascripts/issue_show/components/title.vue30
10 files changed, 226 insertions, 57 deletions
diff --git a/app/assets/javascripts/issue_show/components/app.vue b/app/assets/javascripts/issue_show/components/app.vue
index 992d87a969f..22db0f1cfc1 100644
--- a/app/assets/javascripts/issue_show/components/app.vue
+++ b/app/assets/javascripts/issue_show/components/app.vue
@@ -20,7 +20,6 @@ export default {
components: {
GlIcon,
GlIntersectionObserver,
- descriptionComponent,
titleComponent,
editedComponent,
formComponent,
@@ -152,6 +151,18 @@ export default {
required: false,
default: 0,
},
+ descriptionComponent: {
+ type: Object,
+ required: false,
+ default: () => {
+ return descriptionComponent;
+ },
+ },
+ showTitleBorder: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
},
data() {
const store = new Store({
@@ -209,6 +220,11 @@ export default {
isOpenStatus() {
return this.issuableStatus === IssuableStatus.Open;
},
+ pinnedLinkClasses() {
+ return this.showTitleBorder
+ ? 'gl-border-b-1 gl-border-b-gray-100 gl-border-b-solid gl-mb-6'
+ : '';
+ },
statusIcon() {
return this.isOpenStatus ? 'issue-open-m' : 'mobile-issue-close';
},
@@ -231,7 +247,7 @@ export default {
});
if (!Visibility.hidden()) {
- this.poll.makeRequest();
+ this.poll.makeDelayedRequest(2000);
}
Visibility.change(() => {
@@ -447,10 +463,11 @@ export default {
<pinned-links
:zoom-meeting-url="zoomMeetingUrl"
:published-incident-url="publishedIncidentUrl"
+ :class="pinnedLinkClasses"
/>
- <description-component
- v-if="state.descriptionHtml"
+ <component
+ :is="descriptionComponent"
:can-update="canUpdate"
:description-html="state.descriptionHtml"
:description-text="state.descriptionText"
diff --git a/app/assets/javascripts/issue_show/components/description.vue b/app/assets/javascripts/issue_show/components/description.vue
index abb63f606ae..2a6468c783b 100644
--- a/app/assets/javascripts/issue_show/components/description.vue
+++ b/app/assets/javascripts/issue_show/components/description.vue
@@ -1,5 +1,6 @@
<script>
import $ from 'jquery';
+import { GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
import { s__, sprintf } from '~/locale';
import { deprecatedCreateFlash as createFlash } from '~/flash';
import animateMixin from '../mixins/animate';
@@ -7,6 +8,10 @@ import TaskList from '../../task_list';
import recaptchaModalImplementor from '../../vue_shared/mixins/recaptcha_modal_implementor';
export default {
+ directives: {
+ SafeHtml,
+ },
+
mixins: [animateMixin, recaptchaModalImplementor],
props: {
@@ -20,7 +25,8 @@ export default {
},
descriptionText: {
type: String,
- required: true,
+ required: false,
+ default: '',
},
taskStatus: {
type: String,
@@ -47,11 +53,16 @@ export default {
return {
preAnimation: false,
pulseAnimation: false,
+ initialUpdate: true,
};
},
watch: {
- descriptionHtml() {
- this.animateChange();
+ descriptionHtml(newDescription, oldDescription) {
+ if (!this.initialUpdate && newDescription !== oldDescription) {
+ this.animateChange();
+ } else {
+ this.initialUpdate = false;
+ }
this.$nextTick(() => {
this.renderGFM();
@@ -136,12 +147,12 @@ export default {
>
<div
ref="gfm-content"
+ v-safe-html="descriptionHtml"
:class="{
'issue-realtime-pre-pulse': preAnimation,
'issue-realtime-trigger-pulse': pulseAnimation,
}"
class="md"
- v-html="descriptionHtml"
></div>
<textarea
v-if="descriptionText"
diff --git a/app/assets/javascripts/issue_show/components/edit_actions.vue b/app/assets/javascripts/issue_show/components/edit_actions.vue
index 4ee44e50d2f..14ada5adcf6 100644
--- a/app/assets/javascripts/issue_show/components/edit_actions.vue
+++ b/app/assets/javascripts/issue_show/components/edit_actions.vue
@@ -1,5 +1,5 @@
<script>
-/* eslint-disable @gitlab/vue-require-i18n-strings */
+import { GlButton } from '@gitlab/ui';
import { __, sprintf } from '~/locale';
import updateMixin from '../mixins/update';
import eventHub from '../event_hub';
@@ -10,6 +10,9 @@ const issuableTypes = {
};
export default {
+ components: {
+ GlButton,
+ },
mixins: [updateMixin],
props: {
canDestroy: {
@@ -64,28 +67,30 @@ export default {
<template>
<div class="gl-mt-3 gl-mb-3 clearfix">
- <button
- :class="{ disabled: formState.updateLoading || !isSubmitEnabled }"
+ <gl-button
+ :loading="formState.updateLoading"
:disabled="formState.updateLoading || !isSubmitEnabled"
- class="btn btn-success float-left qa-save-button"
+ category="primary"
+ variant="success"
+ class="float-left qa-save-button"
type="submit"
@click.prevent="updateIssuable"
>
- Save changes
- <i v-if="formState.updateLoading" class="fa fa-spinner fa-spin" aria-hidden="true"> </i>
- </button>
- <button class="btn btn-default float-right" type="button" @click="closeForm">
+ {{ __('Save changes') }}
+ </gl-button>
+ <gl-button class="float-right" @click="closeForm">
{{ __('Cancel') }}
- </button>
- <button
+ </gl-button>
+ <gl-button
v-if="shouldShowDeleteButton"
- :class="{ disabled: deleteLoading }"
+ :loading="deleteLoading"
:disabled="deleteLoading"
- class="btn btn-danger float-right gl-mr-3 qa-delete-button"
- type="button"
+ category="primary"
+ variant="danger"
+ class="float-right gl-mr-3 qa-delete-button"
@click="deleteIssuable"
>
- Delete <i v-if="deleteLoading" class="fa fa-spinner fa-spin" aria-hidden="true"> </i>
- </button>
+ {{ __('Delete') }}
+ </gl-button>
</div>
</template>
diff --git a/app/assets/javascripts/issue_show/components/fields/description_template.vue b/app/assets/javascripts/issue_show/components/fields/description_template.vue
index 6d8a9950b6d..e1b308c6f57 100644
--- a/app/assets/javascripts/issue_show/components/fields/description_template.vue
+++ b/app/assets/javascripts/issue_show/components/fields/description_template.vue
@@ -1,9 +1,13 @@
<script>
/* eslint-disable @gitlab/vue-require-i18n-strings */
import $ from 'jquery';
+import { GlIcon } from '@gitlab/ui';
import IssuableTemplateSelectors from '../../../templates/issuable_template_selectors';
export default {
+ components: {
+ GlIcon,
+ },
props: {
formState: {
type: Object,
@@ -61,14 +65,14 @@ export default {
<i aria-hidden="true" class="fa fa-chevron-down"> </i>
</button>
<div class="dropdown-menu dropdown-select">
- <div class="dropdown-title">
- Choose a template
+ <div class="dropdown-title gl-display-flex gl-justify-content-center">
+ <span class="gl-ml-auto">Choose a template</span>
<button
- class="dropdown-title-button dropdown-menu-close"
+ class="dropdown-title-button dropdown-menu-close gl-ml-auto"
:aria-label="__('Close')"
type="button"
>
- <i aria-hidden="true" class="fa fa-times dropdown-menu-close-icon"> </i>
+ <gl-icon name="close" class="dropdown-menu-close-icon" :aria-hidden="true" />
</button>
</div>
<div class="dropdown-input">
@@ -79,12 +83,11 @@ export default {
autocomplete="off"
/>
<i aria-hidden="true" class="fa fa-search dropdown-input-search"> </i>
- <i
- role="button"
+ <gl-icon
+ name="close"
+ class="dropdown-input-clear js-dropdown-input-clear"
:aria-label="__('Clear templates search input')"
- class="fa fa-times dropdown-input-clear js-dropdown-input-clear"
- >
- </i>
+ />
</div>
<div class="dropdown-content"></div>
<div class="dropdown-footer">
diff --git a/app/assets/javascripts/issue_show/components/incidents/graphql/queries/get_alert.graphql b/app/assets/javascripts/issue_show/components/incidents/graphql/queries/get_alert.graphql
new file mode 100644
index 00000000000..00ddc80432d
--- /dev/null
+++ b/app/assets/javascripts/issue_show/components/incidents/graphql/queries/get_alert.graphql
@@ -0,0 +1,20 @@
+query getAlert($iid: String!, $fullPath: ID!) {
+ project(fullPath: $fullPath) {
+ issue(iid: $iid) {
+ alertManagementAlert {
+ iid
+ title
+ detailsUrl
+ severity
+ status
+ startedAt
+ eventCount
+ monitoringTool
+ service
+ description
+ endedAt
+ details
+ }
+ }
+ }
+}
diff --git a/app/assets/javascripts/issue_show/components/incidents/highlight_bar.vue b/app/assets/javascripts/issue_show/components/incidents/highlight_bar.vue
new file mode 100644
index 00000000000..a47fe4c84cf
--- /dev/null
+++ b/app/assets/javascripts/issue_show/components/incidents/highlight_bar.vue
@@ -0,0 +1,42 @@
+<script>
+import { GlLink } from '@gitlab/ui';
+import { formatDate } from '~/lib/utils/datetime_utility';
+
+export default {
+ components: {
+ GlLink,
+ },
+ props: {
+ alert: {
+ type: Object,
+ required: true,
+ },
+ },
+ computed: {
+ startTime() {
+ return formatDate(this.alert.startedAt, 'yyyy-mm-dd Z');
+ },
+ },
+};
+</script>
+
+<template>
+ <div
+ class="gl-border-solid gl-border-1 gl-border-gray-100 gl-p-5 gl-mb-3 gl-rounded-base gl-display-flex gl-justify-content-space-between"
+ >
+ <div class="text-truncate gl-pr-3">
+ <span class="gl-font-weight-bold">{{ s__('HighlightBar|Original alert:') }}</span>
+ <gl-link :href="alert.detailsUrl">{{ alert.title }}</gl-link>
+ </div>
+
+ <div class="gl-pr-3 gl-white-space-nowrap">
+ <span class="gl-font-weight-bold">{{ s__('HighlightBar|Alert start time:') }}</span>
+ {{ startTime }}
+ </div>
+
+ <div class="gl-white-space-nowrap">
+ <span class="gl-font-weight-bold">{{ s__('HighlightBar|Alert events:') }}</span>
+ <span>{{ alert.eventCount }}</span>
+ </div>
+ </div>
+</template>
diff --git a/app/assets/javascripts/issue_show/components/incidents/incident_tabs.vue b/app/assets/javascripts/issue_show/components/incidents/incident_tabs.vue
new file mode 100644
index 00000000000..4104ddbf06f
--- /dev/null
+++ b/app/assets/javascripts/issue_show/components/incidents/incident_tabs.vue
@@ -0,0 +1,71 @@
+<script>
+import { GlTab, GlTabs } from '@gitlab/ui';
+import DescriptionComponent from '../description.vue';
+import HighlightBar from './highlight_bar.vue';
+import createFlash from '~/flash';
+import { s__ } from '~/locale';
+import AlertDetailsTable from '~/vue_shared/components/alert_details_table.vue';
+
+import getAlert from './graphql/queries/get_alert.graphql';
+
+export default {
+ components: {
+ AlertDetailsTable,
+ DescriptionComponent,
+ GlTab,
+ GlTabs,
+ HighlightBar,
+ },
+ inject: ['fullPath', 'iid'],
+ apollo: {
+ alert: {
+ query: getAlert,
+ variables() {
+ return {
+ fullPath: this.fullPath,
+ iid: this.iid,
+ };
+ },
+ update(data) {
+ return data?.project?.issue?.alertManagementAlert;
+ },
+ error() {
+ createFlash({
+ message: s__('Incident|There was an issue loading alert data. Please try again.'),
+ });
+ },
+ },
+ },
+ data() {
+ return {
+ alert: null,
+ };
+ },
+ computed: {
+ loading() {
+ return this.$apollo.queries.alert.loading;
+ },
+ alertTableFields() {
+ if (this.alert) {
+ const { detailsUrl, __typename, ...restDetails } = this.alert;
+ return restDetails;
+ }
+ return null;
+ },
+ },
+};
+</script>
+
+<template>
+ <div>
+ <gl-tabs content-class="gl-reset-line-height" class="gl-mt-n3" data-testid="incident-tabs">
+ <gl-tab :title="s__('Incident|Summary')">
+ <highlight-bar v-if="alert" :alert="alert" />
+ <description-component v-bind="$attrs" />
+ </gl-tab>
+ <gl-tab v-if="alert" class="alert-management-details" :title="s__('Incident|Alert details')">
+ <alert-details-table :alert="alertTableFields" :loading="loading" />
+ </gl-tab>
+ </gl-tabs>
+ </div>
+</template>
diff --git a/app/assets/javascripts/issue_show/components/locked_warning.vue b/app/assets/javascripts/issue_show/components/locked_warning.vue
index 19c7a11d87b..96f5a7c88e0 100644
--- a/app/assets/javascripts/issue_show/components/locked_warning.vue
+++ b/app/assets/javascripts/issue_show/components/locked_warning.vue
@@ -1,4 +1,5 @@
<script>
+/* eslint-disable vue/no-v-html */
import { __, sprintf } from '~/locale';
export default {
diff --git a/app/assets/javascripts/issue_show/components/pinned_links.vue b/app/assets/javascripts/issue_show/components/pinned_links.vue
index a877aa2ac96..d38189307bd 100644
--- a/app/assets/javascripts/issue_show/components/pinned_links.vue
+++ b/app/assets/javascripts/issue_show/components/pinned_links.vue
@@ -20,20 +20,25 @@ export default {
},
computed: {
pinnedLinks() {
- return [
- {
+ const links = [];
+ if (this.publishedIncidentUrl) {
+ links.push({
id: 'publishedIncidentUrl',
url: this.publishedIncidentUrl,
text: STATUS_PAGE_PUBLISHED,
icon: 'tanuki',
- },
- {
+ });
+ }
+ if (this.zoomMeetingUrl) {
+ links.push({
id: 'zoomMeetingUrl',
url: this.zoomMeetingUrl,
text: JOIN_ZOOM_MEETING,
icon: 'brand-zoom',
- },
- ];
+ });
+ }
+
+ return links;
},
},
methods: {
@@ -45,7 +50,7 @@ export default {
</script>
<template>
- <div class="border-bottom gl-mb-6 gl-display-flex gl-justify-content-start">
+ <div v-if="pinnedLinks && pinnedLinks.length" class="gl-display-flex gl-justify-content-start">
<template v-for="(link, i) in pinnedLinks">
<div v-if="link.url" :key="link.id" :class="{ 'gl-pr-3': needsPaddingClass(i) }">
<gl-button
diff --git a/app/assets/javascripts/issue_show/components/title.vue b/app/assets/javascripts/issue_show/components/title.vue
index 1e1dce5f4fc..b03a91716fe 100644
--- a/app/assets/javascripts/issue_show/components/title.vue
+++ b/app/assets/javascripts/issue_show/components/title.vue
@@ -1,12 +1,15 @@
<script>
+import { GlButton, GlTooltipDirective, GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
import animateMixin from '../mixins/animate';
import eventHub from '../event_hub';
-import tooltip from '../../vue_shared/directives/tooltip';
-import { spriteIcon } from '../../lib/utils/common_utils';
export default {
+ components: {
+ GlButton,
+ },
directives: {
- tooltip,
+ GlTooltip: GlTooltipDirective,
+ SafeHtml,
},
mixins: [animateMixin],
props: {
@@ -40,11 +43,6 @@ export default {
titleEl: document.querySelector('title'),
};
},
- computed: {
- pencilIcon() {
- return spriteIcon('pencil', 'link-highlight');
- },
- },
watch: {
titleHtml() {
this.setPageTitle();
@@ -67,25 +65,21 @@ export default {
<template>
<div class="title-container">
<h2
+ v-safe-html="titleHtml"
:class="{
'issue-realtime-pre-pulse': preAnimation,
'issue-realtime-trigger-pulse': pulseAnimation,
}"
class="title qa-title"
dir="auto"
- v-html="titleHtml"
></h2>
- <button
+ <gl-button
v-if="showInlineEditButton && canUpdate"
- v-tooltip
- type="button"
- class="btn btn-default btn-edit btn-svg js-issuable-edit
- qa-edit-button"
+ v-gl-tooltip.bottom
+ icon="pencil"
+ class="btn-edit js-issuable-edit qa-edit-button"
title="Edit title and description"
- data-placement="bottom"
- data-container="body"
@click="edit"
- v-html="pencilIcon"
- ></button>
+ />
</div>
</template>