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>2023-09-13 21:11:34 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-09-13 21:11:34 +0300
commita5c9ef1929e2b7c1b1beb964d36f9e782ed01e8b (patch)
tree964453b0794811f16b011db7417d50c66d1812d9 /app/assets/javascripts/ci
parent82b9539d93d7fd3d9d7ebccf4d4472d451e888da (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets/javascripts/ci')
-rw-r--r--app/assets/javascripts/ci/job_details/components/job_header.vue175
-rw-r--r--app/assets/javascripts/ci/job_details/job_app.vue6
2 files changed, 178 insertions, 3 deletions
diff --git a/app/assets/javascripts/ci/job_details/components/job_header.vue b/app/assets/javascripts/ci/job_details/components/job_header.vue
new file mode 100644
index 00000000000..7f4dea05464
--- /dev/null
+++ b/app/assets/javascripts/ci/job_details/components/job_header.vue
@@ -0,0 +1,175 @@
+<script>
+import { GlTooltipDirective, GlButton, GlAvatarLink, GlAvatarLabeled, GlTooltip } from '@gitlab/ui';
+import SafeHtml from '~/vue_shared/directives/safe_html';
+import { isGid, getIdFromGraphQLId } from '~/graphql_shared/utils';
+import { glEmojiTag } from '~/emoji';
+import { __, sprintf } from '~/locale';
+import CiBadgeLink from '~/vue_shared/components/ci_badge_link.vue';
+import TimeagoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
+
+/**
+ * Renders header component for job and pipeline page based on UI mockups
+ *
+ * Used in:
+ * - job show page
+ * - pipeline show page
+ */
+export default {
+ components: {
+ CiBadgeLink,
+ TimeagoTooltip,
+ GlButton,
+ GlAvatarLink,
+ GlAvatarLabeled,
+ GlTooltip,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ SafeHtml,
+ },
+ EMOJI_REF: 'EMOJI_REF',
+ props: {
+ status: {
+ type: Object,
+ required: true,
+ },
+ itemName: {
+ type: String,
+ required: true,
+ },
+ itemId: {
+ type: String,
+ required: false,
+ default: '',
+ },
+ time: {
+ type: String,
+ required: true,
+ },
+ user: {
+ type: Object,
+ required: false,
+ default: () => ({}),
+ },
+ hasSidebarButton: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ shouldRenderTriggeredLabel: {
+ type: Boolean,
+ required: false,
+ default: true,
+ },
+ },
+
+ computed: {
+ userAvatarAltText() {
+ return sprintf(__(`%{username}'s avatar`), { username: this.user.name });
+ },
+ userPath() {
+ // GraphQL returns `webPath` and Rest `path`
+ return this.user?.webPath || this.user?.path;
+ },
+ avatarUrl() {
+ // GraphQL returns `avatarUrl` and Rest `avatar_url`
+ return this.user?.avatarUrl || this.user?.avatar_url;
+ },
+ webUrl() {
+ // GraphQL returns `webUrl` and Rest `web_url`
+ return this.user?.webUrl || this.user?.web_url;
+ },
+ statusTooltipHTML() {
+ // Rest `status_tooltip_html` which is a ready to work
+ // html for the emoji and the status text inside a tooltip.
+ // GraphQL returns `status.emoji` and `status.message` which
+ // needs to be combined to make the html we want.
+ const { emoji } = this.user?.status || {};
+ const emojiHtml = emoji ? glEmojiTag(emoji) : '';
+
+ return emojiHtml || this.user?.status_tooltip_html;
+ },
+ message() {
+ return this.user?.status?.message;
+ },
+ item() {
+ if (this.itemId) {
+ return `${this.itemName} #${this.itemId}`;
+ }
+
+ return this.itemName;
+ },
+ userId() {
+ return isGid(this.user?.id) ? getIdFromGraphQLId(this.user?.id) : this.user?.id;
+ },
+ },
+
+ methods: {
+ onClickSidebarButton() {
+ this.$emit('clickedSidebarButton');
+ },
+ },
+ safeHtmlConfig: { ADD_TAGS: ['gl-emoji'] },
+};
+</script>
+
+<template>
+ <header
+ class="page-content-header gl-md-display-flex gl-min-h-7"
+ data-testid="job-header-content"
+ >
+ <section class="header-main-content gl-mr-3">
+ <ci-badge-link class="gl-mr-3" :status="status" />
+
+ <strong data-testid="job-header-item-text">{{ item }}</strong>
+
+ <template v-if="shouldRenderTriggeredLabel">{{ __('started') }}</template>
+ <template v-else>{{ __('created') }}</template>
+
+ <timeago-tooltip :time="time" />
+
+ {{ __('by') }}
+
+ <template v-if="user">
+ <gl-avatar-link
+ :data-user-id="userId"
+ :data-username="user.username"
+ :data-name="user.name"
+ :href="webUrl"
+ target="_blank"
+ class="js-user-link gl-vertical-align-middle gl-mx-2 gl-align-items-center"
+ >
+ <gl-avatar-labeled
+ :size="24"
+ :src="avatarUrl"
+ :label="user.name"
+ class="gl-display-none gl-sm-display-inline-flex gl-mx-1"
+ />
+ <strong class="author gl-display-inline gl-sm-display-none!">@{{ user.username }}</strong>
+ <gl-tooltip v-if="message" :target="() => $refs[$options.EMOJI_REF]">
+ {{ message }}
+ </gl-tooltip>
+ <span
+ v-if="statusTooltipHTML"
+ :ref="$options.EMOJI_REF"
+ v-safe-html:[$options.safeHtmlConfig]="statusTooltipHTML"
+ class="gl-ml-2"
+ :data-testid="message"
+ ></span>
+ </gl-avatar-link>
+ </template>
+ </section>
+
+ <!-- eslint-disable-next-line @gitlab/vue-prefer-dollar-scopedslots -->
+ <section v-if="$slots.default" data-testid="job-header-action-buttons" class="gl-display-flex">
+ <slot></slot>
+ </section>
+ <gl-button
+ v-if="hasSidebarButton"
+ class="gl-md-display-none gl-ml-auto gl-align-self-start js-sidebar-build-toggle"
+ icon="chevron-double-lg-left"
+ :aria-label="__('Toggle sidebar')"
+ @click="onClickSidebarButton"
+ />
+ </header>
+</template>
diff --git a/app/assets/javascripts/ci/job_details/job_app.vue b/app/assets/javascripts/ci/job_details/job_app.vue
index ede517b2d94..474190fe50e 100644
--- a/app/assets/javascripts/ci/job_details/job_app.vue
+++ b/app/assets/javascripts/ci/job_details/job_app.vue
@@ -8,13 +8,13 @@ import LogTopBar from 'ee_else_ce/ci/job_details/components/job_log_controllers.
import SafeHtml from '~/vue_shared/directives/safe_html';
import { isScrolledToBottom } from '~/lib/utils/scroll_utils';
import { __, sprintf } from '~/locale';
-import CiHeader from '~/vue_shared/components/header_ci_component.vue';
import delayedJobMixin from '~/ci/mixins/delayed_job_mixin';
import Log from '~/ci/job_details/components/log/log.vue';
import { MANUAL_STATUS } from '~/ci/constants';
import EmptyState from './components/empty_state.vue';
import EnvironmentsBlock from './components/environments_block.vue';
import ErasedBlock from './components/erased_block.vue';
+import JobHeader from './components/job_header.vue';
import StuckBlock from './components/stuck_block.vue';
import UnmetPrerequisitesBlock from './components/unmet_prerequisites_block.vue';
import Sidebar from './components/sidebar/sidebar.vue';
@@ -22,7 +22,7 @@ import Sidebar from './components/sidebar/sidebar.vue';
export default {
name: 'JobPageApp',
components: {
- CiHeader,
+ JobHeader,
EmptyState,
EnvironmentsBlock,
ErasedBlock,
@@ -225,7 +225,7 @@ export default {
<!-- Header Section -->
<header>
<div class="build-header top-area">
- <ci-header
+ <job-header
:status="job.status"
:time="headerTime"
:user="job.user"