diff options
Diffstat (limited to 'app/assets/javascripts/jobs/components')
6 files changed, 83 insertions, 52 deletions
diff --git a/app/assets/javascripts/jobs/components/environments_block.vue b/app/assets/javascripts/jobs/components/environments_block.vue index da72cbeb856..4046e1ade82 100644 --- a/app/assets/javascripts/jobs/components/environments_block.vue +++ b/app/assets/javascripts/jobs/components/environments_block.vue @@ -189,25 +189,23 @@ export default { v-if="hasEnvironment" :href="environmentLink.link" data-testid="job-environment-link" - v-text="environmentLink.name" - /> + >{{ environmentLink.name }}</gl-link + > </template> <template #clusterNameOrLink> <gl-link v-if="clusterNameOrLink.path" :href="clusterNameOrLink.path" data-testid="job-cluster-link" - v-text="clusterNameOrLink.name" - /> + >{{ clusterNameOrLink.name }}</gl-link + > <template v-else>{{ clusterNameOrLink.name }}</template> </template> <template #kubernetesNamespace>{{ kubernetesNamespace }}</template> <template #deploymentLink> - <gl-link - :href="deploymentLink.path" - data-testid="job-deployment-link" - v-text="deploymentLink.name" - /> + <gl-link :href="deploymentLink.path" data-testid="job-deployment-link">{{ + deploymentLink.name + }}</gl-link> </template> </gl-sprintf> </p> diff --git a/app/assets/javascripts/jobs/components/job_app.vue b/app/assets/javascripts/jobs/components/job_app.vue index f9e6c64aad1..d5ee3423d70 100644 --- a/app/assets/javascripts/jobs/components/job_app.vue +++ b/app/assets/javascripts/jobs/components/job_app.vue @@ -287,6 +287,7 @@ export default { :is-scroll-top-disabled="isScrollTopDisabled" :is-job-log-size-visible="isJobLogSizeVisible" :is-scrolling-down="isScrollingDown" + :is-complete="isJobLogComplete" :job-log="jobLog" @scrollJobLogTop="scrollTop" @scrollJobLogBottom="scrollBottom" diff --git a/app/assets/javascripts/jobs/components/job_log_controllers.vue b/app/assets/javascripts/jobs/components/job_log_controllers.vue index 5e89dd5acc2..e9809ac661b 100644 --- a/app/assets/javascripts/jobs/components/job_log_controllers.vue +++ b/app/assets/javascripts/jobs/components/job_log_controllers.vue @@ -1,6 +1,6 @@ <script> import { GlTooltipDirective, GlLink, GlButton, GlSearchBoxByClick } from '@gitlab/ui'; -import { scrollToElement } from '~/lib/utils/common_utils'; +import { scrollToElement, backOff } from '~/lib/utils/common_utils'; import { numberToHumanSize } from '~/lib/utils/number_utils'; import { __, s__, sprintf } from '~/locale'; import HelpPopover from '~/vue_shared/components/help_popover.vue'; @@ -10,6 +10,7 @@ export default { i18n: { scrollToBottomButtonLabel: s__('Job|Scroll to bottom'), scrollToTopButtonLabel: s__('Job|Scroll to top'), + scrollToNextFailureButtonLabel: s__('Job|Scroll to next failure'), showRawButtonLabel: s__('Job|Show complete raw'), searchPlaceholder: s__('Job|Search job log'), noResults: s__('Job|No search results found'), @@ -55,6 +56,10 @@ export default { type: Boolean, required: true, }, + isComplete: { + type: Boolean, + required: true, + }, jobLog: { type: Array, required: true, @@ -64,6 +69,8 @@ export default { return { searchTerm: '', searchResults: [], + failureCount: null, + failureIndex: 0, }; }, computed: { @@ -72,16 +79,49 @@ export default { size: numberToHumanSize(this.size), }); }, - showJobLogSearch() { - return this.glFeatures.jobLogSearch; + showJumpToFailures() { + return this.glFeatures.jobLogJumpToFailures; + }, + hasFailures() { + return this.failureCount > 0; + }, + shouldDisableJumpToFailures() { + return !this.hasFailures; }, }, + mounted() { + this.checkFailureCount(); + }, methods: { + checkFailureCount() { + if (this.glFeatures.jobLogJumpToFailures) { + backOff((next, stop) => { + this.failureCount = document.querySelectorAll('.term-fg-l-red').length; + + if (this.hasFailures || (this.isComplete && !this.hasFailures)) { + stop(); + } else { + next(); + } + }); + } + }, + handleScrollToNextFailure() { + const failures = document.querySelectorAll('.term-fg-l-red'); + const nextFailure = failures[this.failureIndex]; + + if (nextFailure) { + nextFailure.scrollIntoView({ block: 'center' }); + this.failureIndex = (this.failureIndex + 1) % failures.length; + } + }, handleScrollToTop() { this.$emit('scrollJobLogTop'); + this.failureIndex = 0; }, handleScrollToBottom() { this.$emit('scrollJobLogBottom'); + this.failureIndex = 0; }, searchJobLog() { this.searchResults = []; @@ -135,10 +175,10 @@ export default { }; </script> <template> - <div class="top-bar"> + <div class="top-bar gl-display-flex gl-justify-content-space-between"> <!-- truncate information --> <div - class="truncated-info gl-display-none gl-sm-display-block gl-float-left" + class="truncated-info gl-display-none gl-sm-display-flex gl-flex-wrap gl-align-items-center" data-testid="log-truncated-info" > <template v-if="isJobLogSizeVisible"> @@ -154,25 +194,23 @@ export default { </div> <!-- eo truncate information --> - <div class="controllers gl-float-right"> - <template v-if="showJobLogSearch"> - <gl-search-box-by-click - v-model="searchTerm" - class="gl-mr-3" - :placeholder="$options.i18n.searchPlaceholder" - data-testid="job-log-search-box" - @clear="$emit('searchResults', [])" - @submit="searchJobLog" - /> + <div class="controllers"> + <gl-search-box-by-click + v-model="searchTerm" + class="gl-mr-3" + :placeholder="$options.i18n.searchPlaceholder" + data-testid="job-log-search-box" + @clear="$emit('searchResults', [])" + @submit="searchJobLog" + /> - <help-popover class="gl-mr-3"> - <template #title>{{ $options.i18n.searchPopoverTitle }}</template> + <help-popover class="gl-mr-3"> + <template #title>{{ $options.i18n.searchPopoverTitle }}</template> - <p class="gl-mb-0"> - {{ $options.i18n.searchPopoverDescription }} - </p> - </help-popover> - </template> + <p class="gl-mb-0"> + {{ $options.i18n.searchPopoverDescription }} + </p> + </help-popover> <!-- links --> <gl-button @@ -187,6 +225,18 @@ export default { <!-- eo links --> <!-- scroll buttons --> + <gl-button + v-if="showJumpToFailures" + v-gl-tooltip + :title="$options.i18n.scrollToNextFailureButtonLabel" + :aria-label="$options.i18n.scrollToNextFailureButtonLabel" + :disabled="shouldDisableJumpToFailures" + class="btn-scroll gl-ml-3" + data-testid="job-controller-scroll-to-failure" + icon="soft-wrap" + @click="handleScrollToNextFailure" + /> + <div v-gl-tooltip :title="$options.i18n.scrollToTopButtonLabel" class="gl-ml-3"> <gl-button :disabled="isScrollTopDisabled" diff --git a/app/assets/javascripts/jobs/components/sidebar_job_details_container.vue b/app/assets/javascripts/jobs/components/sidebar_job_details_container.vue index 15c4e503685..3b1509e5be5 100644 --- a/app/assets/javascripts/jobs/components/sidebar_job_details_container.vue +++ b/app/assets/javascripts/jobs/components/sidebar_job_details_container.vue @@ -1,7 +1,6 @@ <script> import { mapState } from 'vuex'; import { GlBadge } from '@gitlab/ui'; -import { helpPagePath } from '~/helpers/help_page_helper'; import { timeIntervalInWords } from '~/lib/utils/datetime_utility'; import { __, sprintf } from '~/locale'; import timeagoMixin from '~/vue_shared/mixins/timeago'; @@ -47,11 +46,6 @@ export default { this.job.coverage, ); }, - runnerHelpUrl() { - return helpPagePath('ci/runners/configure_runners.html', { - anchor: 'set-maximum-job-timeout-for-a-runner', - }); - }, runnerId() { const { id, short_sha: token, description } = this.job.runner; @@ -85,6 +79,7 @@ export default { TAGS: __('Tags:'), TIMEOUT: __('Timeout'), }, + RUNNER_HELP_URL: 'https://docs.gitlab.com/runner/register/index.html', }; </script> @@ -101,7 +96,7 @@ export default { <detail-row v-if="job.queued_duration" :value="queuedDuration" :title="$options.i18n.QUEUED" /> <detail-row v-if="hasTimeout" - :help-url="runnerHelpUrl" + :help-url="$options.RUNNER_HELP_URL" :value="timeout" data-testid="job-timeout" :title="$options.i18n.TIMEOUT" diff --git a/app/assets/javascripts/jobs/components/table/graphql/queries/get_jobs.query.graphql b/app/assets/javascripts/jobs/components/table/graphql/queries/get_jobs.query.graphql index 5b1032c6448..98b51e8c2c4 100644 --- a/app/assets/javascripts/jobs/components/table/graphql/queries/get_jobs.query.graphql +++ b/app/assets/javascripts/jobs/components/table/graphql/queries/get_jobs.query.graphql @@ -1,7 +1,6 @@ query getJobs($fullPath: ID!, $after: String, $first: Int = 30, $statuses: [CiJobStatus!]) { project(fullPath: $fullPath) { id - __typename jobs(after: $after, first: $first, statuses: $statuses) { count pageInfo { @@ -9,15 +8,12 @@ query getJobs($fullPath: ID!, $after: String, $first: Int = 30, $statuses: [CiJo hasNextPage hasPreviousPage startCursor - __typename } nodes { - __typename artifacts { nodes { downloadPath fileType - __typename } } allowFailure diff --git a/app/assets/javascripts/jobs/components/table/jobs_table_app.vue b/app/assets/javascripts/jobs/components/table/jobs_table_app.vue index b3db5a94ac5..c2f460cb647 100644 --- a/app/assets/javascripts/jobs/components/table/jobs_table_app.vue +++ b/app/assets/javascripts/jobs/components/table/jobs_table_app.vue @@ -3,7 +3,6 @@ import { GlAlert, GlSkeletonLoader, GlIntersectionObserver, GlLoadingIcon } from import { __ } from '~/locale'; import createFlash from '~/flash'; import JobsFilteredSearch from '../filtered_search/jobs_filtered_search.vue'; -import eventHub from './event_hub'; import GetJobs from './graphql/queries/get_jobs.query.graphql'; import JobsTable from './jobs_table.vue'; import JobsTableEmptyState from './jobs_table_empty_state.vue'; @@ -108,16 +107,7 @@ export default { } }, }, - mounted() { - eventHub.$on('jobActionPerformed', this.handleJobAction); - }, - beforeDestroy() { - eventHub.$off('jobActionPerformed', this.handleJobAction); - }, methods: { - handleJobAction() { - this.$apollo.queries.jobs.refetch({ statuses: this.scope }); - }, fetchJobsByStatus(scope) { this.infiniteScrollingTriggered = false; @@ -169,6 +159,7 @@ export default { v-if="shouldShowAlert" class="gl-mt-2" variant="danger" + data-testid="jobs-table-error-alert" dismissible @dismiss="isAlertDismissed = true" > |