Skip to content

Commit

Permalink
Implement UI (#83)
Browse files Browse the repository at this point in the history
* Add UI

* fixup! Add UI

* fixup! fixup! Add UI

* Add tests draft

* Add tests

* fixup! Add tests

* fixup! fixup! Add tests

* Refactoring

* fixup! Refactoring

* fixup! fixup! Refactoring

* fixup! fixup! fixup! Refactoring

* fixup! fixup! fixup! fixup! Refactoring

* fixup! fixup! fixup! fixup! fixup! Refactoring

* fixup! fixup! fixup! fixup! fixup! fixup! Refactoring

* Add Migration class

* fixup! Add Migration class

* fixup! fixup! Add Migration class

* Add DatabaseConnection class

* Add unecode icons to buttons

* fixup! Add DatabaseConnection class

* fixup! fixup! Add DatabaseConnection class

* fixup! fixup! fixup! fixup! fixup! fixup! fixup! Refactoring

* fixup! fixup! fixup! fixup! fixup! fixup! fixup! fixup! Refactoring

* fixup! fixup! fixup! Add tests

* Add new env var for "disabled"

* Remove railtie

* fixup! fixup! fixup! Add DatabaseConnection class

* fixup! fixup! fixup! fixup! fixup! fixup! fixup! fixup! fixup! Refactoring

* Memoize helper methods

* Rename migrations to phantom migrations

* Fix render not_found and add test

* Revert changes for metadata method

* add migration not found text

* hide "down" migrations

* fix tests

* fixup! fix tests

* Reduce Test Execution Time

* Add migrations controller

* fixup! Add migrations controller

* fixup! fixup! Add migrations controller

* fixup! fixup! fixup! Add migrations controller

* Add test

* Add buttons

* Add migrate button

* Fix tests

* fixup! fixup! fixup! fixup! Add migrations controller

* Fix Test

* show only the relevant buttons

* remove debugger

* Truncate name field

* Change the sorting to DESC

* fix buttons style

* hide migrations with down status

* revert changes

* fix tests

* fixup! fix tests

* Update .gitignore to ignore all .rb files in db and its subdirectories

* fix migrations list

* hide migrations with down status

* Add Rollback All button

* Add test

* fix warning

* fix rollback_all

* fix

* fixup! fix

* fix background colors for rows

---------

Co-authored-by: Vladislav Sokov <[email protected]>
  • Loading branch information
ka8725 and VladislavSokov authored Jul 19, 2024
1 parent bd295f1 commit 528a929
Show file tree
Hide file tree
Showing 31 changed files with 941 additions and 117 deletions.
3 changes: 1 addition & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@
/spec/reports/
/tmp/
/test/dummy_app/tmp/
/test/dummy_app/db/*/*.rb
/test/dummy_app/db/*.rb
/test/dummy_app/db/**/*.rb
.ruby-version
.ruby-gemset
/gemfiles/*.gemfile.lock
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## [0.7.6] - 2024-07-05
- Added UI
- Added environment variable `ACTUAL_DB_SCHEMA_UI_ENABLED` to enable/disable the UI in specific environments
- Added configuration option `ActualDbSchema.config[:ui_enabled]` to enable/disable the UI in specific environments

## [0.7.5] - 2024-06-20
- Added db:rollback_migrations:manual task to manually rolls back phantom migrations one by one

Expand Down
29 changes: 29 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,35 @@ The gem offers the following rake tasks that can be manually run according to yo
- `rails db:rollback_branches:manual` - run it to manually rolls back phantom migrations one by one.
- `rails db:phantom_migrations` - displays a list of phantom migrations.

## Accessing the UI

The UI for managing migrations is enabled automatically. To access the UI, simply navigate to the following URL in your web browser:
```
http://localhost:3000/rails/phantom_migrations
```
This page displays a list of phantom migrations for each database connection and provides options to view details and rollback them.

## UI options

By default, the UI is enabled in the development environment. If you prefer to enable the UI for another environment, you can do so in two ways:

### 1. Using Environment Variable

Set the environment variable `ACTUAL_DB_SCHEMA_UI_ENABLED` to `true`:

```sh
export ACTUAL_DB_SCHEMA_UI_ENABLED=true
```

### 2. Using Initializer
Add the following line to your initializer file (`config/initializers/actual_db_schema.rb`):

```ruby
ActualDbSchema.config[:ui_enabled] = true
```

> With this option, the UI can be disabled for all environments or be enabled in specific ones.
## Disabling Automatic Rollback

By default, the automatic rollback of migrations is enabled. If you prefer to perform manual rollbacks, you can disable the automatic rollback in two ways:
Expand Down
92 changes: 92 additions & 0 deletions app/assets/stylesheets/actual_db_schema/styles.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
body {
margin: 8px;
background-color: #fff;
color: #333;
}

body, p, td {
font-family: helvetica, verdana, arial, sans-serif;
font-size: 13px;
line-height: 18px;
}

h2 {
padding-left: 10px;
}

table {
margin: 0;
border-collapse: collapse;

thead tr {
border-bottom: 2px solid #ddd;
}

tbody {
.migration-row.phantom {
background-color: #fff3f3;
}

.migration-row.normal {
background-color: #ffffff;
}

.migration-row:nth-child(odd).phantom {
background-color: #ffe6e6;
}

.migration-row:nth-child(odd).normal {
background-color: #f9f9f9;
}
}

td {
padding: 14px 30px;
}
}

.top-buttons {
margin: 8px;
display: flex;
align-items: center;

.top-button {
background-color: #ddd;
}
}

.button, .top-button {
font-weight: bold;
color: #000;
border: none;
padding: 5px 10px;
text-align: center;
text-decoration: none;
display: inline-block;
margin: 0 2px;
cursor: pointer;
border-radius: 4px;
transition: background-color 0.3s;
background: none;
}

.button:hover, .top-button:hover {
color: #fff;
background-color: #000;
}

.button-container {
display: flex;
}

pre {
background-color: #f7f7f7;
padding: 10px;
border: 1px solid #ddd;
}

.truncate-text {
max-width: 200px;
overflow: hidden;
text-overflow: ellipsis;
}
32 changes: 32 additions & 0 deletions app/controllers/actual_db_schema/migrations_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# frozen_string_literal: true

module ActualDbSchema
# Controller to display the list of migrations for each database connection.
class MigrationsController < ActionController::Base
def index; end

def show
render file: "#{Rails.root}/public/404.html", layout: false, status: :not_found unless migration
end

def rollback
ActualDbSchema::Migration.instance.rollback(params[:id], params[:database])
redirect_to migrations_path
end

def migrate
ActualDbSchema::Migration.instance.migrate(params[:id], params[:database])
redirect_to migrations_path
end

private

helper_method def migrations
@migrations ||= ActualDbSchema::Migration.instance.all
end

helper_method def migration
@migration ||= ActualDbSchema::Migration.instance.find(params[:id], params[:database])
end
end
end
32 changes: 32 additions & 0 deletions app/controllers/actual_db_schema/phantom_migrations_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# frozen_string_literal: true

module ActualDbSchema
# Controller to display the list of phantom migrations for each database connection.
class PhantomMigrationsController < ActionController::Base
def index; end

def show
render file: "#{Rails.root}/public/404.html", layout: false, status: :not_found unless phantom_migration
end

def rollback
ActualDbSchema::Migration.instance.rollback(params[:id], params[:database])
redirect_to phantom_migrations_path
end

def rollback_all
ActualDbSchema::Migration.instance.rollback_all
redirect_to phantom_migrations_path
end

private

helper_method def phantom_migrations
@phantom_migrations ||= ActualDbSchema::Migration.instance.all_phantom
end

helper_method def phantom_migration
@phantom_migration ||= ActualDbSchema::Migration.instance.find(params[:id], params[:database])
end
end
end
66 changes: 66 additions & 0 deletions app/views/actual_db_schema/migrations/index.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<!DOCTYPE html>
<html>
<head>
<title>Migrations</title>
<%= stylesheet_link_tag 'actual_db_schema/styles', media: 'all' %>
</head>
<body>
<div>
<h2>Migrations</h2>
<p>
<span style="background-color: #ffe6e6; padding: 0 5px;">Red rows</span> represent phantom migrations.
</p>
<div class="top-buttons">
<%= link_to 'Phantom Migrations', phantom_migrations_path, class: "top-button" %>
</div>
<% if migrations.present? %>
<table>
<thead>
<tr>
<th>Status</th>
<th>Migration ID</th>
<th>Name</th>
<th>Branch</th>
<th>Database</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% migrations.each do |migration| %>
<tr class="migration-row <%= migration[:phantom] ? 'phantom' : 'normal' %>">
<td><%= migration[:status] %></td>
<td><%= migration[:version] %></td>
<td>
<div class="truncate-text" title="<%= migration[:name] %>">
<%= migration[:name] %>
</div>
</td>
<td><%= migration[:branch] %></td>
<td><%= migration[:database] %></td>
<td>
<div class='button-container'>
<%= link_to '👁 Show',
migration_path(id: migration[:version], database: migration[:database]),
class: 'button' %>
<%= button_to '⎌ Rollback',
rollback_migration_path(id: migration[:version], database: migration[:database]),
method: :post,
class: 'button',
style: ('display: none;' if migration[:status] == "down") %>
<%= button_to '⬆ Migrate',
migrate_migration_path(id: migration[:version], database: migration[:database]),
method: :post,
class: 'button',
style: ('display: none;' if migration[:status] == "up" || migration[:phantom]) %>
</div>
</td>
</tr>
<% end %>
</tbody>
</table>
<% else %>
<p>No migrations found.</p>
<% end %>
</div>
</body>
</html>
54 changes: 54 additions & 0 deletions app/views/actual_db_schema/migrations/show.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<!DOCTYPE html>
<html>
<head>
<title>Migration Details</title>
<%= stylesheet_link_tag 'actual_db_schema/styles', media: 'all' %>
</head>
<body>
<div>
<h2>Migration <%= migration[:name] %> Details</h2>
<table>
<tbody>
<tr>
<th>Status</th>
<td><%= migration[:status] %></td>
</tr>
<tr>
<th>Migration ID</th>
<td><%= migration[:version] %></td>
</tr>
<tr>
<th>Branch</th>
<td><%= migration[:branch] %></td>
</tr>
<tr>
<th>Database</th>
<td><%= migration[:database] %></td>
</tr>
<tr>
<th>Path</th>
<td><%= migration[:filename] %></td>
</tr>
</tbody>
</table>

<h3>Migration Code</h3>
<div>
<pre><%= File.read(migration[:filename]) %></pre>
</div>
<div class='button-container'>
<%= link_to '← Back', migrations_path, class: 'button' %>
<%= button_to '⎌ Rollback',
rollback_migration_path(id: migration[:version], database: migration[:database]),
method: :post,
class: 'button',
style: ('display: none;' if migration[:status] == "down") %>
<%= button_to '⬆ Migrate',
migrate_migration_path(id: migration[:version], database: migration[:database]),
method: :post,
class: 'button',
style: ('display: none;' if migration[:status] == "up" || migration[:phantom]) %>
</div>
</div>
</body>
</html>
55 changes: 55 additions & 0 deletions app/views/actual_db_schema/phantom_migrations/index.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<!DOCTYPE html>
<html>
<head>
<title>Phantom Migrations</title>
<%= stylesheet_link_tag 'actual_db_schema/styles', media: 'all' %>
</head>
<body>
<div>
<h2>Phantom Migrations</h2>
<div class="top-buttons">
<%= link_to 'All Migrations', migrations_path, class: "top-button" %>
<% if phantom_migrations.present? %>
<%= button_to '⎌ Rollback all', rollback_all_phantom_migrations_path, method: :post, class: 'button' %>
<% end %>
</div>
<% if phantom_migrations.present? %>
<table>
<thead>
<tr>
<th>Status</th>
<th>Migration ID</th>
<th>Name</th>
<th>Branch</th>
<th>Database</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<% phantom_migrations.each do |migration| %>
<tr class="migration-row phantom">
<td><%= migration[:status] %></td>
<td><%= migration[:version] %></td>
<td>
<div class="truncate-text" title="<%= migration[:name] %>">
<%= migration[:name] %>
</div>
</td>
<td><%= migration[:branch] %></td>
<td><%= migration[:database] %></td>
<td>
<div class='button-container'>
<%= link_to '👁 Show', phantom_migration_path(id: migration[:version], database: migration[:database]), class: 'button' %>
<%= button_to '⎌ Rollback', rollback_phantom_migration_path(id: migration[:version], database: migration[:database]), method: :post, class: 'button' %>
</div>
</td>
</tr>
<% end %>
</tbody>
</table>
<% else %>
<p>No phantom migrations found.</p>
<% end %>
</div>
</body>
</html>
Loading

0 comments on commit 528a929

Please sign in to comment.