databasium 0.1.0 → 0.1.1

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.
@@ -48,6 +48,10 @@ export default class extends Controller {
48
48
  if (!e.target.closest("input, label, a, button")) {
49
49
  checkbox.checked = !checkbox.checked;
50
50
  }
51
+ // new records were rendered
52
+ if (this.deleteButtonTarget.parentElement.classList.contains("hidden")) {
53
+ this.resetDeleteButton();
54
+ }
51
55
  this.updateDeleteButton(checkbox.checked);
52
56
  this.allRecordsSelected = this.checkboxTargets.length === this.selectedRecords;
53
57
  this.updateStyleOfToggleAllRecordsButton();
@@ -159,6 +163,7 @@ export default class extends Controller {
159
163
 
160
164
  createAddRecordForm(row) {
161
165
  const form = this.element.querySelector("#addRecord").cloneNode(true);
166
+ this.uniquifyTurboFrames(form, `_${row.id}`);
162
167
  form.id = `record-form-${row.id}`;
163
168
  form.classList.remove("hidden", "max-h-100");
164
169
  // 135px is the space up to the open form cant define as constants because of tailwind dynamic classes
@@ -202,6 +207,27 @@ export default class extends Controller {
202
207
 
203
208
  return form;
204
209
  }
210
+ // this need to be done as also add tab contains the model froms and the ids would fight
211
+ uniquifyTurboFrames(root, suffix) {
212
+ root.querySelectorAll("turbo-frame[id]").forEach((frame) => {
213
+ frame.id = `${frame.id}${suffix}`;
214
+ });
215
+
216
+ root.querySelectorAll("[data-turbo-frame]").forEach((el) => {
217
+ const frame = el.getAttribute("data-turbo-frame");
218
+ if (frame && frame !== "_top") {
219
+ el.setAttribute("data-turbo-frame", `${frame}${suffix}`);
220
+ }
221
+ });
222
+
223
+ root.querySelectorAll("a[href]").forEach((link) => {
224
+ const url = new URL(link.href, window.location.origin);
225
+ const frameId = url.searchParams.get("frame_id");
226
+ if (!frameId) return;
227
+ url.searchParams.set("frame_id", `${frameId}${suffix}`);
228
+ link.href = url.toString();
229
+ });
230
+ }
205
231
 
206
232
  openTab(e, givenRecordId = null) {
207
233
  const recordId = givenRecordId || e.currentTarget.dataset.recordId;
@@ -23,10 +23,7 @@ module Components
23
23
  div(
24
24
  class:
25
25
  "relative bg-panel p-4 rounded-xl border-1 border-border w-fit max-w-[50vw] flex flex-col h-[90dvh] overflow-auto shadow-2xl",
26
- id: @frame_id,
27
- data: {
28
- action: "click->table-select#stopPropagation"
29
- }
26
+ id: @frame_id
30
27
  ) do
31
28
  render_title
32
29
  render_selected_record
@@ -27,7 +27,7 @@ module Components
27
27
  %w[binary Binary],
28
28
  %w[boolean Boolean],
29
29
  %w[references Reference]
30
- ].each { |value, label| option(value: value, selected: @value == value) { label } }
30
+ ].each { |value, label| option(value: value, selected: @value.to_s == value.to_s) { label } }
31
31
  end
32
32
  end
33
33
  end
@@ -14,9 +14,6 @@ module Databasium
14
14
  end
15
15
 
16
16
  def render_error_flash(error)
17
- Rails.logger.error("[Databasium] #{error.class}: #{error.message}")
18
- Rails.logger.error(error.backtrace.join("\n")) if error.backtrace
19
-
20
17
  return if performed?
21
18
 
22
19
  message, details = error_message_parts(error)
@@ -53,12 +50,20 @@ module Databasium
53
50
  end
54
51
  end
55
52
 
53
+ def raise_user_error(message)
54
+ raise Databasium::UserFacingError, message
55
+ end
56
+
56
57
  def error_message_parts(error)
57
58
  lines = strip_ansi(error.message.to_s).lines.map(&:chomp)
58
59
  message = lines.shift.presence || "Something went wrong"
59
- details = lines.join("\n")
60
+ details = lines.join("\n").presence
61
+
62
+ unless error.is_a?(Databasium::UserFacingError)
63
+ details ||= strip_ansi(error.backtrace&.join("\n").to_s).presence
64
+ end
60
65
 
61
- [ message, details.presence || strip_ansi(error.backtrace&.join("\n").to_s).presence ]
66
+ [ message, details ]
62
67
  end
63
68
 
64
69
  def strip_ansi(text)
@@ -43,6 +43,7 @@ class Databasium::MigrationsController < Databasium::ApplicationController
43
43
  success = @migration_service.save_migration(migration_params)
44
44
  else
45
45
  content = @migration_service.generate_migration(migration_params)
46
+ raise_user_error("Please provide a table name to generate a migration") unless content
46
47
  end
47
48
 
48
49
  if success
@@ -61,7 +62,7 @@ class Databasium::MigrationsController < Databasium::ApplicationController
61
62
 
62
63
  def sidebar
63
64
  pagy, migrations =
64
- pagy(@migration_service.get_migrations(params[:search]), limit: 5, root_key: "migrations")
65
+ pagy(@migration_service.get_migrations(params[:search]), limit: 7, root_key: "migrations")
65
66
  pending_migrations = @migration_service.pending_migrations
66
67
 
67
68
  render Components::Databasium::SearchResults::Migrations.new(
@@ -12,6 +12,7 @@ class Databasium::ModelsController < Databasium::ApplicationController
12
12
  def show
13
13
  model = params[:id]
14
14
  content = @model_service.read_model_file(model)
15
+ raise_user_error("Model file not found for #{model}.") unless content
15
16
  attributes = @model_service.get_model_data_from_file(model)
16
17
  models = @model_service.get_all_models_from_db(search: params[:search])
17
18
 
@@ -10,7 +10,9 @@ class Databasium::RecordsController < Databasium::ApplicationController
10
10
 
11
11
  def create
12
12
  new_record = @record_service.create_new(attributes: model_columns_params)
13
- raise ActiveRecord::RecordInvalid, new_record.errors.full_messages.join(", ") unless new_record
13
+ unless new_record && new_record.valid?
14
+ return raise_user_error(new_record.errors.full_messages.join(", "))
15
+ end
14
16
 
15
17
  render turbo_stream: [
16
18
  turbo_stream.append(
@@ -25,13 +27,10 @@ class Databasium::RecordsController < Databasium::ApplicationController
25
27
  end
26
28
 
27
29
  def records
30
+ raise_user_error("Missing model for #{params[:table]} table.") if @model.blank?
28
31
  @context = records_context
29
- pagy, records =
30
- pagy(
31
- @record_service.filter_records(filter_params),
32
- limit: params[:limit].presence || 10,
33
- root_key: "records"
34
- )
32
+ raw_records = @record_service.filter_records(filter_params)
33
+ pagy, records = pagy(raw_records, limit: params[:limit].presence || 10, root_key: "records")
35
34
 
36
35
  if foreign_records_frame?(@context[:turbo_frame])
37
36
  render_foreign_records_table
@@ -45,7 +44,7 @@ class Databasium::RecordsController < Databasium::ApplicationController
45
44
 
46
45
  def update
47
46
  record = @record_service.update_by_id(params[:id], attributes: model_columns_params)
48
- raise ActiveRecord::RecordInvalid, record.errors.full_messages.join(", ") unless record
47
+ raise_user_error(record.errors.full_messages.join(", ")) unless record
49
48
  render turbo_stream:
50
49
  turbo_stream.replace(
51
50
  dom_id(record),
@@ -58,9 +57,7 @@ class Databasium::RecordsController < Databasium::ApplicationController
58
57
 
59
58
  def bulk_destroy
60
59
  deleted_records = @record_service.bulk_destroy(params[:ids])
61
- unless deleted_records
62
- raise ActiveRecord::RecordInvalid, deleted_records.errors.full_messages.join(", ")
63
- end
60
+ raise_user_error(deleted_records.errors.full_messages.join(", ")) unless deleted_records
64
61
 
65
62
  doms_ids = deleted_records.map { |record| dom_id(record) }
66
63
 
@@ -74,7 +74,7 @@ class Databasium::Migration
74
74
  def generate_migration(params)
75
75
  unless params[:table_name_from].present? || params[:table_name_to].present? ||
76
76
  params[:table_name].present?
77
- raise "Please provide a table name to generate a migration"
77
+ return nil
78
78
  end
79
79
 
80
80
  require "rails/generators/active_record/migration/migration_generator"
@@ -30,7 +30,11 @@ class Databasium::Model
30
30
  end
31
31
 
32
32
  def read_model_file(model_name)
33
- File.read(model_file_path(model_name))
33
+ begin
34
+ File.read(model_file_path(model_name))
35
+ rescue Errno::ENOENT
36
+ nil
37
+ end
34
38
  end
35
39
 
36
40
  def get_model_data_from_file(model_name)
@@ -29,7 +29,7 @@ class Databasium::Record
29
29
 
30
30
  def filter_records(filter)
31
31
  records = @model&.all
32
- return records if filter.nil? || @model.nil?
32
+ return [] if filter.nil? || @model.nil? || records.blank?
33
33
  connectors = Array(filter[:operator_types]).map(&:to_s)
34
34
  allowed_operators = %w[eq not_eq gt lt gteq lteq matches does_not_match]
35
35
  combined_predicate = nil
@@ -9,7 +9,7 @@ class Databasium::Schema
9
9
  def sync!(schema: nil)
10
10
  path = Rails.root.join("storage")
11
11
  FileUtils.mkdir_p(path) unless Dir.exist?(path)
12
- File.write(path.join("schema_graph.json"), schema || build_schema.to_json)
12
+ File.write(path.join("schema_graph.json"), (schema || build_schema).to_json)
13
13
  end
14
14
 
15
15
  def get_associations(table)
@@ -2,6 +2,7 @@
2
2
 
3
3
  require "databasium/engine_mount"
4
4
  require "databasium/middleware/conditional_check_pending"
5
+ require "databasium/user_facing_error"
5
6
 
6
7
  module Databasium
7
8
  class Engine < ::Rails::Engine
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Databasium
4
+ class UserFacingError < StandardError
5
+ end
6
+ end
@@ -1,3 +1,3 @@
1
1
  module Databasium
2
- VERSION = "0.1.0"
2
+ VERSION = "0.1.1"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: databasium
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Róbert Švihla
@@ -242,6 +242,7 @@ files:
242
242
  - lib/databasium/templates/create_table_migration.rb.tt
243
243
  - lib/databasium/templates/migration.rb.tt
244
244
  - lib/databasium/templates/model.rb.tt
245
+ - lib/databasium/user_facing_error.rb
245
246
  - lib/databasium/version.rb
246
247
  - lib/tasks/databasium_tasks.rake
247
248
  homepage: https://github.com/Unitato1/databasium