diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-09-20 14:18:08 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-09-20 14:18:08 +0300 |
commit | 5afcbe03ead9ada87621888a31a62652b10a7e4f (patch) | |
tree | 9918b67a0d0f0bafa6542e839a8be37adf73102d /app/assets/javascripts/ci/job_details/components/log/log.vue | |
parent | c97c0201564848c1f53226fe19d71fdcc472f7d0 (diff) |
Add latest changes from gitlab-org/gitlab@16-4-stable-eev16.4.0-rc42
Diffstat (limited to 'app/assets/javascripts/ci/job_details/components/log/log.vue')
-rw-r--r-- | app/assets/javascripts/ci/job_details/components/log/log.vue | 106 |
1 files changed, 106 insertions, 0 deletions
diff --git a/app/assets/javascripts/ci/job_details/components/log/log.vue b/app/assets/javascripts/ci/job_details/components/log/log.vue new file mode 100644 index 00000000000..fb6a6a58074 --- /dev/null +++ b/app/assets/javascripts/ci/job_details/components/log/log.vue @@ -0,0 +1,106 @@ +<!-- eslint-disable vue/multi-word-component-names --> +<script> +// eslint-disable-next-line no-restricted-imports +import { mapState, mapActions } from 'vuex'; +import { scrollToElement } from '~/lib/utils/common_utils'; +import { getLocationHash } from '~/lib/utils/url_utility'; +import CollapsibleLogSection from './collapsible_section.vue'; +import LogLine from './line.vue'; + +export default { + components: { + CollapsibleLogSection, + LogLine, + }, + props: { + searchResults: { + type: Array, + required: false, + default: () => [], + }, + }, + computed: { + ...mapState([ + 'jobLogEndpoint', + 'jobLog', + 'isJobLogComplete', + 'isScrolledToBottomBeforeReceivingJobLog', + ]), + highlightedLines() { + return this.searchResults.map((result) => result.lineNumber); + }, + }, + updated() { + this.$nextTick(() => { + if (!window.location.hash) { + this.handleScrollDown(); + } + }); + }, + mounted() { + if (window.location.hash) { + const lineNumber = getLocationHash(); + + this.unwatchJobLog = this.$watch('jobLog', async () => { + if (this.jobLog.length) { + await this.$nextTick(); + + const el = document.getElementById(lineNumber); + scrollToElement(el); + this.unwatchJobLog(); + } + }); + } + }, + methods: { + ...mapActions(['toggleCollapsibleLine', 'scrollBottom']), + handleOnClickCollapsibleLine(section) { + this.toggleCollapsibleLine(section); + }, + /** + * The job log is sent in HTML, which means we need to use `v-html` to render it + * Using the updated hook with $nextTick is not enough to wait for the DOM to be updated + * in this case because it runs before `v-html` has finished running, since there's no + * Vue binding. + * In order to scroll the page down after `v-html` has finished, we need to use setTimeout + */ + handleScrollDown() { + if (this.isScrolledToBottomBeforeReceivingJobLog) { + setTimeout(() => { + this.scrollBottom(); + }, 0); + } + }, + isHighlighted({ lineNumber }) { + return this.highlightedLines.includes(lineNumber); + }, + }, +}; +</script> +<template> + <code class="job-log d-block" data-testid="job-log-content"> + <template v-for="(section, index) in jobLog"> + <collapsible-log-section + v-if="section.isHeader" + :key="`collapsible-${index}`" + :section="section" + :job-log-endpoint="jobLogEndpoint" + :search-results="searchResults" + @onClickCollapsibleLine="handleOnClickCollapsibleLine" + /> + <log-line + v-else + :key="section.offset" + :line="section" + :path="jobLogEndpoint" + :is-highlighted="isHighlighted(section)" + /> + </template> + + <div v-if="!isJobLogComplete" class="js-log-animation loader-animation pt-3 pl-3"> + <div class="dot"></div> + <div class="dot"></div> + <div class="dot"></div> + </div> + </code> +</template> |