mat_views 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +4 -4
- data/app/assets/images/mat_views/android-chrome-192x192.png +0 -0
- data/app/assets/images/mat_views/android-chrome-512x512.png +0 -0
- data/app/assets/images/mat_views/apple-touch-icon.png +0 -0
- data/app/assets/images/mat_views/favicon-16x16.png +0 -0
- data/app/assets/images/mat_views/favicon-32x32.png +0 -0
- data/app/assets/images/mat_views/favicon-48x48.png +0 -0
- data/app/assets/images/mat_views/favicon.ico +0 -0
- data/app/assets/images/mat_views/favicon.svg +18 -0
- data/app/assets/images/mat_views/logo.svg +18 -0
- data/app/assets/images/mat_views/mask-icon.svg +5 -0
- data/app/assets/stylesheets/mat_views/application.css +323 -12
- data/app/controllers/mat_views/admin/application_controller.rb +135 -0
- data/app/controllers/mat_views/admin/dashboard_controller.rb +32 -0
- data/app/controllers/mat_views/admin/mat_view_definitions_controller.rb +248 -0
- data/app/controllers/mat_views/admin/preferences_controller.rb +91 -0
- data/app/controllers/mat_views/admin/runs_controller.rb +74 -0
- data/app/helpers/mat_views/admin/ui_helper.rb +385 -0
- data/app/javascript/mat_views/application.js +8 -0
- data/app/javascript/mat_views/controllers/application.js +10 -0
- data/app/javascript/mat_views/controllers/details_controller.js +122 -0
- data/app/javascript/mat_views/controllers/drawer_controller.js +252 -0
- data/app/javascript/mat_views/controllers/filter_controller.js +90 -0
- data/app/javascript/mat_views/controllers/flash_controller.js +13 -0
- data/app/javascript/mat_views/controllers/index.js +10 -0
- data/app/javascript/mat_views/controllers/mv_confirm_controller.js +281 -0
- data/app/javascript/mat_views/controllers/submitter_controller.js +15 -0
- data/app/javascript/mat_views/controllers/tabs_controller.js +67 -0
- data/app/javascript/mat_views/controllers/timezone_controller.js +16 -0
- data/app/javascript/mat_views/controllers/tooltip_controller.js +328 -0
- data/app/javascript/mat_views/controllers/turbo_frame_lifecycle_controller.js +49 -0
- data/app/jobs/mat_views/application_job.rb +2 -2
- data/app/jobs/mat_views/create_view_job.rb +9 -8
- data/app/jobs/mat_views/delete_view_job.rb +8 -8
- data/app/jobs/mat_views/refresh_view_job.rb +8 -9
- data/app/models/concerns/mat_views_i18n.rb +139 -0
- data/app/models/mat_views/application_record.rb +1 -0
- data/app/models/mat_views/mat_view_definition.rb +12 -7
- data/app/models/mat_views/mat_view_run.rb +11 -13
- data/app/views/layouts/mat_views/_footer.html.erb +41 -0
- data/app/views/layouts/mat_views/_header.html.erb +25 -0
- data/app/views/layouts/mat_views/admin.html.erb +47 -0
- data/app/views/layouts/mat_views/turbo_frame.html.erb +3 -0
- data/app/views/mat_views/admin/dashboard/index.html.erb +33 -0
- data/app/views/mat_views/admin/mat_view_definitions/_definition_actions.html.erb +94 -0
- data/app/views/mat_views/admin/mat_view_definitions/_table.html.erb +48 -0
- data/app/views/mat_views/admin/mat_view_definitions/empty.html.erb +1 -0
- data/app/views/mat_views/admin/mat_view_definitions/form.html.erb +79 -0
- data/app/views/mat_views/admin/mat_view_definitions/index.html.erb +10 -0
- data/app/views/mat_views/admin/mat_view_definitions/show.html.erb +40 -0
- data/app/views/mat_views/admin/preferences/show.html.erb +50 -0
- data/app/views/mat_views/admin/runs/_table.html.erb +61 -0
- data/app/views/mat_views/admin/runs/index.html.erb +38 -0
- data/app/views/mat_views/admin/runs/show.html.erb +64 -0
- data/app/views/mat_views/admin/ui/_card.html.erb +15 -0
- data/app/views/mat_views/admin/ui/_details.html.erb +10 -0
- data/app/views/mat_views/admin/ui/_flash.html.erb +6 -0
- data/app/views/mat_views/admin/ui/_table.html.erb +8 -0
- data/config/importmap.rb +9 -0
- data/config/locales/en-AU-ocker.yml +187 -0
- data/config/locales/en-AU.yml +187 -0
- data/config/locales/en-BB.yml +187 -0
- data/config/locales/en-BD.yml +187 -0
- data/config/locales/en-BE.yml +187 -0
- data/config/locales/en-BORK.yml +187 -0
- data/config/locales/en-BS.yml +187 -0
- data/config/locales/en-BZ.yml +187 -0
- data/config/locales/en-CA.yml +187 -0
- data/config/locales/en-CM.yml +187 -0
- data/config/locales/en-CY.yml +187 -0
- data/config/locales/en-EG.yml +187 -0
- data/config/locales/en-FJ.yml +187 -0
- data/config/locales/en-GB.yml +187 -0
- data/config/locales/en-GH.yml +187 -0
- data/config/locales/en-GI.yml +187 -0
- data/config/locales/en-GM.yml +187 -0
- data/config/locales/en-GY.yml +187 -0
- data/config/locales/en-HK.yml +187 -0
- data/config/locales/en-IE.yml +187 -0
- data/config/locales/en-IN.yml +187 -0
- data/config/locales/en-JM.yml +187 -0
- data/config/locales/en-KE.yml +187 -0
- data/config/locales/en-LK.yml +187 -0
- data/config/locales/en-LOL.yml +187 -0
- data/config/locales/en-LR.yml +187 -0
- data/config/locales/en-MS.yml +187 -0
- data/config/locales/en-MT.yml +187 -0
- data/config/locales/en-MW.yml +187 -0
- data/config/locales/en-MY.yml +187 -0
- data/config/locales/en-NG.yml +187 -0
- data/config/locales/en-NP.yml +187 -0
- data/config/locales/en-NZ.yml +187 -0
- data/config/locales/en-PG.yml +187 -0
- data/config/locales/en-PH.yml +187 -0
- data/config/locales/en-PK.yml +187 -0
- data/config/locales/en-RW.yml +187 -0
- data/config/locales/en-SCOT.yml +187 -0
- data/config/locales/en-SG.yml +187 -0
- data/config/locales/en-SHAKESPEARE.yml +187 -0
- data/config/locales/en-SL.yml +187 -0
- data/config/locales/en-SS.yml +187 -0
- data/config/locales/en-TH.yml +187 -0
- data/config/locales/en-TT.yml +187 -0
- data/config/locales/en-TZ.yml +187 -0
- data/config/locales/en-UG.yml +187 -0
- data/config/locales/en-US-pirate.yml +187 -0
- data/config/locales/en-US.yml +187 -0
- data/config/locales/en-YODA.yml +187 -0
- data/config/locales/en-ZA.yml +187 -0
- data/config/locales/en-ZW.yml +187 -0
- data/config/locales/en.yml +187 -0
- data/config/routes.rb +27 -3
- data/lib/generators/mat_views/install/templates/create_mat_view_definitions.rb +7 -7
- data/lib/generators/mat_views/install/templates/create_mat_view_runs.rb +5 -5
- data/lib/mat_views/admin/auth_bridge.rb +93 -0
- data/lib/mat_views/admin/default_auth.rb +61 -0
- data/lib/mat_views/configuration.rb +9 -0
- data/lib/mat_views/engine.rb +50 -2
- data/lib/mat_views/helpers/ui_test_ids.rb +43 -0
- data/lib/mat_views/services/base_service.rb +46 -38
- data/lib/mat_views/services/check_matview_exists.rb +76 -0
- data/lib/mat_views/services/concurrent_refresh.rb +9 -6
- data/lib/mat_views/services/create_view.rb +15 -15
- data/lib/mat_views/services/delete_view.rb +8 -11
- data/lib/mat_views/services/regular_refresh.rb +6 -5
- data/lib/mat_views/services/swap_refresh.rb +11 -9
- data/lib/mat_views/version.rb +1 -1
- data/lib/mat_views.rb +10 -4
- data/lib/tasks/helpers.rb +13 -13
- data/lib/tasks/mat_views_tasks.rake +15 -15
- metadata +130 -5
@@ -0,0 +1,248 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright Codevedas Inc. 2025-present
|
4
|
+
#
|
5
|
+
# This source code is licensed under the MIT license found in the
|
6
|
+
# LICENSE file in the root directory of this source tree.
|
7
|
+
|
8
|
+
module MatViews
|
9
|
+
module Admin
|
10
|
+
# MatViews::Admin::MatViewDefinitionsController
|
11
|
+
# ---------------------------------------------
|
12
|
+
# Admin CRUD controller for {MatViews::MatViewDefinition} records.
|
13
|
+
#
|
14
|
+
# Responsibilities:
|
15
|
+
# - Full CRUD lifecycle: index, show, new, create, edit, update, destroy.
|
16
|
+
# - Admin-only actions to trigger materialised view operations:
|
17
|
+
# - {#create_now} → enqueues {MatViews::CreateViewJob}
|
18
|
+
# - {#refresh} → enqueues {MatViews::RefreshViewJob}
|
19
|
+
# - {#delete_now} → enqueues {MatViews::DeleteViewJob}
|
20
|
+
# - Integrates with Turbo Frames (uses frame-aware redirects/responses).
|
21
|
+
# - Normalizes array fields (`unique_index_columns`, `dependencies`) from
|
22
|
+
# comma-separated params into arrays.
|
23
|
+
#
|
24
|
+
# Filters:
|
25
|
+
# - `before_action :set_definition` for member actions.
|
26
|
+
# - `before_action :normalize_array_fields` for create/update.
|
27
|
+
# - `before_action :ensure_frame` to enforce frame context.
|
28
|
+
#
|
29
|
+
class MatViewDefinitionsController < ApplicationController
|
30
|
+
before_action :set_definition, only: %i[show edit update destroy create_now refresh delete_now]
|
31
|
+
before_action :normalize_array_fields, only: %i[create update]
|
32
|
+
before_action :ensure_frame
|
33
|
+
|
34
|
+
# GET /:lang/admin/definitions
|
35
|
+
#
|
36
|
+
# Lists all definitions with existence checks against the database.
|
37
|
+
#
|
38
|
+
# @return [void]
|
39
|
+
def index
|
40
|
+
# sleep 20
|
41
|
+
authorize_mat_views!(:read, MatViews::MatViewDefinition)
|
42
|
+
@definitions = MatViews::MatViewDefinition.order(:name).to_a
|
43
|
+
@mv_exists_map = @definitions.index_with do |defn|
|
44
|
+
MatViews::Services::CheckMatviewExists.new(defn).call.response[:exists]
|
45
|
+
end
|
46
|
+
render 'index', formats: :html, layout: 'mat_views/turbo_frame'
|
47
|
+
end
|
48
|
+
|
49
|
+
# GET /:lang/admin/definitions/:id
|
50
|
+
#
|
51
|
+
# Shows a single definition, including run history.
|
52
|
+
#
|
53
|
+
# @return [void]
|
54
|
+
def show
|
55
|
+
authorize_mat_views!(:read, @definition)
|
56
|
+
@mv_exists = MatViews::Services::CheckMatviewExists.new(@definition).call.response[:exists]
|
57
|
+
@runs = @definition.mat_view_runs.order(created_at: :desc).to_a
|
58
|
+
render 'show', formats: :html, layout: 'mat_views/turbo_frame'
|
59
|
+
end
|
60
|
+
|
61
|
+
# GET /:lang/admin/definitions/new
|
62
|
+
#
|
63
|
+
# Renders the new definition form.
|
64
|
+
#
|
65
|
+
# @return [void]
|
66
|
+
def new
|
67
|
+
authorize_mat_views!(:create, MatViews::MatViewDefinition)
|
68
|
+
@definition = MatViews::MatViewDefinition.new
|
69
|
+
render 'form', formats: :html, layout: 'mat_views/turbo_frame'
|
70
|
+
end
|
71
|
+
|
72
|
+
# POST /:lang/admin/definitions
|
73
|
+
#
|
74
|
+
# Creates a new definition from params.
|
75
|
+
#
|
76
|
+
# @return [void]
|
77
|
+
def create
|
78
|
+
authorize_mat_views!(:create, MatViews::MatViewDefinition)
|
79
|
+
@definition = MatViews::MatViewDefinition.new(definition_params)
|
80
|
+
if @definition.save
|
81
|
+
handle_frame_response(status: 298)
|
82
|
+
else
|
83
|
+
render 'form', formats: :html, layout: 'mat_views/turbo_frame', status: :unprocessable_content
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
# GET /:lang/admin/definitions/:id/edit
|
88
|
+
#
|
89
|
+
# Renders the edit form for an existing definition.
|
90
|
+
#
|
91
|
+
# @return [void]
|
92
|
+
def edit
|
93
|
+
authorize_mat_views!(:update, @definition)
|
94
|
+
render 'form', formats: :html, layout: 'mat_views/turbo_frame'
|
95
|
+
end
|
96
|
+
|
97
|
+
# PATCH/PUT /:lang/admin/definitions/:id
|
98
|
+
#
|
99
|
+
# Updates an existing definition.
|
100
|
+
#
|
101
|
+
# @return [void]
|
102
|
+
def update
|
103
|
+
authorize_mat_views!(:update, @definition)
|
104
|
+
if @definition.update(definition_params)
|
105
|
+
handle_frame_response(status: 298)
|
106
|
+
else
|
107
|
+
render 'form', formats: :html, layout: 'mat_views/turbo_frame', status: :unprocessable_content
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
# DELETE /:lang/admin/definitions/:id
|
112
|
+
#
|
113
|
+
# Destroys the definition. Frame-specific redirect/empty response.
|
114
|
+
#
|
115
|
+
# @return [void]
|
116
|
+
def destroy
|
117
|
+
authorize_mat_views!(:destroy, @definition)
|
118
|
+
@definition.destroy!
|
119
|
+
if @frame_id == 'dash-definitions'
|
120
|
+
redirect_to admin_mat_view_definitions_path(frame_id: @frame_id, frame_action: @frame_action), status: :see_other
|
121
|
+
else
|
122
|
+
render 'empty', formats: :html, layout: 'mat_views/turbo_frame', status: 298
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
# POST /:lang/admin/definitions/:id/create_now
|
127
|
+
#
|
128
|
+
# Immediately enqueues a background job to create the materialised view.
|
129
|
+
#
|
130
|
+
# @return [void]
|
131
|
+
def create_now
|
132
|
+
force = params[:force].to_s.downcase == 'true'
|
133
|
+
authorize_mat_views!(:create_view, @definition)
|
134
|
+
MatViews::Jobs::Adapter.enqueue(
|
135
|
+
MatViews::CreateViewJob,
|
136
|
+
queue: MatViews.configuration.job_queue,
|
137
|
+
args: [@definition.id, force, row_count_strategy]
|
138
|
+
)
|
139
|
+
handle_frame_response
|
140
|
+
end
|
141
|
+
|
142
|
+
# POST /:lang/admin/definitions/:id/refresh
|
143
|
+
#
|
144
|
+
# Immediately enqueues a background job to refresh the materialised view.
|
145
|
+
#
|
146
|
+
# @return [void]
|
147
|
+
def refresh
|
148
|
+
authorize_mat_views!(:refresh, @definition)
|
149
|
+
MatViews::Jobs::Adapter.enqueue(
|
150
|
+
MatViews::RefreshViewJob,
|
151
|
+
queue: MatViews.configuration.job_queue,
|
152
|
+
args: [@definition.id, row_count_strategy]
|
153
|
+
)
|
154
|
+
handle_frame_response
|
155
|
+
end
|
156
|
+
|
157
|
+
# POST /:lang/admin/definitions/:id/delete_now
|
158
|
+
#
|
159
|
+
# Immediately enqueues a background job to delete the materialised view.
|
160
|
+
#
|
161
|
+
# @return [void]
|
162
|
+
def delete_now
|
163
|
+
authorize_mat_views!(:delete_view, @definition)
|
164
|
+
|
165
|
+
cascade = params[:cascade].to_s.downcase == 'true'
|
166
|
+
MatViews::Jobs::Adapter.enqueue(
|
167
|
+
MatViews::DeleteViewJob,
|
168
|
+
queue: MatViews.configuration.job_queue,
|
169
|
+
args: [@definition.id, cascade, row_count_strategy]
|
170
|
+
)
|
171
|
+
handle_frame_response
|
172
|
+
end
|
173
|
+
|
174
|
+
private
|
175
|
+
|
176
|
+
# Returns the configured row count strategy for admin UI operations.
|
177
|
+
#
|
178
|
+
# @api private
|
179
|
+
#
|
180
|
+
# @return [Symbol, nil] row count strategy (e.g., :estimated, :exact, :none)
|
181
|
+
def row_count_strategy
|
182
|
+
MatViews.configuration.admin_ui[:row_count_strategy] || :none
|
183
|
+
end
|
184
|
+
|
185
|
+
# Handles redirect/response after a frame-based action.
|
186
|
+
#
|
187
|
+
# @api private
|
188
|
+
#
|
189
|
+
# @param status [Symbol,Integer] the HTTP status for redirect
|
190
|
+
# @return [void]
|
191
|
+
def handle_frame_response(status: :see_other)
|
192
|
+
if @frame_id == 'dash-definitions'
|
193
|
+
redirect_to admin_mat_view_definitions_path(frame_id: @frame_id, frame_action: @frame_action), status: :see_other
|
194
|
+
else
|
195
|
+
redirect_to admin_mat_view_definition_path(@definition, frame_id: @frame_id, frame_action: @frame_action), status: status
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
# Loads a definition by `params[:id]`.
|
200
|
+
#
|
201
|
+
# @api private
|
202
|
+
#
|
203
|
+
# @return [void]
|
204
|
+
def set_definition
|
205
|
+
@definition = MatViews::MatViewDefinition.find(params[:id])
|
206
|
+
end
|
207
|
+
|
208
|
+
# Normalizes array fields (unique_index_columns, dependencies) from
|
209
|
+
# comma-separated strings into arrays.
|
210
|
+
#
|
211
|
+
# @api private
|
212
|
+
#
|
213
|
+
# @return [void]
|
214
|
+
def normalize_array_fields
|
215
|
+
normalize_array_field(:mat_view_definition, :unique_index_columns)
|
216
|
+
normalize_array_field(:mat_view_definition, :dependencies)
|
217
|
+
end
|
218
|
+
|
219
|
+
# Normalizes a specific array field from a comma-separated string into an array.
|
220
|
+
#
|
221
|
+
# @api private
|
222
|
+
#
|
223
|
+
# @param object_key [Symbol] the params object key (e.g., :mat_view_definition)
|
224
|
+
# @param array_key [Symbol] the specific array field key (e.g., :unique_index_columns)
|
225
|
+
#
|
226
|
+
# @return [void]
|
227
|
+
def normalize_array_field(object_key, array_key)
|
228
|
+
object = params[object_key]
|
229
|
+
values = object[array_key]
|
230
|
+
return if values.nil?
|
231
|
+
|
232
|
+
object[array_key] = values.split(',').map(&:strip).reject(&:blank?)
|
233
|
+
end
|
234
|
+
|
235
|
+
# Strong params for mat view definitions.
|
236
|
+
#
|
237
|
+
# @api private
|
238
|
+
#
|
239
|
+
# @return [ActionController::Parameters]
|
240
|
+
def definition_params
|
241
|
+
params.require(:mat_view_definition).permit(
|
242
|
+
:name, :sql, :refresh_strategy, :schedule_cron,
|
243
|
+
unique_index_columns: [], dependencies: []
|
244
|
+
)
|
245
|
+
end
|
246
|
+
end
|
247
|
+
end
|
248
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright Codevedas Inc. 2025-present
|
4
|
+
#
|
5
|
+
# This source code is licensed under the MIT license found in the
|
6
|
+
# LICENSE file in the root directory of this source tree.
|
7
|
+
|
8
|
+
module MatViews
|
9
|
+
module Admin
|
10
|
+
# MatViews::Admin::PreferencesController
|
11
|
+
# --------------------------------------
|
12
|
+
# Controller for managing user preferences in the MatViews admin UI.
|
13
|
+
#
|
14
|
+
# Responsibilities:
|
15
|
+
# - Allows users to view and update UI preferences such as theme and locale.
|
16
|
+
# - Stores theme in cookies and locale in session.
|
17
|
+
# - Provides a force-reload response option to update Turbo frames dynamically.
|
18
|
+
#
|
19
|
+
# Filters:
|
20
|
+
# - `before_action :authorize!` → ensures user can access preferences.
|
21
|
+
# - `before_action :ensure_frame` → requires Turbo frame context for `show`.
|
22
|
+
#
|
23
|
+
class PreferencesController < ApplicationController
|
24
|
+
before_action :authorize!
|
25
|
+
before_action :ensure_frame
|
26
|
+
|
27
|
+
# GET /:lang/admin/preferences
|
28
|
+
#
|
29
|
+
# Displays the current preferences (theme + locale) and available locales.
|
30
|
+
# If `force_reload=1` is passed, sets a non-standard status code (299) and
|
31
|
+
# a custom header to signal the client to reload.
|
32
|
+
#
|
33
|
+
# @return [void]
|
34
|
+
def show
|
35
|
+
@theme = read_theme
|
36
|
+
@locale = I18n.locale.to_s
|
37
|
+
@locales = MatViews::Engine.locale_code_mapping.sort_by { |_key, name| name }.map { |code, _name| code.to_s }.uniq
|
38
|
+
|
39
|
+
# force reload frame if requested
|
40
|
+
if params[:force_reload].to_s == '1'
|
41
|
+
response.status = 299
|
42
|
+
response.set_header('X-Status-Name', 'Success force reload')
|
43
|
+
end
|
44
|
+
|
45
|
+
render 'show', formats: :html, layout: 'mat_views/turbo_frame'
|
46
|
+
end
|
47
|
+
|
48
|
+
# PATCH/PUT /:lang/admin/preferences
|
49
|
+
#
|
50
|
+
# Updates preferences:
|
51
|
+
# - Theme (`light`, `dark`, or deleted if invalid) stored in cookies.
|
52
|
+
# - Locale stored in session if valid.
|
53
|
+
# Redirects back to preferences with `force_reload=1` to trigger a refresh.
|
54
|
+
#
|
55
|
+
# @return [void]
|
56
|
+
def update
|
57
|
+
theme_param = params[:theme].to_s
|
58
|
+
case theme_param
|
59
|
+
when 'light', 'dark' then cookies[:theme] = { value: theme_param, expires: 1.year.from_now, httponly: false }
|
60
|
+
else cookies.delete(:theme)
|
61
|
+
end
|
62
|
+
|
63
|
+
locale = params[:locale].to_s.presence || MatViews::Engine.default_locale.to_s
|
64
|
+
session[:mat_views_locale] = locale if MatViews::Engine.available_locales.map(&:to_s).include?(locale)
|
65
|
+
|
66
|
+
redirect_to "#{admin_preferences_path}?force_reload=1&frame_id=#{@frame_id}", status: :see_other
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
# Authorizes access to preferences.
|
72
|
+
#
|
73
|
+
# @api private
|
74
|
+
#
|
75
|
+
# @return [void]
|
76
|
+
def authorize!
|
77
|
+
authorize_mat_views!(:read, MatViews::MatViewDefinition)
|
78
|
+
end
|
79
|
+
|
80
|
+
# Reads the theme from cookies.
|
81
|
+
#
|
82
|
+
# @api private
|
83
|
+
#
|
84
|
+
# @return ["light", "dark", "auto"] theme preference or "auto" if unset/invalid
|
85
|
+
def read_theme
|
86
|
+
t = cookies[:theme].to_s
|
87
|
+
%w[light dark].include?(t) ? t : 'auto'
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright Codevedas Inc. 2025-present
|
4
|
+
#
|
5
|
+
# This source code is licensed under the MIT license found in the
|
6
|
+
# LICENSE file in the root directory of this source tree.
|
7
|
+
|
8
|
+
module MatViews
|
9
|
+
module Admin
|
10
|
+
# MatViews::Admin::RunsController
|
11
|
+
# -------------------------------
|
12
|
+
# Controller for viewing materialised view run history in the admin UI.
|
13
|
+
#
|
14
|
+
# Responsibilities:
|
15
|
+
# - Provides a list of recent runs (create/refresh/delete) for all definitions.
|
16
|
+
# - Shows details for an individual run in a Turbo frame/drawer context.
|
17
|
+
#
|
18
|
+
# Filters:
|
19
|
+
# - `before_action :ensure_frame` → enforces frame-only access.
|
20
|
+
# - `before_action :set_mat_view_run` → loads and authorizes a single run.
|
21
|
+
#
|
22
|
+
# Views:
|
23
|
+
# - Index renders `mat_views/admin/runs/embed_frame` partial.
|
24
|
+
# - Show renders `mat_views/admin/runs/embed_show_drawer` partial.
|
25
|
+
#
|
26
|
+
class RunsController < ApplicationController
|
27
|
+
before_action :ensure_frame
|
28
|
+
helper_method :definition
|
29
|
+
before_action :ensure_frame, only: %i[index show]
|
30
|
+
before_action :set_mat_view_run, only: %i[show]
|
31
|
+
|
32
|
+
# GET /:lang/admin/runs
|
33
|
+
#
|
34
|
+
# Lists all materialised view runs ordered by start time.
|
35
|
+
#
|
36
|
+
# @return [void]
|
37
|
+
def index
|
38
|
+
authorize_mat_views!(:read, :mat_views_runs)
|
39
|
+
|
40
|
+
@definitions = MatViews::MatViewDefinition.order(:name).to_a
|
41
|
+
@runs = MatViews::MatViewRun.order(started_at: :desc)
|
42
|
+
|
43
|
+
%i[mat_view_definition_id operation status].each do |param|
|
44
|
+
param_value = params[param]
|
45
|
+
next unless param_value.present?
|
46
|
+
|
47
|
+
@runs = @runs.where(param => param_value)
|
48
|
+
end
|
49
|
+
render 'index', formats: :html, layout: 'mat_views/turbo_frame'
|
50
|
+
end
|
51
|
+
|
52
|
+
# GET /:lang/admin/runs/:id
|
53
|
+
#
|
54
|
+
# Displays details for a single run.
|
55
|
+
#
|
56
|
+
# @return [void]
|
57
|
+
def show
|
58
|
+
render 'show', formats: :html, layout: 'mat_views/turbo_frame'
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
|
63
|
+
# Loads the requested run and checks authorization.
|
64
|
+
#
|
65
|
+
# @api private
|
66
|
+
#
|
67
|
+
# @return [void]
|
68
|
+
def set_mat_view_run
|
69
|
+
@run = MatViews::MatViewRun.find(params[:id])
|
70
|
+
authorize_mat_views!(:read, @run)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|