ActionButton.js 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. import { marshalLogsJsonToHtml } from './marshaller.js'
  2. import './ArgumentForm.js'
  3. class ActionButton extends window.HTMLElement {
  4. constructFromJson (json) {
  5. this.updateIterationTimestamp = 0
  6. this.constructDomFromTemplate()
  7. // DOM Attributes
  8. this.btn.title = json.title
  9. this.btn.onclick = () => { this.startAction() }
  10. // Class attributes
  11. this.actionCallUrl = window.restBaseUrl + 'StartAction?actionName=' + json.title
  12. this.temporaryStatusMessage = null
  13. this.isWaiting = false
  14. this.actionCallUrl = window.restBaseUrl + 'StartAction'
  15. this.updateFromJson(json)
  16. this.onclick = () => {
  17. if (json.arguments.length > 0) {
  18. const frm = document.createElement('form', { is: 'argument-form' })
  19. frm.setup(json, (args) => {
  20. this.startAction(args)
  21. })
  22. document.body.appendChild(frm)
  23. } else {
  24. this.startAction()
  25. }
  26. }
  27. this.constructTemplate()
  28. this.updateHtml()
  29. =======
  30. this.updateFromJson(json)
  31. this.updateDom()
  32. >>>>>>> 40cfb1f (progress so far)
  33. this.setAttribute('id', 'actionButton_' + json.id)
  34. }
  35. updateFromJson (json) {
  36. // Fields that should not be updated
  37. //
  38. // title - as the callback URL relies on it
  39. // actionCallbackUrl - as it's based on the title
  40. // temporaryStatusMessage - as the button might be "waiting" on execution to finish while it's being updated.
  41. if (json.icon === '') {
  42. this.unicodeIcon = '&#x1f4a9'
  43. } else {
  44. this.unicodeIcon = unescape(json.icon)
  45. }
  46. }
  47. startAction (actionArgs) {
  48. this.btn.disabled = true
  49. this.isWaiting = true
  50. this.updateDom()
  51. this.btn.classList = [] // Removes old animation classes
  52. if (actionArgs === undefined) {
  53. actionArgs = []
  54. }
  55. const startActionArgs = {
  56. actionName: this.title,
  57. arguments: actionArgs
  58. }
  59. window.fetch(this.actionCallUrl, {
  60. method: 'POST',
  61. headers: {
  62. 'Content-Type': 'application/json'
  63. },
  64. body: JSON.stringify(startActionArgs)
  65. }).then((res) => {
  66. if (res.ok) {
  67. return res.json()
  68. } else {
  69. throw new Error(res.statusText)
  70. }
  71. }
  72. ).then((json) => {
  73. marshalLogsJsonToHtml({ logs: [json.logEntry] })
  74. if (json.logEntry.timedOut) {
  75. this.onActionResult('actionTimeout', 'Timed out')
  76. } else if (json.logEntry.exitCode === -1337) {
  77. this.onActionError('Error')
  78. } else if (json.logEntry.exitCode !== 0) {
  79. this.onActionResult('actionNonZeroExit', 'Exit code ' + json.logEntry.exitCode)
  80. } else {
  81. this.onActionResult('actionSuccess', 'Success!')
  82. }
  83. }).catch(err => {
  84. this.onActionError(err)
  85. })
  86. }
  87. onActionResult (cssClass, temporaryStatusMessage) {
  88. this.temporaryStatusMessage = '[ ' + temporaryStatusMessage + ' ]'
  89. this.updateDom()
  90. this.btn.classList.add(cssClass)
  91. setTimeout(() => {
  92. this.btn.classList.remove(cssClass)
  93. }, 1000);
  94. }
  95. onActionError (err) {
  96. console.log('callback error', err)
  97. this.btn.disabled = false
  98. this.isWaiting = false
  99. this.updateDom()
  100. this.btn.classList.add('actionFailed')
  101. setTimeout(() => {
  102. this.btn.classList.remove('actionFailed')
  103. }, 1000);
  104. }
  105. constructDomFromTemplate () {
  106. const tpl = document.getElementById('tplActionButton')
  107. const content = tpl.content.cloneNode(true)
  108. /*
  109. * FIXME: Should probably be using a shadowdom here, but seem to
  110. * get an error when combined with custom elements.
  111. */
  112. this.appendChild(content)
  113. this.btn = this.querySelector('button')
  114. this.domTitle = this.btn.querySelector('.title')
  115. this.domIcon = this.btn.querySelector('.icon')
  116. }
  117. updateDom () {
  118. console.log(this.querySelector("button"))
  119. if (this.temporaryStatusMessage != null) {
  120. this.domTitle.innerText = this.temporaryStatusMessage
  121. this.domTitle.classList.add('temporaryStatusMessage')
  122. this.isWaiting = false
  123. this.disabled = false
  124. setTimeout(() => {
  125. this.temporaryStatusMessage = null
  126. this.domTitle.classList.remove('temporaryStatusMessage')
  127. this.updateDom()
  128. }, 2000)
  129. } else if (this.isWaiting) {
  130. this.domTitle.innerText = 'Waiting...'
  131. } else {
  132. this.domTitle.innerText = this.btn.title
  133. }
  134. this.domIcon.innerHTML = this.unicodeIcon
  135. }
  136. }
  137. window.customElements.define('action-button', ActionButton)