mirror of
				https://github.com/go-gitea/gitea
				synced 2025-10-31 03:18:24 +00:00 
			
		
		
		
	Add log line anchor for action logs (#25532)
Close #24593 Some behavior: - If log step line in hash exists, expand the step and scroll to the log line. - If step exists but line not exists, the step will be expanded. - If step not exists, stays on the job's page. Some Notes: - Changed mounted to async because need to await for first `loadJob` so `currentJobStepsStates` can be initialized and used in `hashChangeListener `. --------- Co-authored-by: silverwind <me@silverwind.io> Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
		| @@ -204,15 +204,19 @@ const sfc = { | |||||||
|     }; |     }; | ||||||
|   }, |   }, | ||||||
|  |  | ||||||
|   mounted() { |   async mounted() { | ||||||
|     // load job data and then auto-reload periodically |     // load job data and then auto-reload periodically | ||||||
|     this.loadJob(); |     // need to await first loadJob so this.currentJobStepsStates is initialized and can be used in hashChangeListener | ||||||
|  |     await this.loadJob(); | ||||||
|     this.intervalID = setInterval(this.loadJob, 1000); |     this.intervalID = setInterval(this.loadJob, 1000); | ||||||
|     document.body.addEventListener('click', this.closeDropdown); |     document.body.addEventListener('click', this.closeDropdown); | ||||||
|  |     this.hashChangeListener(); | ||||||
|  |     window.addEventListener('hashchange', this.hashChangeListener); | ||||||
|   }, |   }, | ||||||
|  |  | ||||||
|   beforeUnmount() { |   beforeUnmount() { | ||||||
|     document.body.removeEventListener('click', this.closeDropdown); |     document.body.removeEventListener('click', this.closeDropdown); | ||||||
|  |     window.removeEventListener('hashchange', this.hashChangeListener); | ||||||
|   }, |   }, | ||||||
|  |  | ||||||
|   unmounted() { |   unmounted() { | ||||||
| @@ -280,14 +284,16 @@ const sfc = { | |||||||
|       this.fetchPost(`${this.run.link}/approve`); |       this.fetchPost(`${this.run.link}/approve`); | ||||||
|     }, |     }, | ||||||
|  |  | ||||||
|     createLogLine(line, startTime) { |     createLogLine(line, startTime, stepIndex) { | ||||||
|       const div = document.createElement('div'); |       const div = document.createElement('div'); | ||||||
|       div.classList.add('job-log-line'); |       div.classList.add('job-log-line'); | ||||||
|  |       div.setAttribute('id', `jobstep-${stepIndex}-${line.index}`); | ||||||
|       div._jobLogTime = line.timestamp; |       div._jobLogTime = line.timestamp; | ||||||
|  |  | ||||||
|       const lineNumber = document.createElement('div'); |       const lineNumber = document.createElement('a'); | ||||||
|       lineNumber.className = 'line-num'; |       lineNumber.classList.add('line-num', 'muted'); | ||||||
|       lineNumber.textContent = line.index; |       lineNumber.textContent = line.index; | ||||||
|  |       lineNumber.setAttribute('href', `#jobstep-${stepIndex}-${line.index}`); | ||||||
|       div.append(lineNumber); |       div.append(lineNumber); | ||||||
|  |  | ||||||
|       // for "Show timestamps" |       // for "Show timestamps" | ||||||
| @@ -318,7 +324,7 @@ const sfc = { | |||||||
|       for (const line of logLines) { |       for (const line of logLines) { | ||||||
|         // TODO: group support: ##[group]GroupTitle , ##[endgroup] |         // TODO: group support: ##[group]GroupTitle , ##[endgroup] | ||||||
|         const el = this.getLogsContainer(stepIndex); |         const el = this.getLogsContainer(stepIndex); | ||||||
|         el.append(this.createLogLine(line, startTime)); |         el.append(this.createLogLine(line, startTime, stepIndex)); | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|  |  | ||||||
| @@ -429,6 +435,21 @@ const sfc = { | |||||||
|       } else { |       } else { | ||||||
|         actionBodyEl.append(fullScreenEl); |         actionBodyEl.append(fullScreenEl); | ||||||
|       } |       } | ||||||
|  |     }, | ||||||
|  |     async hashChangeListener() { | ||||||
|  |       const selectedLogStep = window.location.hash; | ||||||
|  |       if (!selectedLogStep) return; | ||||||
|  |       const [_, step, _line] = selectedLogStep.split('-'); | ||||||
|  |       if (!this.currentJobStepsStates[step]) return; | ||||||
|  |       if (!this.currentJobStepsStates[step].expanded && this.currentJobStepsStates[step].cursor === null) { | ||||||
|  |         this.currentJobStepsStates[step].expanded = true; | ||||||
|  |         // need to await for load job if the step log is loaded for the first time | ||||||
|  |         // so logline can be selected by querySelector | ||||||
|  |         await this.loadJob(); | ||||||
|  |       } | ||||||
|  |       const logLine = this.$refs.steps.querySelector(selectedLogStep); | ||||||
|  |       if (!logLine) return; | ||||||
|  |       logLine.querySelector('.line-num').click(); | ||||||
|     } |     } | ||||||
|   }, |   }, | ||||||
| }; | }; | ||||||
| @@ -802,10 +823,15 @@ export function initRepositoryActionView() { | |||||||
|   display: flex; |   display: flex; | ||||||
| } | } | ||||||
|  |  | ||||||
| .job-step-section .job-step-logs .job-log-line:hover { | .job-log-line:hover, | ||||||
|  | .job-log-line:target { | ||||||
|   background-color: var(--color-console-hover-bg); |   background-color: var(--color-console-hover-bg); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | .job-log-line:target { | ||||||
|  |   scroll-margin-top: 95px; | ||||||
|  | } | ||||||
|  |  | ||||||
| /* class names 'log-time-seconds' and 'log-time-stamp' are used in the method toggleTimeDisplay */ | /* class names 'log-time-seconds' and 'log-time-stamp' are used in the method toggleTimeDisplay */ | ||||||
| .job-log-line .line-num, .log-time-seconds { | .job-log-line .line-num, .log-time-seconds { | ||||||
|   width: 48px; |   width: 48px; | ||||||
| @@ -814,6 +840,11 @@ export function initRepositoryActionView() { | |||||||
|   user-select: none; |   user-select: none; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | .job-log-line:target > .line-num { | ||||||
|  |   color: var(--color-primary); | ||||||
|  |   text-decoration: underline; | ||||||
|  | } | ||||||
|  |  | ||||||
| .log-time-seconds { | .log-time-seconds { | ||||||
|   padding-right: 2px; |   padding-right: 2px; | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user