ActionButton.js 2.9 KB

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