Class: ActiveCanvas::Admin::SettingsController

Inherits:
ActiveCanvas::ApplicationController show all
Defined in:
app/controllers/active_canvas/admin/settings_controller.rb

Instance Method Summary collapse

Instance Method Details

#bulk_toggle_ai_modelsObject



181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
# File 'app/controllers/active_canvas/admin/settings_controller.rb', line 181

def bulk_toggle_ai_models
  action = params[:action_type]
  scope = params[:scope]
  provider = params[:provider]

  models = AiModel.all
  models = models.where(provider: provider) if provider.present?
  models = models.where(model_type: scope) if scope.present? && scope != "all"

  case action
  when "activate"
    count = models.update_all(active: true)
    message = "Activated #{count} models."
  when "deactivate"
    count = models.update_all(active: false)
    message = "Deactivated #{count} models."
  else
    message = "Invalid action."
  end

  respond_to do |format|
    format.html { redirect_to admin_settings_path(tab: "models"), notice: message }
    format.json { render json: { success: true, count: count, message: message } }
  end
end

#create_ai_modelObject



139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
# File 'app/controllers/active_canvas/admin/settings_controller.rb', line 139

def create_ai_model
  model = AiModel.new(
    model_id: params[:model_id],
    provider: params[:provider],
    model_type: params[:model_type],
    name: params[:name],
    context_window: params[:context_window].presence,
    max_tokens: params[:max_tokens].presence,
    supports_functions: params[:supports_functions] == "1",
    active: params[:active] != "0",
    input_modalities: Array(params[:input_modalities]).reject(&:blank?),
    output_modalities: Array(params[:output_modalities]).reject(&:blank?)
  )

  if model.save
    respond_to do |format|
      format.html { redirect_to admin_settings_path(tab: "models"), notice: "Model '#{model.display_name}' added." }
      format.json { render json: { success: true, model: model.as_json_for_editor } }
    end
  else
    respond_to do |format|
      format.html { redirect_to admin_settings_path(tab: "models"), alert: model.errors.full_messages.to_sentence }
      format.json { render json: { success: false, errors: model.errors.full_messages }, status: :unprocessable_entity }
    end
  end
end

#destroy_ai_modelObject



166
167
168
169
170
171
172
173
174
175
176
177
178
179
# File 'app/controllers/active_canvas/admin/settings_controller.rb', line 166

def destroy_ai_model
  model = AiModel.find(params[:model_id])
  model.destroy!

  respond_to do |format|
    format.html { redirect_to admin_settings_path(tab: "models"), notice: "Model '#{model.display_name}' removed." }
    format.json { render json: { success: true } }
  end
rescue ActiveRecord::RecordNotFound
  respond_to do |format|
    format.html { redirect_to admin_settings_path(tab: "models"), alert: "Model not found." }
    format.json { render json: { success: false, error: "Model not found" }, status: :not_found }
  end
end

#recompile_tailwindObject



227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
# File 'app/controllers/active_canvas/admin/settings_controller.rb', line 227

def recompile_tailwind
  unless ActiveCanvas::TailwindCompiler.available?
    respond_to do |format|
      format.html { redirect_to admin_settings_path(tab: "styles"), alert: "tailwindcss-ruby gem is not installed." }
      format.json { render json: { success: false, error: "tailwindcss-ruby gem is not installed." }, status: :unprocessable_entity }
    end
    return
  end

  unless Setting.css_framework == "tailwind"
    respond_to do |format|
      format.html { redirect_to admin_settings_path(tab: "styles"), alert: "Tailwind is not the selected CSS framework." }
      format.json { render json: { success: false, error: "Tailwind is not the selected CSS framework." }, status: :unprocessable_entity }
    end
    return
  end

  pages = Page.where.not(content: [nil, ""])
  pages.find_each do |page|
    CompileTailwindJob.perform_later(page.id)
  end

  respond_to do |format|
    format.html { redirect_to admin_settings_path(tab: "styles"), notice: "Queued #{pages.count} pages for Tailwind compilation." }
    format.json { render json: { success: true, count: pages.count, message: "Queued #{pages.count} pages for compilation." } }
  end
end

#showObject



4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'app/controllers/active_canvas/admin/settings_controller.rb', line 4

def show
  @active_tab = params[:tab] || "general"
  @homepage_page_id = Setting.homepage_page_id
  @css_framework = Setting.css_framework
  @global_css = Setting.global_css
  @global_js = Setting.global_js
  @pages = Page.published.order(:title)

  # Tailwind settings
  @tailwind_config = Setting.tailwind_config_js
  @tailwind_available = ActiveCanvas::TailwindCompiler.available?
  @tailwind_compiled_mode = Setting.tailwind_compiled_mode?

  # AI settings - use masked values for display
  @ai_openai_key = Setting.masked_api_key("ai_openai_api_key")
  @ai_anthropic_key = Setting.masked_api_key("ai_anthropic_api_key")
  @ai_openrouter_key = Setting.masked_api_key("ai_openrouter_api_key")
  @ai_openai_configured = Setting.api_key_configured?("ai_openai_api_key")
  @ai_anthropic_configured = Setting.api_key_configured?("ai_anthropic_api_key")
  @ai_openrouter_configured = Setting.api_key_configured?("ai_openrouter_api_key")
  @ai_default_text_model = Setting.ai_default_text_model
  @ai_default_image_model = Setting.ai_default_image_model
  @ai_text_enabled = Setting.ai_text_enabled?
  @ai_image_enabled = Setting.ai_image_enabled?
  @ai_screenshot_enabled = Setting.ai_screenshot_enabled?

  # Model sync info
  @ai_models_synced = AiModels.models_synced?
  @ai_models_last_synced = AiModels.last_synced_at
  @ai_models_count = AiModel.count if @ai_models_synced
  @ai_default_vision_model = Setting.ai_default_vision_model
  @ai_connection_mode = Setting.ai_connection_mode
  @ai_text_models = AiModels.all_text_models
  @ai_image_models = AiModels.all_image_models
  @ai_vision_models = AiModels.all_vision_models

  # Models tab - models from configured providers only
  if @active_tab == "models"
    configured_providers = AiConfiguration.configured_providers
    @all_models_by_provider = AiModel
      .where(provider: configured_providers)
      .order(:provider, :model_type, :name)
      .group_by(&:provider)
  end
