| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237 |
- import { ActionStatusDisplay } from './ActionStatusDisplay.js'
- import { OutputTerminal } from './OutputTerminal.js'
- // This ExecutionDialog is NOT a custom HTML element, but rather just picks up
- // the <dialog /> element out of index.html and just re-uses that - as only
- // one dialog can be shown at a time.
- export class ExecutionDialog {
- constructor () {
- this.dlg = document.querySelector('dialog#execution-results-popup')
- this.domIcon = document.getElementById('execution-dialog-icon')
- this.domTitle = document.getElementById('execution-dialog-title')
- this.domOutput = document.getElementById('execution-dialog-xterm')
- this.domOutputHtml = document.getElementById('execution-dialog-output-html')
- this.domOutputToggleBig = document.getElementById('execution-dialog-toggle-size')
- this.domOutputToggleBig.onclick = () => {
- this.toggleSize()
- }
- this.domBtnRerun = document.getElementById('execution-dialog-rerun-action')
- this.domBtnKill = document.getElementById('execution-dialog-kill-action')
- this.domDuration = document.getElementById('execution-dialog-duration')
- this.domStatus = new ActionStatusDisplay(document.getElementById('execution-dialog-status'))
- this.domExecutionBasics = document.getElementById('execution-dialog-basics')
- this.domExecutionDetails = document.getElementById('execution-dialog-details')
- window.terminal = new OutputTerminal()
- window.terminal.open(this.domOutput)
- window.terminal.resize(80, 24)
- }
- toggleSize () {
- if (this.dlg.classList.contains('big')) {
- this.dlg.classList.remove('big')
- window.terminal.resize(80, 24)
- } else {
- this.dlg.classList.add('big')
- window.terminal.fit()
- }
- }
- async reset () {
- this.executionSeconds = 0
- this.executionTrackingId = 'notset'
- this.dlg.classList.remove('big')
- this.domOutputToggleBig.hidden = false
- this.domIcon.innerText = ''
- this.domTitle.innerText = 'Waiting for result... '
- this.domDuration.innerText = ''
- // window.terminal.close()
- this.domBtnRerun.disabled = true
- this.domBtnRerun.onclick = () => {}
- this.domBtnKill.disabled = true
- this.domBtnKill.onclick = () => {}
- this.hideDetailsOnResult = false
- this.domExecutionBasics.hidden = false
- this.domExecutionDetails.hidden = true
- await window.terminal.reset()
- window.terminal.fit()
- }
- show (actionButton) {
- if (typeof actionButton !== 'undefined' && actionButton != null) {
- this.domIcon.innerText = actionButton.domIcon.innerText
- }
- this.domBtnKill.disabled = false
- this.domBtnKill.onclick = () => {
- this.killAction()
- }
- clearInterval(window.executionDialogTicker)
- this.executionSeconds = 0
- this.executionTick()
- window.executionDialogTicker = setInterval(() => {
- this.executionTick()
- }, 1000)
- if (this.dlg.open) {
- this.dlg.close()
- }
- this.dlg.showModal()
- }
- rerunAction (actionId) {
- const actionButton = document.getElementById('actionButton-' + actionId)
- if (actionButton !== undefined) {
- actionButton.btn.click()
- }
- this.dlg.close()
- }
- killAction () {
- const killActionArgs = {
- executionTrackingId: this.executionTrackingId
- }
- window.fetch(window.restBaseUrl + 'KillAction', {
- cors: 'cors',
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json'
- },
- body: JSON.stringify(killActionArgs)
- }).then((res) => {
- return res.json() // This isn't used by anything. UI is updated by OnExecutionFinished like normal.
- }).catch(err => {
- throw err
- })
- }
- executionTick () {
- this.executionSeconds++
- this.updateDuration(null)
- }
- hideEverythingApartFromOutput () {
- this.hideDetailsOnResult = true
- this.domExecutionBasics.hidden = true
- }
- fetchExecutionResult (executionTrackingId) {
- this.executionTrackingId = executionTrackingId
- const executionStatusArgs = {
- executionTrackingId: this.executionTrackingId
- }
- window.fetch(window.restBaseUrl + 'ExecutionStatus', {
- cors: 'cors',
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json'
- },
- body: JSON.stringify(executionStatusArgs)
- }).then((res) => {
- if (res.ok) {
- return res.json()
- } else if (res.status === 404) {
- throw new Error('Execution not found: ' + executionTrackingId)
- } else {
- throw new Error(res.statusText)
- }
- }
- ).then((json) => {
- this.renderExecutionResult(json)
- }).catch(err => {
- console.log(err)
- this.renderError(err)
- })
- }
- updateDuration (logEntry) {
- if (logEntry == null) {
- this.domDuration.innerHTML = this.executionSeconds + ' seconds'
- } else if (!logEntry.executionStarted) {
- this.domDuration.innerHTML = logEntry.datetimeStarted + ' (request time). Not executed.'
- } else if (logEntry.executionStarted && !logEntry.executionFinished) {
- this.domDuration.innerHTML = logEntry.datetimeStarted
- } else {
- let delta = ''
- try {
- delta = (new Date(logEntry.datetimeStarted) - new Date(logEntry.datetimeStarted)) / 1000
- delta = new Intl.RelativeTimeFormat().format(delta, 'seconds').replace('in ', '').replace('ago', '')
- } catch (e) {
- console.warn('Failed to calculate delta', e)
- }
- this.domDuration.innerHTML = logEntry.datetimeStarted + ' → ' + logEntry.datetimeFinished
- if (delta !== '') {
- this.domDuration.innerHTML += ' (' + delta + ')'
- }
- }
- }
- async renderExecutionResult (res) {
- this.res = res
- clearInterval(window.executionDialogTicker)
- if ('type' in res && res.type === 'execution-dialog-output-html') {
- this.domOutputHtml.hidden = false
- this.domOutput.hidden = true
- this.domOutputHtml.innerHTML = res.logEntry.output
- this.domOutputHtml.hidden = false
- this.hideDetailsonResult = true
- } else {
- this.domOutput.hidden = false
- this.domOutputHtml.innerHTML = ''
- this.domOutputHtml.hidden = true
- }
- if (this.hideDetailsOnResult) {
- this.domExecutionDetails.hidden = true
- }
- this.executionTrackingId = res.logEntry.executionTrackingId
- this.domBtnRerun.disabled = !res.logEntry.executionFinished
- this.domBtnRerun.onclick = () => { this.rerunAction(res.logEntry.actionId) }
- this.domBtnKill.disabled = !res.logEntry.canKill
- this.domStatus.update(res.logEntry)
- this.domIcon.innerHTML = res.logEntry.actionIcon
- this.domTitle.innerText = res.logEntry.actionTitle
- this.domTitle.title = 'Action ID: ' + res.logEntry.actionId + '\nExecution ID: ' + res.logEntry.executionTrackingId
- this.updateDuration(res.logEntry)
- await window.terminal.reset()
- await window.terminal.write(res.logEntry.output, () => {
- window.terminal.fit()
- })
- }
- renderError (err) {
- window.showBigError('execution-dlg-err', 'in the execution dialog', 'Failed to fetch execution result. ' + err, false)
- }
- }
|