launchpad.ts 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. import '@/marketing'
  2. import {
  3. inflightHelper,
  4. toggleDisplay,
  5. } from '@/features/form-helpers/hydrate-form'
  6. import getMeta from '@/utils/meta'
  7. import { Socket } from '@/features/ide-react/connection/types/socket'
  8. declare const io: {
  9. connect: (url: string | null, options?: Record<string, unknown>) => Socket
  10. }
  11. interface ConnectionRejectedError {
  12. code?: string
  13. message?: string
  14. }
  15. function setUpStatusIndicator(el: HTMLElement, fn: () => Promise<void>) {
  16. inflightHelper(el)
  17. const displaySuccess = el.querySelectorAll<HTMLElement>(
  18. '[data-ol-result="success"]'
  19. )
  20. const displayError = el.querySelectorAll<HTMLElement>(
  21. '[data-ol-result="error"]'
  22. )
  23. // The checks are very lightweight and do not appear to do anything
  24. // from looking at the UI. Add an artificial delay of 1s to show that
  25. // we are actually doing something. :)
  26. const artificialProgressDelay = 1000
  27. function run() {
  28. setTimeout(() => {
  29. fn()
  30. .then(() => {
  31. toggleDisplay(displayError, displaySuccess)
  32. })
  33. .catch(error => {
  34. const errorElement = el.querySelector('[data-ol-error]')
  35. if (errorElement) {
  36. errorElement.textContent = error.message
  37. }
  38. toggleDisplay(displaySuccess, displayError)
  39. })
  40. .finally(() => {
  41. el.dispatchEvent(new Event('idle'))
  42. })
  43. }, artificialProgressDelay)
  44. }
  45. el.querySelectorAll('button').forEach(retryBtn => {
  46. retryBtn.addEventListener('click', function (e) {
  47. e.preventDefault()
  48. el.dispatchEvent(new Event('pending'))
  49. run()
  50. })
  51. })
  52. run()
  53. }
  54. function setUpStatusIndicators() {
  55. const launchpadCheckElement = document.querySelector<HTMLElement>(
  56. '[data-ol-launchpad-check="websocket"]'
  57. )
  58. if (!launchpadCheckElement) {
  59. return
  60. }
  61. setUpStatusIndicator(launchpadCheckElement, () => {
  62. const timeout = 10 * 1000
  63. const socket = io.connect(null, {
  64. reconnect: false,
  65. 'connect timeout': timeout,
  66. 'force new connection': true,
  67. query: new URLSearchParams({
  68. projectId: '404404404404404404404404',
  69. }).toString(),
  70. })
  71. return new Promise<void>((resolve, reject) => {
  72. setTimeout(() => reject(new Error('timed out')), timeout)
  73. socket.on('connectionRejected', function (err?: ConnectionRejectedError) {
  74. if (err?.code === 'ProjectNotFound') {
  75. // We received the response from joinProject, so the websocket is up.
  76. resolve()
  77. } else {
  78. reject(new Error(err && err.message))
  79. }
  80. })
  81. socket.on('connect_failed', function (err?: Error) {
  82. reject(new Error(err && err.message))
  83. })
  84. }).finally(() => {
  85. socket.disconnect()
  86. })
  87. })
  88. }
  89. if (getMeta('ol-adminUserExists')) {
  90. setUpStatusIndicators()
  91. }