diff options
author | HesterG <hestergong@gmail.com> | 2023-05-22 12:17:24 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-05-22 12:17:24 +0800 |
commit | da461b5a085c0fbf705df9a751159d13bee7139a (patch) | |
tree | 87d3ca4d682fda67e4502f83796e8f34b348d105 | |
parent | cdb088cec288a20e14240f86a689dd14f4cd603b (diff) | |
download | gitea-da461b5a085c0fbf705df9a751159d13bee7139a.tar.gz gitea-da461b5a085c0fbf705df9a751159d13bee7139a.zip |
Improvements for action detail page (#24718)
Close #24625
Main changes:
1. For the left panel, show rerun icon only on hover, and add style when
the job is selected, and removed icon on the "rerun all" button and
modify the text on the button
https://github.com/go-gitea/gitea/assets/17645053/cc437a17-d2e9-4f1b-a8cf-f56e53962767
2. Adjust fonts, and add on hover effects to the log lines. And add
loading effect when the job is done and the job step log is expanded for
the first time. (With reference to github)
https://github.com/go-gitea/gitea/assets/17645053/2808d77d-f402-4fb0-8819-7aa0a018cf0c
3. Add `gt-ellipsis` to `step-summary-msg` and `job-brief-name`
<img width="898" alt="ellipsis"
src="https://github.com/go-gitea/gitea/assets/17645053/e2fb7049-3125-4252-970d-15b0751febc7">
4. Fixed
https://github.com/go-gitea/gitea/issues/24625#issuecomment-1541380010
by adding explicit conditions to `ActionRunStatus.vue` and `status.tmpl`
5. Adjust some css styles
---------
Co-authored-by: silverwind <me@silverwind.io>
-rw-r--r-- | options/locale/locale_en-US.ini | 1 | ||||
-rw-r--r-- | templates/repo/actions/status.tmpl | 5 | ||||
-rw-r--r-- | templates/repo/actions/view.tmpl | 1 | ||||
-rw-r--r-- | web_src/css/base.css | 1 | ||||
-rw-r--r-- | web_src/js/components/ActionRunStatus.vue | 5 | ||||
-rw-r--r-- | web_src/js/components/RepoActionView.vue | 171 |
6 files changed, 130 insertions, 54 deletions
diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index e5742157d8..80ccecbce1 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -80,6 +80,7 @@ milestones = Milestones ok = OK cancel = Cancel rerun = Re-run +rerun_all = Re-run all jobs save = Save add = Add add_all = Add All diff --git a/templates/repo/actions/status.tmpl b/templates/repo/actions/status.tmpl index ab2ee8482c..cdc747aa8b 100644 --- a/templates/repo/actions/status.tmpl +++ b/templates/repo/actions/status.tmpl @@ -1,5 +1,6 @@ <!-- This template should be kept the same as web_src/js/components/ActionRunStatus.vue Please also update the vue file above if this template is modified. + action status accepted: success, skipped, waiting, blocked, running, failure, cancelled, unknown --> {{- $size := 16 -}} {{- if .size -}} @@ -11,7 +12,7 @@ {{- $className = .className -}} {{- end -}} -<span data-tooltip-content="{{.locale.Tr (printf "actions.status.%s" .status)}}"> +<span class="gt-df gt-ac" data-tooltip-content="{{.locale.Tr (printf "actions.status.%s" .status)}}"> {{if eq .status "success"}} {{svg "octicon-check-circle-fill" $size (printf "text green %s" $className)}} {{else if eq .status "skipped"}} @@ -22,7 +23,7 @@ {{svg "octicon-blocked" $size (printf "text yellow %s" $className)}} {{else if eq .status "running"}} {{svg "octicon-meter" $size (printf "text yellow job-status-rotate %s" $className)}} -{{else}} +{{else if or (eq .status "failure") or (eq .status "cancelled") or (eq .status "unknown")}} {{svg "octicon-x-circle-fill" $size (printf "text red %s" $className)}} {{end}} </span> diff --git a/templates/repo/actions/view.tmpl b/templates/repo/actions/view.tmpl index 8d6559ee98..3a3a069cbc 100644 --- a/templates/repo/actions/view.tmpl +++ b/templates/repo/actions/view.tmpl @@ -9,6 +9,7 @@ data-locale-approve="{{.locale.Tr "repo.diff.review.approve"}}" data-locale-cancel="{{.locale.Tr "cancel"}}" data-locale-rerun="{{.locale.Tr "rerun"}}" + data-locale-rerun-all="{{.locale.Tr "rerun_all"}}" data-locale-status-unknown="{{.locale.Tr "actions.status.unknown"}}" data-locale-status-waiting="{{.locale.Tr "actions.status.waiting"}}" data-locale-status-running="{{.locale.Tr "actions.status.running"}}" diff --git a/web_src/css/base.css b/web_src/css/base.css index eb12ffef7a..4b9f1eef22 100644 --- a/web_src/css/base.css +++ b/web_src/css/base.css @@ -71,6 +71,7 @@ /* console colors */ --color-console-fg: #ffffff; --color-console-bg: #171717; + --color-console-hover-bg: #ffffff16; /* named colors */ --color-red: #db2828; --color-orange: #f2711c; diff --git a/web_src/js/components/ActionRunStatus.vue b/web_src/js/components/ActionRunStatus.vue index 0786cb60a9..bddf307a1b 100644 --- a/web_src/js/components/ActionRunStatus.vue +++ b/web_src/js/components/ActionRunStatus.vue @@ -1,14 +1,15 @@ <!-- This vue should be kept the same as templates/repo/actions/status.tmpl Please also update the template file above if this vue is modified. + action status accepted: success, skipped, waiting, blocked, running, failure, cancelled, unknown --> <template> - <span :data-tooltip-content="localeStatus" v-if="status"> + <span class="gt-df gt-ac" :data-tooltip-content="localeStatus" v-if="status"> <SvgIcon name="octicon-check-circle-fill" class="text green" :size="size" :class-name="className" v-if="status === 'success'"/> <SvgIcon name="octicon-skip" class="text grey" :size="size" :class-name="className" v-else-if="status === 'skipped'"/> <SvgIcon name="octicon-clock" class="text yellow" :size="size" :class-name="className" v-else-if="status === 'waiting'"/> <SvgIcon name="octicon-blocked" class="text yellow" :size="size" :class-name="className" v-else-if="status === 'blocked'"/> <SvgIcon name="octicon-meter" class="text yellow" :size="size" :class-name="'job-status-rotate ' + className" v-else-if="status === 'running'"/> - <SvgIcon name="octicon-x-circle-fill" class="text red" :size="size" v-else/> + <SvgIcon name="octicon-x-circle-fill" class="text red" :size="size" v-else-if="['failure', 'cancelled', 'unknown'].includes(status)" /> </span> </template> diff --git a/web_src/js/components/RepoActionView.vue b/web_src/js/components/RepoActionView.vue index 28adfbc6ec..b2fd63dd18 100644 --- a/web_src/js/components/RepoActionView.vue +++ b/web_src/js/components/RepoActionView.vue @@ -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"> - <ActionRunStatus :locale-status="locale.status[run.status]" :status="run.status" :size="20"/> - <div class="action-title"> - {{ run.title }} + <div class="action-info-summary-title"> + <ActionRunStatus :locale-status="locale.status[run.status]" :status="run.status" :size="20"/> + <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="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> + <span class="job-brief-info"> + <span class="step-summary-duration">{{ job.duration }}</span> + <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-title { + display: flex; } -.action-info-summary .action-title { - padding: 0 5px; +.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-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-group-section .job-brief-list .job-brief-item .job-brief-rerun { - float: right; - border: none; - background-color: transparent; - outline: none; +.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); |