PageSourceSearch

https://golf4holland.nl/g4h_assets/controllers/background_job_cont…800c19d4351fd3bc5cd98afcef387ba598533da4.js

js golf4holland.nl collected 2026-09-24 10:57:52 UTC 3,674 bytes, 131 lines download raw bytes

1import { Controller } from "@hotwired/stimulus"
2
3export default class extends Controller {
4  static targets = ["button", "progress", "bar", "message"]
5  static values = {
6    url: String,
7    label: String
8  }
9
10  connect() {
11    this.pollTimer = null
12    this.originallyDisabled = this.hasButtonTarget && this.buttonTarget.disabled
13  }
14
15  disconnect() {
16    this.stopPolling()
17  }
18
19  async start(event) {
20    event.preventDefault()
21    if (this.pollTimer) return
22    if (this.hasButtonTarget && this.buttonTarget.disabled) return
23
24    this.setRunningState()
25    try {
26      const response = await fetch(this.urlValue, {
27        method: "POST",
28        headers: this.requestHeaders(),
29        credentials: "same-origin"
30      })
31      if (!response.ok) throw new Error(`Request failed (${response.status})`)
32
33      const data = await response.json()
34      this.pollUrl = data.poll_url
35      this.startPolling()
36    } catch (error) {
37      this.resetButton()
38      this.showMessage(this.errorText())
39      console.error("Background job start failed:", error)
40    }
41  }
42
43  startPolling() {
44    this.pollTimer = setInterval(() => this.poll(), 1000)
45    this.poll()
46  }
47
48  stopPolling() {
49    if (this.pollTimer) {
50      clearInterval(this.pollTimer)
51      this.pollTimer = null
52    }
53  }
54
55  async poll() {
56    try {
57      const response = await fetch(this.pollUrl, {
58        headers: { Accept: "application/json" },
59        credentials: "same-origin"
60      })
61      if (!response.ok) throw new Error(`Poll failed (${response.status})`)
62
63      const status = await response.json()
64      this.updateProgress(status.progress, status.message)
65
66      if (status.status === "completed") {
67        this.stopPolling()
68        this.resetButton()
69        if (status.download_url) {
70          window.location.href = status.download_url
71        } else if (status.redirect_url) {
72          window.location.href = status.redirect_url
73        }
74      } else if (status.status === "failed") {
75        this.stopPolling()
76        this.resetButton()
77        this.showMessage(status.message || this.errorText())
78      }
79    } catch (error) {
80      this.stopPolling()
81      this.resetButton()
82      this.showMessage(this.errorText())
83      console.error("Background job poll failed:", error)
84    }
85  }
86
87  setRunningState() {
88    if (this.hasProgressTarget) this.progressTarget.classList.remove("hidden")
89    if (this.hasButtonTarget) {
90      this.buttonTarget.disabled = true
91      this.buttonTarget.textContent = this.runningText()
92    }
93    this.updateProgress(0, null)
94  }
95
96  resetButton() {
97    if (this.hasProgressTarget) this.progressTarget.classList.add("hidden")
98    if (this.hasButtonTarget) {
99      this.buttonTarget.disabled = this.originallyDisabled
100      this.buttonTarget.textContent = this.labelValue
101    }
102    if (this.hasMessageTarget) this.messageTarget.textContent = ""
103  }
104
105  updateProgress(progress, message) {
106    if (this.hasBarTarget) this.barTarget.style.width = `${progress || 0}%`
107    if (this.hasMessageTarget && message) this.messageTarget.textContent = message
108  }
109
110  showMessage(text) {
111    if (this.hasMessageTarget) this.messageTarget.textContent = text
112  }
113
114  requestHeaders() {
115    const headers = {
116      Accept: "application/json",
117      "X-Requested-With": "XMLHttpRequest"
118    }
119    const token = document.querySelector('meta[name="csrf-token"]')?.content
120    if (token) headers["X-CSRF-Token"] = token
121    return headers
122  }
123
124  runningText() {
125    return this.element.dataset.backgroundJobRunningTextValue || "Export in progress..."
126  }
127
128  errorText() {
129    return this.element.dataset.backgroundJobErrorTextValue || "Export failed. Please try again."
130  }
131};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.