diff --git a/app/controllers/data_drip/backfill_runs_controller.rb b/app/controllers/data_drip/backfill_runs_controller.rb index be4501f..cc076ae 100644 --- a/app/controllers/data_drip/backfill_runs_controller.rb +++ b/app/controllers/data_drip/backfill_runs_controller.rb @@ -160,7 +160,7 @@ def backfill_options if backfill_class_name.blank? || backfill_class_name == "Select a backfill class" - render json: { html: "" } + render json: { html: "", instructions: nil } return end @@ -168,7 +168,7 @@ def backfill_options DataDrip.all.find { |klass| klass.name == backfill_class_name } if backfill_class.nil? - render json: { html: "" } + render json: { html: "", instructions: nil } return end @@ -180,8 +180,9 @@ def backfill_options ) html = helpers.backfill_option_inputs(temp_run) + instructions = backfill_class.instructions - render json: { html: html } + render json: { html: html, instructions: instructions } end def find_current_backfiller diff --git a/app/javascript/data_drip/controllers/backfill_form_controller.js b/app/javascript/data_drip/controllers/backfill_form_controller.js new file mode 100644 index 0000000..9e13004 --- /dev/null +++ b/app/javascript/data_drip/controllers/backfill_form_controller.js @@ -0,0 +1,67 @@ +import { Controller } from "@hotwired/stimulus" +import { renderInstructions } from "markdown" + +// Drives the "New Backfill Run" form: +// - captures the browser timezone into a hidden field +// - when a backfill class is picked, fetches its option inputs + instructions +// and renders them +// - disables the submit button while the form is being submitted +export default class extends Controller { + static targets = ["classInput", "optionsContainer", "instructionsContainer", "timezone", "submit"] + static values = { optionsUrl: String } + + connect() { + if (this.hasTimezoneTarget) { + this.timezoneTarget.value = Intl.DateTimeFormat().resolvedOptions().timeZone + } + } + + classChanged() { + const selectedClass = this.classInputTarget.value + + this.optionsContainerTarget.innerHTML = "" + if (this.hasInstructionsContainerTarget) this.instructionsContainerTarget.innerHTML = "" + + if (!selectedClass || selectedClass === "Select a backfill class") return + + fetch(`${this.optionsUrlValue}?backfill_class_name=${encodeURIComponent(selectedClass)}`, { + method: "GET", + headers: { + Accept: "application/json", + "X-Requested-With": "XMLHttpRequest", + "X-CSRF-Token": document.querySelector('meta[name="csrf-token"]')?.getAttribute("content") + } + }) + .then((response) => { + if (!response.ok) throw new Error(`Network response was not ok: ${response.status}`) + return response.json() + }) + .then((data) => { + if (data.instructions && this.hasInstructionsContainerTarget) { + this.instructionsContainerTarget.innerHTML = + '
$1')
+}
+
+export function renderInstructions(text) {
+ const lines = text.split("\n")
+ let html = ""
+ let inList = false
+ let inCodeBlock = false
+ let codeLines = []
+
+ for (let i = 0; i < lines.length; i++) {
+ const line = lines[i]
+
+ if (line.trim().match(/^```/)) {
+ if (inCodeBlock) {
+ html += '' + esc(codeLines.join("\n")) + ""
+ codeLines = []
+ inCodeBlock = false
+ } else {
+ if (inList) { html += ""; inList = false }
+ inCodeBlock = true
+ }
+ continue
+ }
+
+ if (inCodeBlock) {
+ codeLines.push(line)
+ continue
+ }
+
+ if (line.trim() === "") {
+ if (inList) { html += ""; inList = false }
+ html += ''
+ continue
+ }
+
+ const headerMatch = line.match(/^(#{1,3})\s+(.+)$/)
+ if (headerMatch) {
+ if (inList) { html += ""; inList = false }
+ const level = headerMatch[1].length
+ const style = level === 1
+ ? "font-size:15px;font-weight:600;color:#1e3a5f;margin-bottom:2px"
+ : level === 2
+ ? "font-size:13px;font-weight:600;color:#2563eb;margin-bottom:2px;text-transform:uppercase;letter-spacing:0.03em"
+ : "font-size:13px;font-weight:500;color:#475569;margin-bottom:2px"
+ html += '' + inlineFormat(esc(line)) + "
" + } + + if (inList) html += "" + return html +} diff --git a/app/views/data_drip/backfill_runs/new.html.erb b/app/views/data_drip/backfill_runs/new.html.erb index e1b7c65..8dba370 100644 --- a/app/views/data_drip/backfill_runs/new.html.erb +++ b/app/views/data_drip/backfill_runs/new.html.erb @@ -1,7 +1,7 @@