Class: BoardsController

Inherits:
ApplicationController show all
Defined in:
app/controllers/boards_controller.rb

Instance Method Summary collapse

Instance Method Details

#archiveObject

The archive browser (card #42): everything archived, searchable, restorable.



69
70
71
72
# File 'app/controllers/boards_controller.rb', line 69

def archive
  @board = Board.first!
  @cards = @board.cards.archived.includes(:column).order(updated_at: :desc)
end

#briefObject

Inspect the repo brief: what the deep dive wrote, when, from which SHA.



75
76
77
78
79
80
# File 'app/controllers/boards_controller.rb', line 75

def brief
  @board = Board.first!
  redirect_to root_path and return unless turbo_frame_request?

  render :brief
end

#deep_diveObject

Kick off the repo deep dive (card #12). Non-blocking: flip the board into its "Working" state, morph the topbar so the button reflects it, and let DeepDiveJob do the read-only exploration in the background. Skipped when a dive is already running, or when the brief already matches HEAD — nothing changed, so a re-dive would just burn a run (the brief modal's Regenerate button passes force=1 to override).



12
13
14
15
16
17
18
19
20
21
# File 'app/controllers/boards_controller.rb', line 12

def deep_dive
  board = Board.first!
  fresh = board.brief? && board.commits_behind_brief == 0
  unless board.brief_working? || (fresh && params[:force].blank?)
    board.update!(brief_status: "working")
    board.broadcast_refresh_to board
    DeepDiveJob.perform_later(board)
  end
  redirect_to root_path
end

#editObject

Board settings gear (the board-level analog of the column gear): name and default branch — the branch agents fork from and Done merges toward.



25
26
27
28
# File 'app/controllers/boards_controller.rb', line 25

def edit
  @board = Board.first!
  redirect_to root_path and return unless turbo_frame_request?
end

#import_issueObject



60
61
62
63
64
65
66
# File 'app/controllers/boards_controller.rb', line 60

def import_issue
  board = Board.first!
  card = GithubIssues.import!(board, params.require(:number))
  redirect_to card_path(card)
rescue ArgumentError => e
  redirect_to root_path, alert: e.message
end

#issuesObject

GitHub Issues sync (card #49): list open issues, one click imports one as an inbox card; the card's eventual PR carries "Closes #N".



53
54
55
56
57
58
# File 'app/controllers/boards_controller.rb', line 53

def issues
  @board = Board.first!
  redirect_to root_path and return unless turbo_frame_request?
  @issues = GithubIssues.available?(@board) ? GithubIssues.list(@board) : []
  @imported = @board.cards.where.not(issue_number: nil).pluck(:issue_number, :number).to_h
end

#pullObject

Cards reaching Done merge PRs on GitHub, so the checkout Cardinal runs against falls behind. The topbar Pull button fast-forwards it. --ff-only on purpose: never invent merge commits or rebase local work — if the tree has diverged, say so and let the human sort it out in a real terminal.



86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'app/controllers/boards_controller.rb', line 86

def pull
  board = Board.first!
  message, ok = pull_repo(board)
  streams = [turbo_stream.update(
    "repo-pull-status",
    helpers.tag.span(message, class: ok ? "pull-ok" : "pull-err")
  )]
  if @pulled_commits
    # New code often means new JS (Stimulus controllers, importmap entries)
    # that an already-open tab will never fetch — Turbo morphs keep the page
    # alive on stale assets forever. A pull is a deliberate "give me the new
    # version", so finish the job with a full reload.
    streams << turbo_stream.append("repo-pull-status",
      helpers.tag.script("setTimeout(() => window.location.reload(), 1200)".html_safe))
  end
  render turbo_stream: streams
end

#showObject



2
3
4
# File 'app/controllers/boards_controller.rb', line 2

def show
  @board = Board.includes(columns: :cards).first!
end

#updateObject



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'app/controllers/boards_controller.rb', line 30

def update
  board = Board.first!
  attrs = params.require(:board).permit(:name, :default_branch, :permission_bypass, :permission_mode, archive_accepts_from: [])
  board.archive_accepts_from = attrs[:archive_accepts_from].to_a.map(&:to_s).reject(&:blank?) if attrs.key?(:archive_accepts_from)
  board.permission_bypass = (attrs[:permission_bypass] == "1") if attrs.key?(:permission_bypass)
  board.settings["permission_mode"] = attrs[:permission_mode].presence_in(Board::PERMISSION_MODES) if attrs.key?(:permission_mode)
  board.update!(
    name: attrs[:name].presence || board.name,
    default_branch: attrs[:default_branch].presence || board.default_branch
  )
  board.broadcast_refresh_to board
  if params[:autosave]
    render turbo_stream: [
      turbo_stream.update("board-name", board.name),
      turbo_stream.update("board-form-errors", "")
    ]
  else
    redirect_to root_path
  end
end