ActionButton.js 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. class ActionButton extends window.HTMLButtonElement {
  2. constructFromJson (json) {
  3. this.updateIterationTimestamp = 0;
  4. this.title = json.title
  5. this.temporaryStatusMessage = null
  6. this.isWaiting = false
  7. this.actionCallUrl = window.restBaseUrl + 'StartAction?actionName=' + this.title
  8. this.updateFromJson(json)
  9. this.onclick = () => { this.startAction() }
  10. this.constructTemplate()
  11. this.updateHtml()
  12. this.setAttribute("id", "actionButton_" + json.id)
  13. }
  14. updateFromJson (json) {
  15. // Fields that should not be updated
  16. //
  17. // title - as the callback URL relies on it
  18. // actionCallbackUrl - as it's based on the title
  19. // temporaryStatusMessage - as the button might be "waiting" on execution to finish while it's being updated.
  20. if (json.icon === '') {
  21. this.unicodeIcon = '&#x1f4a9'
  22. } else {
  23. this.unicodeIcon = unescape(json.icon)
  24. }
  25. }
  26. startAction () {
  27. this.disabled = true
  28. this.isWaiting = true
  29. this.updateHtml()
  30. this.classList = [] // Removes old animation classes
  31. window.fetch(this.actionCallUrl).then(res => res.json()
  32. ).then((json) => {
  33. if (json.timedOut) {
  34. this.onActionResult('actionTimeout', 'Timed out')
  35. } else if (json.exitCode !== 0) {
  36. this.onActionResult('actionNonZeroExit', 'Exit code ' + json.exitCode)
  37. } else {
  38. this.onActionResult('actionSuccess', 'Success!')
  39. }
  40. }).catch(err => {
  41. this.onActionError(err)
  42. })
  43. }
  44. onActionResult (cssClass, temporaryStatusMessage) {
  45. this.temporaryStatusMessage = '[ ' + temporaryStatusMessage + ' ]'
  46. this.updateHtml()
  47. this.classList.add(cssClass)
  48. }
  49. onActionError (err) {
  50. console.log('callback error', err)
  51. this.disabled = false
  52. this.isWaiting = false
  53. this.updateHtml()
  54. this.classList.add('actionFailed')
  55. }
  56. constructTemplate () {
  57. const tpl = document.getElementById('tplActionButton')
  58. const content = tpl.content.cloneNode(true)
  59. /*
  60. * FIXME: Should probably be using a shadowdom here, but seem to
  61. * get an error when combined with custom elements.
  62. */
  63. this.appendChild(content)
  64. this.domTitle = this.querySelector('.title')
  65. this.domIcon = this.querySelector('.icon')
  66. }
  67. updateHtml () {
  68. if (this.temporaryStatusMessage != null) {
  69. this.domTitle.innerText = this.temporaryStatusMessage
  70. this.domTitle.classList.add('temporaryStatusMessage')
  71. this.isWaiting = false
  72. this.disabled = false
  73. setTimeout(() => {
  74. this.temporaryStatusMessage = null
  75. this.domTitle.classList.remove('temporaryStatusMessage')
  76. this.updateHtml()
  77. }, 2000)
  78. } else if (this.isWaiting) {
  79. this.domTitle.innerText = 'Waiting...'
  80. } else {
  81. this.domTitle.innerText = this.title
  82. }
  83. this.domIcon.innerHTML = this.unicodeIcon
  84. }
  85. }
  86. window.customElements.define('action-button', ActionButton, { extends: 'button' })