|
|
|
@ -1,28 +1,30 @@
|
|
|
|
|
<template>
|
|
|
|
|
<div class="action-view-container">
|
|
|
|
|
<div class="ui container action-view-container">
|
|
|
|
|
<div class="action-view-header">
|
|
|
|
|
<div class="action-info-summary">
|
|
|
|
|
<div class="action-info-summary-title">
|
|
|
|
|
<ActionRunStatus :locale-status="locale.status[run.status]" :status="run.status" :size="20"/>
|
|
|
|
|
<div class="action-title">
|
|
|
|
|
<h2 class="action-info-summary-title-text">
|
|
|
|
|
{{ run.title }}
|
|
|
|
|
</h2>
|
|
|
|
|
</div>
|
|
|
|
|
<button class="ui basic small compact button primary" @click="approveRun()" v-if="run.canApprove">
|
|
|
|
|
<SvgIcon class="gt-mr-2" name="octicon-play" :size="20"/> {{ locale.approve }}
|
|
|
|
|
{{ locale.approve }}
|
|
|
|
|
</button>
|
|
|
|
|
<button class="ui basic small compact button red" @click="cancelRun()" v-else-if="run.canCancel">
|
|
|
|
|
<SvgIcon class="gt-mr-2" name="octicon-x-circle-fill" :size="20"/> {{ locale.cancel }}
|
|
|
|
|
{{ locale.cancel }}
|
|
|
|
|
</button>
|
|
|
|
|
<button class="ui basic small compact button secondary" @click="rerun()" v-else-if="run.canRerun">
|
|
|
|
|
<SvgIcon class="gt-mr-2" name="octicon-sync" :size="20"/> {{ locale.rerun }}
|
|
|
|
|
{{ locale.rerun_all }}
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="action-commit-summary">
|
|
|
|
|
{{ run.commit.localeCommit }}
|
|
|
|
|
<a :href="run.commit.link">{{ run.commit.shortSHA }}</a>
|
|
|
|
|
<span class="ui label" v-if="run.commit.shortSHA">
|
|
|
|
|
<span class="ui label" v-if="run.commit.shortSHA">
|
|
|
|
|
<a :href="run.commit.branch.link">{{ run.commit.branch.name }}</a>
|
|
|
|
|
</span>
|
|
|
|
|
{{ run.commit.localePushedBy }}
|
|
|
|
|
{{ run.commit.localePushedBy }}
|
|
|
|
|
<a :href="run.commit.pusher.link">{{ run.commit.pusher.displayName }}</a>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
@ -30,15 +32,15 @@
|
|
|
|
|
<div class="action-view-left">
|
|
|
|
|
<div class="job-group-section">
|
|
|
|
|
<div class="job-brief-list">
|
|
|
|
|
<div class="job-brief-item" v-for="(job, index) in run.jobs" :key="job.id">
|
|
|
|
|
<div class="job-brief-item" :class="parseInt(jobIndex) === index ? 'selected' : ''" v-for="(job, index) in run.jobs" :key="job.id" @mouseenter="onHoverRerunIndex = job.id" @mouseleave="onHoverRerunIndex = -1">
|
|
|
|
|
<a class="job-brief-link" :href="run.link+'/jobs/'+index">
|
|
|
|
|
<ActionRunStatus :locale-status="locale.status[job.status]" :status="job.status"/>
|
|
|
|
|
<span class="ui text gt-mx-3">{{ job.name }}</span>
|
|
|
|
|
<span class="job-brief-name gt-mx-3 gt-ellipsis">{{ job.name }}</span>
|
|
|
|
|
</a>
|
|
|
|
|
<span class="job-brief-info">
|
|
|
|
|
<span class="step-summary-duration">{{ job.duration }}</span>
|
|
|
|
|
<button :data-tooltip-content="locale.rerun" class="job-brief-rerun" @click="rerunJob(index)" v-if="job.canRerun">
|
|
|
|
|
<SvgIcon name="octicon-sync" class="ui text black"/>
|
|
|
|
|
</button>
|
|
|
|
|
<SvgIcon name="octicon-sync" role="button" :data-tooltip-content="locale.rerun" class="job-brief-rerun gt-mx-3" @click="rerunJob(index)" v-if="job.canRerun && onHoverRerunIndex === job.id"/>
|
|
|
|
|
</span>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
@ -58,21 +60,24 @@
|
|
|
|
|
|
|
|
|
|
<div class="action-view-right">
|
|
|
|
|
<div class="job-info-header">
|
|
|
|
|
<div class="job-info-header-title">
|
|
|
|
|
<h3 class="job-info-header-title">
|
|
|
|
|
{{ currentJob.title }}
|
|
|
|
|
</div>
|
|
|
|
|
<div class="job-info-header-detail">
|
|
|
|
|
</h3>
|
|
|
|
|
<p class="job-info-header-detail">
|
|
|
|
|
{{ currentJob.detail }}
|
|
|
|
|
</div>
|
|
|
|
|
</p>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="job-step-container">
|
|
|
|
|
<div class="job-step-section" v-for="(jobStep, i) in currentJob.steps" :key="i">
|
|
|
|
|
<div class="job-step-summary" @click.stop="toggleStepLogs(i)">
|
|
|
|
|
<SvgIcon :name="currentJobStepsStates[i].expanded ? 'octicon-chevron-down': 'octicon-chevron-right'" class="gt-mr-3"/>
|
|
|
|
|
|
|
|
|
|
<div class="job-step-summary" @click.stop="toggleStepLogs(i)" :class="currentJobStepsStates[i].expanded ? 'selected' : ''">
|
|
|
|
|
<!-- If the job is done and the job step log is loaded for the first time, show the loading icon
|
|
|
|
|
currentJobStepsStates[i].cursor === null means the log is loaded for the first time
|
|
|
|
|
-->
|
|
|
|
|
<SvgIcon v-if="isDone(run.status) && currentJobStepsStates[i].expanded && currentJobStepsStates[i].cursor === null" name="octicon-sync" class="gt-mr-3 job-status-rotate"/>
|
|
|
|
|
<SvgIcon v-else :name="currentJobStepsStates[i].expanded ? 'octicon-chevron-down': 'octicon-chevron-right'" class="gt-mr-3"/>
|
|
|
|
|
<ActionRunStatus :status="jobStep.status" class="gt-mr-3"/>
|
|
|
|
|
|
|
|
|
|
<span class="step-summary-msg">{{ jobStep.summary }}</span>
|
|
|
|
|
<span class="step-summary-msg gt-ellipsis">{{ jobStep.summary }}</span>
|
|
|
|
|
<span class="step-summary-duration">{{ jobStep.duration }}</span>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
@ -115,6 +120,7 @@ const sfc = {
|
|
|
|
|
intervalID: null,
|
|
|
|
|
currentJobStepsStates: [],
|
|
|
|
|
artifacts: [],
|
|
|
|
|
onHoverRerunIndex: -1,
|
|
|
|
|
|
|
|
|
|
// provided by backend
|
|
|
|
|
run: {
|
|
|
|
@ -295,6 +301,7 @@ const sfc = {
|
|
|
|
|
// sync the currentJobStepsStates to store the job step states
|
|
|
|
|
for (let i = 0; i < this.currentJob.steps.length; i++) {
|
|
|
|
|
if (!this.currentJobStepsStates[i]) {
|
|
|
|
|
// initial states for job steps
|
|
|
|
|
this.currentJobStepsStates[i] = {cursor: null, expanded: false};
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -325,6 +332,10 @@ const sfc = {
|
|
|
|
|
body,
|
|
|
|
|
});
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
isDone(status) {
|
|
|
|
|
return ['success', 'skipped', 'failure', 'cancelled'].includes(status);
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
@ -348,6 +359,7 @@ export function initRepositoryActionView() {
|
|
|
|
|
cancel: el.getAttribute('data-locale-cancel'),
|
|
|
|
|
rerun: el.getAttribute('data-locale-rerun'),
|
|
|
|
|
artifactsTitle: el.getAttribute('data-locale-artifacts-title'),
|
|
|
|
|
rerun_all: el.getAttribute('data-locale-rerun-all'),
|
|
|
|
|
status: {
|
|
|
|
|
unknown: el.getAttribute('data-locale-status-unknown'),
|
|
|
|
|
waiting: el.getAttribute('data-locale-status-waiting'),
|
|
|
|
@ -417,24 +429,30 @@ export function ansiLogToHTML(line) {
|
|
|
|
|
/* action view header */
|
|
|
|
|
|
|
|
|
|
.action-view-header {
|
|
|
|
|
margin: 0 20px 20px 20px;
|
|
|
|
|
margin: 20px 0px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.action-info-summary {
|
|
|
|
|
font-size: 150%;
|
|
|
|
|
height: 20px;
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
margin-top: 1rem;
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.action-info-summary .action-title {
|
|
|
|
|
padding: 0 5px;
|
|
|
|
|
.action-info-summary-title {
|
|
|
|
|
display: flex;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.action-info-summary-title-text {
|
|
|
|
|
font-size: 20px;
|
|
|
|
|
margin: 0 0 0 5px;
|
|
|
|
|
flex: 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.action-commit-summary {
|
|
|
|
|
padding: 10px 10px;
|
|
|
|
|
display: flex;
|
|
|
|
|
gap: 5px;
|
|
|
|
|
margin: 10px 0px 10px 25px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ================ */
|
|
|
|
@ -444,7 +462,6 @@ export function ansiLogToHTML(line) {
|
|
|
|
|
width: 30%;
|
|
|
|
|
max-width: 400px;
|
|
|
|
|
overflow-y: scroll;
|
|
|
|
|
margin-left: 10px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.job-group-section .job-group-summary {
|
|
|
|
@ -473,42 +490,64 @@ export function ansiLogToHTML(line) {
|
|
|
|
|
padding-right: 3px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.job-group-section .job-brief-list .job-brief-item {
|
|
|
|
|
.job-brief-item {
|
|
|
|
|
margin: 5px 0;
|
|
|
|
|
padding: 10px;
|
|
|
|
|
background: var(--color-info-bg);
|
|
|
|
|
border-radius: 5px;
|
|
|
|
|
text-decoration: none;
|
|
|
|
|
display: flex;
|
|
|
|
|
justify-items: center;
|
|
|
|
|
flex-wrap: nowrap;
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
align-items: center;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.job-group-section .job-brief-list .job-brief-item .job-brief-rerun {
|
|
|
|
|
float: right;
|
|
|
|
|
border: none;
|
|
|
|
|
background-color: transparent;
|
|
|
|
|
outline: none;
|
|
|
|
|
.job-brief-item:hover {
|
|
|
|
|
background-color: var(--color-secondary);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.job-brief-item.selected {
|
|
|
|
|
font-weight: var(--font-weight-bold);
|
|
|
|
|
background-color: var(--color-secondary-dark-1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.job-brief-item:first-of-type {
|
|
|
|
|
margin-top: 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.job-brief-item .job-brief-rerun {
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
transition: transform 0.2s;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.job-group-section .job-brief-list .job-brief-item .job-brief-rerun:hover {
|
|
|
|
|
.job-brief-item .job-brief-rerun:hover {
|
|
|
|
|
transform: scale(130%);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.job-group-section .job-brief-list .job-brief-item .job-brief-link {
|
|
|
|
|
flex-grow: 1;
|
|
|
|
|
.job-brief-item .job-brief-link {
|
|
|
|
|
display: flex;
|
|
|
|
|
width: 100%;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.job-group-section .job-brief-list .job-brief-item .job-brief-link span {
|
|
|
|
|
.job-brief-item .job-brief-link span {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.job-group-section .job-brief-list .job-brief-item:hover {
|
|
|
|
|
background-color: var(--color-secondary);
|
|
|
|
|
.job-brief-item .job-brief-link .job-brief-name {
|
|
|
|
|
display: block;
|
|
|
|
|
width: 70%;
|
|
|
|
|
color: var(--color-text);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.job-brief-item .job-brief-link:hover {
|
|
|
|
|
text-decoration: none;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.job-brief-item .job-brief-info {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
width: 55px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ================ */
|
|
|
|
@ -517,21 +556,27 @@ export function ansiLogToHTML(line) {
|
|
|
|
|
.action-view-right {
|
|
|
|
|
flex: 1;
|
|
|
|
|
background-color: var(--color-console-bg);
|
|
|
|
|
color: var(--color-console-fg);
|
|
|
|
|
color: var(--color-secondary-dark-2);
|
|
|
|
|
max-height: 100%;
|
|
|
|
|
margin-right: 10px;
|
|
|
|
|
width: 70%;
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.job-info-header .job-info-header-title {
|
|
|
|
|
font-size: 150%;
|
|
|
|
|
.job-info-header {
|
|
|
|
|
padding: 10px;
|
|
|
|
|
border-bottom: 1px solid var(--color-grey);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.job-info-header .job-info-header-title {
|
|
|
|
|
color: var(--color-console-fg);
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
margin: 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.job-info-header .job-info-header-detail {
|
|
|
|
|
padding: 0 10px 10px;
|
|
|
|
|
border-bottom: 1px solid var(--color-grey);
|
|
|
|
|
color: var(--color-secondary-dark-3);
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.job-step-container {
|
|
|
|
@ -543,6 +588,8 @@ export function ansiLogToHTML(line) {
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
padding: 5px 10px;
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
user-select: none;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.job-step-container .job-step-summary .step-summary-msg {
|
|
|
|
@ -553,8 +600,25 @@ export function ansiLogToHTML(line) {
|
|
|
|
|
margin-left: 16px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.job-step-container .job-step-summary:hover {
|
|
|
|
|
.job-step-container .job-step-summary:hover,
|
|
|
|
|
.job-step-container .job-step-summary.selected {
|
|
|
|
|
color: var(--color-console-fg);
|
|
|
|
|
background-color: var(--color-black-light);
|
|
|
|
|
border-radius: 5px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@media (max-width: 768px) {
|
|
|
|
|
.action-view-body {
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
}
|
|
|
|
|
.action-view-left, .action-view-right {
|
|
|
|
|
width: 100%;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.action-view-left {
|
|
|
|
|
max-width: none;
|
|
|
|
|
overflow-y: hidden;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
</style>
|
|
|
|
|
|
|
|
|
@ -576,12 +640,19 @@ export function ansiLogToHTML(line) {
|
|
|
|
|
|
|
|
|
|
.job-step-section .job-step-logs {
|
|
|
|
|
font-family: monospace, monospace;
|
|
|
|
|
margin: 8px 0px;
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.job-step-section .job-step-logs .job-log-line {
|
|
|
|
|
display: flex;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.job-step-section .job-step-logs .job-log-line:hover {
|
|
|
|
|
color: var(--color-console-fg);
|
|
|
|
|
background-color: var(--color-console-hover-bg);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.job-step-section .job-step-logs .job-log-line .line-num {
|
|
|
|
|
width: 48px;
|
|
|
|
|
color: var(--color-grey-light);
|
|
|
|
|