databasium 0.1.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 +7 -0
- data/CHANGELOG.md +32 -0
- data/MIT-LICENSE +20 -0
- data/README.md +109 -0
- data/Rakefile +6 -0
- data/app/assets/builds/application.js +9045 -0
- data/app/assets/builds/application.js.map +7 -0
- data/app/assets/builds/databasium.css +2 -0
- data/app/assets/config/databasium_manifest.js +1 -0
- data/app/assets/javascript/databasium/application.js +2 -0
- data/app/assets/javascript/databasium/controllers/attribute_controller.js +27 -0
- data/app/assets/javascript/databasium/controllers/collapse_controller.js +18 -0
- data/app/assets/javascript/databasium/controllers/error_controller.js +15 -0
- data/app/assets/javascript/databasium/controllers/filter_controller.js +224 -0
- data/app/assets/javascript/databasium/controllers/flash_controller.js +18 -0
- data/app/assets/javascript/databasium/controllers/graph_controller.js +193 -0
- data/app/assets/javascript/databasium/controllers/index.js +7 -0
- data/app/assets/javascript/databasium/controllers/layout_controller.js +13 -0
- data/app/assets/javascript/databasium/controllers/model_controller.js +32 -0
- data/app/assets/javascript/databasium/controllers/new_migration_controller.js +107 -0
- data/app/assets/javascript/databasium/controllers/relation_controller.js +10 -0
- data/app/assets/javascript/databasium/controllers/search_controller.js +23 -0
- data/app/assets/javascript/databasium/controllers/table_controller.js +283 -0
- data/app/assets/javascript/databasium/controllers/table_select_controller.js +19 -0
- data/app/assets/javascript/databasium/controllers/toggle_controller.js +28 -0
- data/app/assets/javascript/databasium/controllers/validation_controller.js +78 -0
- data/app/assets/javascript/databasium/shapes/erd_table_shape.js +54 -0
- data/app/assets/stylesheets/databasium/application.css +15 -0
- data/app/assets/stylesheets/databasium/colors.css +55 -0
- data/app/assets/stylesheets/databasium/custom.css +36 -0
- data/app/assets/stylesheets/databasium/databasium_engine.css +6 -0
- data/app/assets/stylesheets/databasium/pagy-tailwind.css +66 -0
- data/app/components/base.rb +50 -0
- data/app/components/databasium/collapsable.rb +62 -0
- data/app/components/databasium/forms/model.rb +147 -0
- data/app/components/databasium/forms/search.rb +31 -0
- data/app/components/databasium/global/error.rb +60 -0
- data/app/components/databasium/global/flash.rb +73 -0
- data/app/components/databasium/global/header_actions.rb +36 -0
- data/app/components/databasium/global/sidebar.rb +45 -0
- data/app/components/databasium/global/suggestion.rb +25 -0
- data/app/components/databasium/migrations/action.rb +39 -0
- data/app/components/databasium/migrations/file.rb +58 -0
- data/app/components/databasium/migrations/form.rb +222 -0
- data/app/components/databasium/migrations/header_actions.rb +87 -0
- data/app/components/databasium/migrations/migration_status.rb +22 -0
- data/app/components/databasium/migrations/preview.rb +29 -0
- data/app/components/databasium/migrations/show_turbo_stream.rb +19 -0
- data/app/components/databasium/migrations/sidebar.rb +28 -0
- data/app/components/databasium/models/attributes.rb +49 -0
- data/app/components/databasium/models/form.rb +100 -0
- data/app/components/databasium/models/header_actions.rb +51 -0
- data/app/components/databasium/models/model_preview.rb +31 -0
- data/app/components/databasium/models/sidebar.rb +25 -0
- data/app/components/databasium/models/templates/attribute.rb +99 -0
- data/app/components/databasium/models/templates/base.rb +6 -0
- data/app/components/databasium/models/templates/relation.rb +56 -0
- data/app/components/databasium/models/templates/validation.rb +285 -0
- data/app/components/databasium/navigation/base_icon.rb +32 -0
- data/app/components/databasium/navigation/frontend_icon.rb +17 -0
- data/app/components/databasium/navigation/get_icon.rb +26 -0
- data/app/components/databasium/navigation/icon.rb +28 -0
- data/app/components/databasium/navigation/icon_panel.rb +26 -0
- data/app/components/databasium/navigation/post_icon.rb +25 -0
- data/app/components/databasium/navigation/put_icon.rb +18 -0
- data/app/components/databasium/records/filter.rb +73 -0
- data/app/components/databasium/records/foreign_records.rb +84 -0
- data/app/components/databasium/records/header_actions.rb +110 -0
- data/app/components/databasium/records/show_turbo_stream.rb +75 -0
- data/app/components/databasium/records/sidebar.rb +23 -0
- data/app/components/databasium/records/table/record_panel.rb +60 -0
- data/app/components/databasium/records/table/row.rb +104 -0
- data/app/components/databasium/records/table.rb +125 -0
- data/app/components/databasium/records/table_turbo_frame.rb +37 -0
- data/app/components/databasium/records/utilities.rb +25 -0
- data/app/components/databasium/schemas/header_actions.rb +99 -0
- data/app/components/databasium/schemas/sidebar.rb +25 -0
- data/app/components/databasium/search_results/migrations.rb +37 -0
- data/app/components/databasium/search_results/models.rb +36 -0
- data/app/components/databasium/search_results/schema_models.rb +37 -0
- data/app/components/databasium/search_results/tables.rb +31 -0
- data/app/components/databasium/type_select.rb +35 -0
- data/app/controllers/databasium/application_controller.rb +68 -0
- data/app/controllers/databasium/homepage_controller.rb +5 -0
- data/app/controllers/databasium/migrations_controller.rb +186 -0
- data/app/controllers/databasium/models_controller.rb +105 -0
- data/app/controllers/databasium/records_controller.rb +156 -0
- data/app/controllers/databasium/schemas_controller.rb +52 -0
- data/app/helpers/databasium/application_helper.rb +4 -0
- data/app/helpers/databasium/heroicon_helper.rb +21 -0
- data/app/helpers/databasium/models_helper.rb +4 -0
- data/app/jobs/databasium/application_job.rb +4 -0
- data/app/mailers/databasium/application_mailer.rb +6 -0
- data/app/models/databasium/application_record.rb +5 -0
- data/app/models/model.json +0 -0
- data/app/services/databasium/migration.rb +176 -0
- data/app/services/databasium/model.rb +182 -0
- data/app/services/databasium/record.rb +65 -0
- data/app/services/databasium/schema.rb +146 -0
- data/app/views/base.rb +13 -0
- data/app/views/databasium/errors/non_development.rb +21 -0
- data/app/views/databasium/homepage/index.rb +29 -0
- data/app/views/databasium/migrations/index.rb +33 -0
- data/app/views/databasium/migrations/new.rb +29 -0
- data/app/views/databasium/models/index.rb +31 -0
- data/app/views/databasium/models/new.rb +37 -0
- data/app/views/databasium/records/index.rb +24 -0
- data/app/views/databasium/schemas/index.rb +39 -0
- data/app/views/layouts/databasium/application.rb +56 -0
- data/config/importmap.rb +12 -0
- data/config/initializers/heroicon.rb +12 -0
- data/config/initializers/pagy.rb +48 -0
- data/config/initializers/phlex.rb +19 -0
- data/config/routes.rb +31 -0
- data/config/tailwind.config.js +10 -0
- data/lib/databasium/engine.rb +57 -0
- data/lib/databasium/engine_mount.rb +37 -0
- data/lib/databasium/middleware/conditional_check_pending.rb +27 -0
- data/lib/databasium/templates/create_table_migration.rb.tt +29 -0
- data/lib/databasium/templates/migration.rb.tt +48 -0
- data/lib/databasium/templates/model.rb.tt +23 -0
- data/lib/databasium/version.rb +3 -0
- data/lib/databasium.rb +11 -0
- data/lib/tasks/databasium_tasks.rake +4 -0
- metadata +272 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
module Components
|
|
2
|
+
module Databasium
|
|
3
|
+
class Migrations::File < Components::Base
|
|
4
|
+
include Phlex::Rails::Helpers::TurboFrameTag
|
|
5
|
+
include Phlex::Rails::Helpers::LinkTo
|
|
6
|
+
include Phlex::Rails::Helpers::ButtonTo
|
|
7
|
+
include Phlex::Rails::Helpers::ContentFor
|
|
8
|
+
|
|
9
|
+
def initialize(migration:, content:)
|
|
10
|
+
@migration = migration
|
|
11
|
+
@content = content
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def view_template
|
|
15
|
+
turbo_frame_tag(
|
|
16
|
+
"migration",
|
|
17
|
+
class: "flex flex-col flex-1 p-4 w-full min-h-0 overflow-hidden"
|
|
18
|
+
) do
|
|
19
|
+
h1(class: "text-2xl font-bold mb-2 text-ellipsis break-all") { @migration.name }
|
|
20
|
+
render_content
|
|
21
|
+
render_extra_info
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
private
|
|
26
|
+
|
|
27
|
+
def render_content
|
|
28
|
+
pre(
|
|
29
|
+
class:
|
|
30
|
+
"min-h-0 flex-1 border-1 border-border bg-panel text-main-text p-4 overflow-auto rounded-2xl scrollbar-thin"
|
|
31
|
+
) { @content }
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def render_extra_info
|
|
35
|
+
h2(class: "text-lg font-semibold my-2") { "Extra info: " }
|
|
36
|
+
div(class: "grid grid-cols-[max-content_1fr] gap-4 w-fill break-all") do
|
|
37
|
+
ul(class: "list-disc list-inside") do
|
|
38
|
+
li { "Timestamp: " }
|
|
39
|
+
li { "Last time modified: " }
|
|
40
|
+
li { "Name: " }
|
|
41
|
+
li { "File path: " }
|
|
42
|
+
end
|
|
43
|
+
div do
|
|
44
|
+
p(class: "font-bold text-wrap") { @migration.version }
|
|
45
|
+
p(class: "font-bold") do
|
|
46
|
+
Time
|
|
47
|
+
.strptime(@migration.version.to_s, "%Y%m%d%H%M%S")
|
|
48
|
+
.localtime
|
|
49
|
+
.strftime("%Y-%m-%d at %H:%M:%S")
|
|
50
|
+
end
|
|
51
|
+
p(class: "font-bold") { @migration.name }
|
|
52
|
+
p(class: "font-bold") { @migration.filename }
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Components
|
|
4
|
+
module Databasium
|
|
5
|
+
class Migrations::Form < Components::Base
|
|
6
|
+
include Phlex::Rails::Helpers::FormWith
|
|
7
|
+
include Phlex::Rails::Helpers::TurboFrameTag
|
|
8
|
+
|
|
9
|
+
def initialize(tables:, content:)
|
|
10
|
+
@tables = tables
|
|
11
|
+
@content = content
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def view_template
|
|
15
|
+
form_with(
|
|
16
|
+
url: helpers.migrations_path,
|
|
17
|
+
method: :post,
|
|
18
|
+
id: "migration_form",
|
|
19
|
+
data: {
|
|
20
|
+
controller: "new-migration",
|
|
21
|
+
turbo_frame: "_top"
|
|
22
|
+
},
|
|
23
|
+
class:
|
|
24
|
+
"flex flex-col gap-4 min-w-fit w-1/3 bg-panel border-1 border-border rounded-xl p-4"
|
|
25
|
+
) do |form|
|
|
26
|
+
render_migration_action(form)
|
|
27
|
+
render_table_name(form)
|
|
28
|
+
render_columns(form)
|
|
29
|
+
render_validations(form)
|
|
30
|
+
render_table_datalist
|
|
31
|
+
form.submit "Generate Preview",
|
|
32
|
+
class: "bg-blue-500 p-2 rounded-md w-fit",
|
|
33
|
+
name: "add_migration"
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
private
|
|
38
|
+
|
|
39
|
+
def render_validations(form)
|
|
40
|
+
render_collapsable_with_button(
|
|
41
|
+
form: form,
|
|
42
|
+
name: "validations",
|
|
43
|
+
data_targets: {
|
|
44
|
+
new_migration_target: "validations"
|
|
45
|
+
},
|
|
46
|
+
button_text: "Add Validation",
|
|
47
|
+
button_action: "click->new-migration#addValidation",
|
|
48
|
+
name_params: {
|
|
49
|
+
new_migration_target: "validation"
|
|
50
|
+
},
|
|
51
|
+
hidden: true
|
|
52
|
+
) do
|
|
53
|
+
select(
|
|
54
|
+
name: "validation[][column_name]",
|
|
55
|
+
class: "p-2 border-1 border-border rounded-md w-fit bg-background",
|
|
56
|
+
data: {
|
|
57
|
+
new_migration_target: "validation_column_name"
|
|
58
|
+
}
|
|
59
|
+
) { option(value: "") { "Select column" } }
|
|
60
|
+
select(
|
|
61
|
+
name: "validation[][type]",
|
|
62
|
+
class: "p-2 border-1 border-border rounded-md w-fit bg-background",
|
|
63
|
+
data: {
|
|
64
|
+
new_migration_target: "validation_column_type"
|
|
65
|
+
}
|
|
66
|
+
) do
|
|
67
|
+
option(value: "uniqueness") { "Uniqueness" }
|
|
68
|
+
option(value: "not_null") { "Not Null" }
|
|
69
|
+
end
|
|
70
|
+
render_remove_button(action: "click->new-migration#removeValidation")
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def render_columns(form)
|
|
75
|
+
render_collapsable_with_button(
|
|
76
|
+
form: form,
|
|
77
|
+
name: "columns",
|
|
78
|
+
data_targets: {
|
|
79
|
+
new_migration_target: "columns"
|
|
80
|
+
},
|
|
81
|
+
button_text: "Add Column",
|
|
82
|
+
button_action: "click->new-migration#addColumn",
|
|
83
|
+
name_params: {
|
|
84
|
+
new_migration_target: "column"
|
|
85
|
+
},
|
|
86
|
+
hidden: true
|
|
87
|
+
) do
|
|
88
|
+
div(class: "flex flex-col gap-2 relative mt-2") do
|
|
89
|
+
if @model
|
|
90
|
+
form.select :column_name,
|
|
91
|
+
@model.columns.map(&:name),
|
|
92
|
+
include_blank: "Select a column name",
|
|
93
|
+
class: "p-2 border-1 border-border rounded-md w-fit bg-background"
|
|
94
|
+
else
|
|
95
|
+
form.label "Column Name", class: minimalistic_label_class
|
|
96
|
+
form.text_field(
|
|
97
|
+
:column_name,
|
|
98
|
+
name: "columns[][column_name]",
|
|
99
|
+
class: "p-1 border-1 rounded-xl border-border h-fit bg-background",
|
|
100
|
+
data: {
|
|
101
|
+
action: "change->new-migration#updateColumnNames"
|
|
102
|
+
}
|
|
103
|
+
)
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
div(class: "flex flex-col gap-2 h-full relative") do
|
|
107
|
+
form.label "Column Name", class: minimalistic_label_class
|
|
108
|
+
render Components::Databasium::TypeSelect.new(name: "columns[][column_type]")
|
|
109
|
+
end
|
|
110
|
+
render_remove_button(action: "click->new-migration#removeColumn")
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def render_table_name(form)
|
|
115
|
+
render_collapsable_with_button(
|
|
116
|
+
form: form,
|
|
117
|
+
name: "table_name",
|
|
118
|
+
data_targets: {
|
|
119
|
+
new_migration_target: "table_name"
|
|
120
|
+
}
|
|
121
|
+
) do
|
|
122
|
+
form.text_field :table_name,
|
|
123
|
+
class: "p-2 border-1 border-border w-fit bg-background rounded-md"
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def render_migration_action(form)
|
|
128
|
+
render_collapsable_with_button(
|
|
129
|
+
form: form,
|
|
130
|
+
name: "migration_action",
|
|
131
|
+
data_targets: {
|
|
132
|
+
new_migration_target: "migration_action"
|
|
133
|
+
}
|
|
134
|
+
) do
|
|
135
|
+
div(class: "flex flex-col") do
|
|
136
|
+
form.label :migration_action, "Action", class: "text-sm font-semibold"
|
|
137
|
+
form.select :migration_action,
|
|
138
|
+
%w[create remove add],
|
|
139
|
+
{},
|
|
140
|
+
class: "p-2 border-1 border-border rounded-md w-fit bg-background",
|
|
141
|
+
data: {
|
|
142
|
+
action: "change->new-migration#set_action"
|
|
143
|
+
}
|
|
144
|
+
end
|
|
145
|
+
div(class: "flex flex-col", data: { new_migration_target: "add_model_container" }) do
|
|
146
|
+
form.label :add_model, "Add also model", class: "text-sm font-semibold"
|
|
147
|
+
div(class: "h-11 flex items-center justify-center") do
|
|
148
|
+
form.check_box :add_model,
|
|
149
|
+
checked: true,
|
|
150
|
+
class: "w-4 h-4",
|
|
151
|
+
data: {
|
|
152
|
+
new_migration_target: "add_model"
|
|
153
|
+
}
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
div(class: "flex flex-col hidden", data: { new_migration_target: "table_name_from" }) do
|
|
158
|
+
form.label :table_name_from, "Table to remove from", class: "text-sm font-semibold"
|
|
159
|
+
render_tables_search_field(form, :table_name_from)
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
div(class: "flex flex-col hidden", data: { new_migration_target: "table_name_to" }) do
|
|
163
|
+
form.label :table_name_to, "Table to add to", class: "text-sm font-semibold"
|
|
164
|
+
render_tables_search_field(form, :table_name_to)
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
def render_tables_search_field(form, name)
|
|
170
|
+
form.search_field name,
|
|
171
|
+
placeholder: "Search for a table",
|
|
172
|
+
list: "table_name_datalist",
|
|
173
|
+
class:
|
|
174
|
+
"p-2 border-1 border-border rounded-md w-fit bg-background leading-5"
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
def render_table_datalist
|
|
178
|
+
datalist(id: "table_name_datalist") do
|
|
179
|
+
@tables.each { |table| option(value: table) { table } }
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
def render_collapsable_with_button(
|
|
184
|
+
form:,
|
|
185
|
+
name:,
|
|
186
|
+
data_targets:,
|
|
187
|
+
button_text: nil,
|
|
188
|
+
button_action: nil,
|
|
189
|
+
name_params: {},
|
|
190
|
+
hidden: false,
|
|
191
|
+
&block
|
|
192
|
+
)
|
|
193
|
+
render_collapsable(
|
|
194
|
+
form: form,
|
|
195
|
+
name: name,
|
|
196
|
+
data_targets: data_targets,
|
|
197
|
+
class_name: "border-1 border-border rounded-xl py-1"
|
|
198
|
+
) do
|
|
199
|
+
div(
|
|
200
|
+
class: "flex gap-2 items-center px-2 mt-2 mb-2 #{hidden ? "hidden" : ""}",
|
|
201
|
+
data: name_params
|
|
202
|
+
) { yield if block_given? }
|
|
203
|
+
if button_text.present? && button_action.present?
|
|
204
|
+
button(
|
|
205
|
+
type: "button",
|
|
206
|
+
class: "text-accent ms-2 mt-1",
|
|
207
|
+
data: {
|
|
208
|
+
action: button_action
|
|
209
|
+
}
|
|
210
|
+
) { heroicon "plus-circle", variant: :outline, options: { class: "w-8 h-8" } }
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
def render_remove_button(action: nil)
|
|
216
|
+
button(type: "button", class: "text-red-500 h-fit self-center", data: { action: action }) do
|
|
217
|
+
heroicon "x-mark", variant: :solid, options: { class: "w-8 h-8" }
|
|
218
|
+
end
|
|
219
|
+
end
|
|
220
|
+
end
|
|
221
|
+
end
|
|
222
|
+
end
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Components
|
|
4
|
+
module Databasium
|
|
5
|
+
class Migrations::HeaderActions < Components::Base
|
|
6
|
+
include Phlex::Rails::Helpers::LinkTo
|
|
7
|
+
include Phlex::Rails::Helpers::Routes
|
|
8
|
+
include Phlex::Rails::Helpers::TurboFrameTag
|
|
9
|
+
include Phlex::Rails::Helpers::ButtonTo
|
|
10
|
+
include Phlex::Rails::Helpers::FormWith
|
|
11
|
+
|
|
12
|
+
def initialize(migration:)
|
|
13
|
+
@migration = migration
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def view_template
|
|
17
|
+
div(id: "header_actions", class: "max-w-full overflow-x-auto flex") do
|
|
18
|
+
render Components::Databasium::Navigation::IconPanel.new(
|
|
19
|
+
icons_with_text: [
|
|
20
|
+
*(
|
|
21
|
+
if @migration
|
|
22
|
+
render_migration_actions
|
|
23
|
+
else
|
|
24
|
+
[]
|
|
25
|
+
end
|
|
26
|
+
),
|
|
27
|
+
{
|
|
28
|
+
icon: "document-plus",
|
|
29
|
+
text: "New Migration",
|
|
30
|
+
method: :get,
|
|
31
|
+
path: databasium.new_migration_path,
|
|
32
|
+
turbo_frame: "main"
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
icon: "forward",
|
|
36
|
+
text: "Run Pending Migrations",
|
|
37
|
+
method: :post,
|
|
38
|
+
path: databasium.run_pending_migrations_migrations_path,
|
|
39
|
+
turbo_frame: "main"
|
|
40
|
+
}
|
|
41
|
+
]
|
|
42
|
+
)
|
|
43
|
+
form_with(
|
|
44
|
+
url: databasium.rollback_migration_migrations_path,
|
|
45
|
+
method: :post,
|
|
46
|
+
class: "w-fit flex gap-2 border-1 border-border rounded-xl bg-background text-sm mx-2"
|
|
47
|
+
) do |form|
|
|
48
|
+
form.number_field :rollback_steps,
|
|
49
|
+
placeholder: "Rollback steps",
|
|
50
|
+
class: "ps-4 w-35 focus:outline-none"
|
|
51
|
+
form.submit "Rollback",
|
|
52
|
+
class: "hover:cursor-pointer hover:text-hover text-accent w-fit pe-4"
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
private
|
|
58
|
+
|
|
59
|
+
def render_migration_actions
|
|
60
|
+
[
|
|
61
|
+
{
|
|
62
|
+
icon: "arrow-up",
|
|
63
|
+
method: :post,
|
|
64
|
+
text: "Run Migration",
|
|
65
|
+
path: databasium.run_migration_migrations_path(version: @migration.version)
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
icon: "arrow-uturn-left",
|
|
69
|
+
method: :post,
|
|
70
|
+
text: "Rollback",
|
|
71
|
+
path: databasium.rollback_migration_migrations_path(version: @migration.version)
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
icon: "backward",
|
|
75
|
+
method: :post,
|
|
76
|
+
text: "Rollback till this migration",
|
|
77
|
+
path:
|
|
78
|
+
databasium.rollback_migration_migrations_path(
|
|
79
|
+
version: @migration.version,
|
|
80
|
+
till_this_migration: true
|
|
81
|
+
)
|
|
82
|
+
}
|
|
83
|
+
]
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Components
|
|
4
|
+
module Databasium
|
|
5
|
+
class Migrations::MigrationStatus < Components::Base
|
|
6
|
+
def initialize(status:, version:)
|
|
7
|
+
@status = status
|
|
8
|
+
@version = version
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def view_template
|
|
12
|
+
div(id: "migration_#{@version}_status") do
|
|
13
|
+
if @status == "pending"
|
|
14
|
+
span(class: "text-red-500") { "Pending" }
|
|
15
|
+
else
|
|
16
|
+
span(class: "text-green-500") { "Applied" }
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
module Components
|
|
2
|
+
module Databasium
|
|
3
|
+
class Migrations::Preview < Components::Base
|
|
4
|
+
def initialize(content:)
|
|
5
|
+
@content = content
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def view_template
|
|
9
|
+
div(id: "migration_preview") do
|
|
10
|
+
div(class: "bg-panel border-1 border-border p-4 rounded-2xl min-h-full") do
|
|
11
|
+
if @content
|
|
12
|
+
h1(class: "text-xl font-semibold mb-3") { "Preview Migration" }
|
|
13
|
+
pre { @content }
|
|
14
|
+
button(
|
|
15
|
+
type: "submit",
|
|
16
|
+
form: "migration_form",
|
|
17
|
+
name: "add_migration",
|
|
18
|
+
value: "Save",
|
|
19
|
+
class: "bg-accent p-2 rounded-md w-fit mt-4"
|
|
20
|
+
) { "Save" }
|
|
21
|
+
else
|
|
22
|
+
h1(class: "text-xl font-semibold") { "Please fill out the form to see the preview" }
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
class Components::Databasium::Migrations::ShowTurboStream < Components::Base
|
|
2
|
+
include Phlex::Rails::Helpers::TurboStream
|
|
3
|
+
|
|
4
|
+
def initialize(migration:, content:)
|
|
5
|
+
@migration = migration
|
|
6
|
+
@content = content
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def view_template
|
|
10
|
+
turbo_stream.replace(
|
|
11
|
+
"migration",
|
|
12
|
+
Components::Databasium::Migrations::File.new(migration: @migration, content: @content)
|
|
13
|
+
)
|
|
14
|
+
turbo_stream.replace(
|
|
15
|
+
"header_actions",
|
|
16
|
+
Components::Databasium::Migrations::HeaderActions.new(migration: @migration)
|
|
17
|
+
)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Components
|
|
4
|
+
module Databasium
|
|
5
|
+
class Migrations::Sidebar < Components::Base
|
|
6
|
+
include Phlex::Rails::Helpers::LinkTo
|
|
7
|
+
include Phlex::Rails::Helpers::FormWith
|
|
8
|
+
include Phlex::Rails::Helpers::ButtonTo
|
|
9
|
+
include Phlex::Rails::Helpers::TurboFrameTag
|
|
10
|
+
|
|
11
|
+
def initialize
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def view_template
|
|
15
|
+
div(class: "flex flex-col gap-2", data: { controller: "search" }) do
|
|
16
|
+
render Components::Databasium::Forms::Search.new(
|
|
17
|
+
url: databasium.sidebar_migrations_path,
|
|
18
|
+
turbo_frame: "results",
|
|
19
|
+
placeholder: "Search for a migration"
|
|
20
|
+
)
|
|
21
|
+
turbo_frame_tag("results", src: databasium.sidebar_migrations_path) do
|
|
22
|
+
p(class: "mt-2 animate-pulse") { "Loading migrations..." }
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
module Components
|
|
2
|
+
module Databasium
|
|
3
|
+
class Models::Attributes < Components::Base
|
|
4
|
+
def initialize(attributes: nil, models: nil)
|
|
5
|
+
@attributes = attributes
|
|
6
|
+
@models = models
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def view_template
|
|
10
|
+
@attributes
|
|
11
|
+
.fetch(:unknown, [])
|
|
12
|
+
.each do |line|
|
|
13
|
+
input(type: "hidden", name: "model[unknown][]", value: line.fetch(:line, line["line"]))
|
|
14
|
+
end
|
|
15
|
+
render_collapsable(
|
|
16
|
+
name: "Pre-filled attributes",
|
|
17
|
+
form: nil,
|
|
18
|
+
class_name: "bg-panel rounded-xl py-2"
|
|
19
|
+
) do
|
|
20
|
+
div(
|
|
21
|
+
class: "rounded-b-xl border border-border overflow-hidden divide-y divide-border mt-2"
|
|
22
|
+
) do
|
|
23
|
+
@attributes
|
|
24
|
+
&.fetch(:columns_hash)
|
|
25
|
+
&.each do |name, attribute|
|
|
26
|
+
render Models::Templates::Attribute.new(name: name, params: attribute)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
render_collapsable(
|
|
31
|
+
name: "Pre-filled relations",
|
|
32
|
+
form: nil,
|
|
33
|
+
data_targets: {
|
|
34
|
+
controller: "relation"
|
|
35
|
+
},
|
|
36
|
+
class_name: "bg-panel mt-2 rounded-xl py-2"
|
|
37
|
+
) do
|
|
38
|
+
div(class: "flex flex-col gap-2 py-2 px-3") do
|
|
39
|
+
@attributes
|
|
40
|
+
&.fetch(:relations)
|
|
41
|
+
&.each do |relation|
|
|
42
|
+
render Models::Templates::Relation.new(relation: relation, models: @models)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Components
|
|
4
|
+
module Databasium
|
|
5
|
+
class Models::Form < Components::Base
|
|
6
|
+
include Phlex::Rails::Helpers::FormWith
|
|
7
|
+
|
|
8
|
+
def initialize(attributes: nil, model: nil, models: nil)
|
|
9
|
+
@attributes = attributes
|
|
10
|
+
@model = model
|
|
11
|
+
@models = models
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def view_template
|
|
15
|
+
form_with(
|
|
16
|
+
url: databasium.models_path,
|
|
17
|
+
method: :post,
|
|
18
|
+
scope: :model,
|
|
19
|
+
html: {
|
|
20
|
+
id: "model_form"
|
|
21
|
+
}
|
|
22
|
+
) do |form|
|
|
23
|
+
render_model_name(form)
|
|
24
|
+
render_form
|
|
25
|
+
render_attributes_container
|
|
26
|
+
render_relations_container
|
|
27
|
+
render_unknown
|
|
28
|
+
form.submit "Create preview for model",
|
|
29
|
+
class: "bg-accent shadow-accent rounded-xl p-1 p-2 mt-2 w-full text-center"
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
private
|
|
34
|
+
|
|
35
|
+
def render_unknown
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def render_attributes_container
|
|
39
|
+
render_collapsable(
|
|
40
|
+
name: @model.present? ? "New Attributes" : "Attributes",
|
|
41
|
+
form: nil,
|
|
42
|
+
class_name: "bg-panel rounded-xl py-2 mt-2"
|
|
43
|
+
) do
|
|
44
|
+
div(
|
|
45
|
+
class: "rounded-b-xl border border-border divide-y divide-border mt-2",
|
|
46
|
+
data: {
|
|
47
|
+
model_target: "attributesContainer"
|
|
48
|
+
}
|
|
49
|
+
) { }
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def render_relations_container
|
|
54
|
+
render_collapsable(
|
|
55
|
+
name: @model.present? ? "New Relations" : "Relations",
|
|
56
|
+
form: nil,
|
|
57
|
+
class_name: "bg-panel rounded-xl py-2 mt-2",
|
|
58
|
+
data_targets: {
|
|
59
|
+
controller: "relation"
|
|
60
|
+
}
|
|
61
|
+
) do
|
|
62
|
+
div(
|
|
63
|
+
class: "flex flex-col gap-2 py-2 px-3",
|
|
64
|
+
data: {
|
|
65
|
+
model_target: "relationsContainer"
|
|
66
|
+
}
|
|
67
|
+
) { }
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def render_model_name(form)
|
|
72
|
+
div(class: "flex items-center mb-3 text-xl") do
|
|
73
|
+
form.label :model_name, "Name:", class: "font-semibold pe-2"
|
|
74
|
+
form.text_field :model_name,
|
|
75
|
+
value: @model,
|
|
76
|
+
class:
|
|
77
|
+
"border-1 w-full rounded-xl p-1 border-border bg-panel w-fit focus:outline-none"
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def render_form
|
|
82
|
+
if @attributes.present?
|
|
83
|
+
render Components::Databasium::Models::Attributes.new(
|
|
84
|
+
attributes: @attributes,
|
|
85
|
+
models: @models
|
|
86
|
+
)
|
|
87
|
+
end
|
|
88
|
+
template(data: { model_target: "attribute" }) do
|
|
89
|
+
render Components::Databasium::Models::Templates::Attribute.new
|
|
90
|
+
end
|
|
91
|
+
template(data: { model_target: "relation" }) do
|
|
92
|
+
render Components::Databasium::Models::Templates::Relation.new(models: @models)
|
|
93
|
+
end
|
|
94
|
+
template(data: { model_target: "validation" }) do
|
|
95
|
+
render Components::Databasium::Models::Templates::Validation.new
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Components
|
|
4
|
+
module Databasium
|
|
5
|
+
class Models::HeaderActions < Components::Base
|
|
6
|
+
include Phlex::Rails::Helpers::LinkTo
|
|
7
|
+
include Phlex::Rails::Helpers::Routes
|
|
8
|
+
include Phlex::Rails::Helpers::TurboFrameTag
|
|
9
|
+
include Phlex::Rails::Helpers::ButtonTo
|
|
10
|
+
def initialize(model: nil)
|
|
11
|
+
@model = model
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def view_template
|
|
15
|
+
div(id: "header_actions", class: "max-w-full overflow-x-auto") do
|
|
16
|
+
render Components::Databasium::Navigation::IconPanel.new(
|
|
17
|
+
icons_with_text: [
|
|
18
|
+
{
|
|
19
|
+
icon: "plus-circle",
|
|
20
|
+
text: "Add attribute",
|
|
21
|
+
method: :frontend,
|
|
22
|
+
data_params: {
|
|
23
|
+
action: "click->model#add",
|
|
24
|
+
model_target_param: "attribute",
|
|
25
|
+
model_container_param: "attributesContainer"
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
icon: "plus-circle",
|
|
30
|
+
text: "Add relation",
|
|
31
|
+
method: :frontend,
|
|
32
|
+
data_params: {
|
|
33
|
+
action: "click->model#add",
|
|
34
|
+
model_target_param: "relation",
|
|
35
|
+
model_container_param: "relationsContainer"
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
icon: "document-plus",
|
|
40
|
+
text: "New model",
|
|
41
|
+
method: :get,
|
|
42
|
+
path: databasium.new_model_path,
|
|
43
|
+
turbo_frame: "main"
|
|
44
|
+
}
|
|
45
|
+
]
|
|
46
|
+
)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|