end

#sync_ai_modelsObject



99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'app/controllers/active_canvas/admin/settings_controller.rb', line 99

def sync_ai_models
  unless AiConfiguration.configured?
    respond_to do |format|
      format.html { redirect_to admin_settings_path(tab: "ai"), alert: "Please configure at least one API key first." }
      format.json { render json: { success: false, error: "Not configured" }, status: :unprocessable_entity }
    end
    return
  end

  begin
    count = AiModels.refresh!

    respond_to do |format|
      format.html { redirect_to admin_settings_path(tab: "ai"), notice: "Synced #{count} models from providers." }
      format.json { render json: { success: true, count: count, message: "Synced #{count} models." } }
    end
  rescue => e
    Rails.logger.error "AI Model Sync Error: #{e.message}"
    respond_to do |format|
      format.html { redirect_to admin_settings_path(tab: "ai"), alert: "Failed to sync models: #{e.message}" }
      format.json { render json: { success: false, error: e.message }, status: :unprocessable_entity }
    end
  end
end

#toggle_ai_modelObject



124
125
126
127
128
129
130
131
132
133
134
135
136
137
# File 'app/controllers/active_canvas/admin/settings_controller.rb', line 124

def toggle_ai_model
  model = AiModel.find(params[:model_id])
  model.update!(active: !model.active)

  respond_to do |format|
    format.html { redirect_to admin_settings_path(tab: "models"), notice: "#{model.display_name} #{model.active? ? 'activated' : 'deactivated'}." }
    format.json { render json: { success: true, active: model.active, model_id: model.id } }
  end
rescue ActiveRecord::RecordNotFound
  respond_to do |format|
    format.html { redirect_to admin_settings_path(tab: "models"), alert: "Model not found." }
    format.json { render json: { success: false, error: "Model not found" }, status: :not_found }
  end
end

#updateObject



50
51
52
53
54
# File 'app/controllers/active_canvas/admin/settings_controller.rb', line 50

def update
  Setting.homepage_page_id = params[:homepage_page_id]

  redirect_to admin_settings_path, notice: "Settings saved successfully."
end

#update_aiObject



74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'app/controllers/active_canvas/admin/settings_controller.rb', line 74

def update_ai
  # API Keys - only update if a new value is provided (not empty, not masked)
  update_api_key("ai_openai_api_key", params[:ai_openai_api_key])
  update_api_key("ai_anthropic_api_key", params[:ai_anthropic_api_key])
  update_api_key("ai_openrouter_api_key", params[:ai_openrouter_api_key])

  # Default models
  Setting.ai_default_text_model = params[:ai_default_text_model] if params.key?(:ai_default_text_model)
  Setting.ai_default_image_model = params[:ai_default_image_model] if params.key?(:ai_default_image_model)
  Setting.ai_default_vision_model = params[:ai_default_vision_model] if params.key?(:ai_default_vision_model)

  # Connection mode
  Setting.ai_connection_mode = params[:ai_connection_mode] if params.key?(:ai_connection_mode)

  # Feature toggles
  Setting.ai_text_enabled = params[:ai_text_enabled] == "1"
  Setting.ai_image_enabled = params[:ai_image_enabled] == "1"
  Setting.ai_screenshot_enabled = params[:ai_screenshot_enabled] == "1"

  respond_to do |format|
    format.html { redirect_to admin_settings_path(tab: "ai"), notice: "AI settings saved." }
    format.json { render json: { success: true, message: "AI settings saved." } }
  end
end

#update_global_cssObject



56
57
58
59
60
61
62
63
# File 'app/controllers/active_canvas/admin/settings_controller.rb', line 56

def update_global_css
  Setting.global_css = params[:global_css]

  respond_to do |format|
    format.html { redirect_to admin_settings_path(tab: "styles"), notice: "Global CSS saved." }
    format.json { render json: { success: true, message: "Global CSS saved." } }
  end
end

#update_global_jsObject



65
66
67
68
69
70
71
72
# File 'app/controllers/active_canvas/admin/settings_controller.rb', line 65

def update_global_js
  Setting.global_js = params[:global_js]

  respond_to do |format|
    format.html { redirect_to admin_settings_path(tab: "scripts"), notice: "Global JavaScript saved." }
    format.json { render json: { success: true, message: "Global JavaScript saved." } }
  end
end

#update_tailwind_configObject



207
208
209
210
211
212
213
214
# File 'app/controllers/active_canvas/admin/settings_controller.rb', line 207

def update_tailwind_config
  Setting.tailwind_config = params[:tailwind_config]

  respond_to do |format|
    format.html { redirect_to admin_settings_path(tab: "styles"), notice: "Tailwind configuration saved." }
    format.json { render json: { success: true, message: "Tailwind configuration saved." } }
  end
end