dbdoc_engine 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.
Files changed (198) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +331 -0
  3. data/Rakefile +8 -0
  4. data/app/assets/builds/dbdoc_engine/application.css +5 -0
  5. data/app/assets/images/dbdoc_engine/arrowdown.svg +3 -0
  6. data/app/assets/images/dbdoc_engine/arrowhorizontal.svg +3 -0
  7. data/app/assets/images/dbdoc_engine/arrowleft.svg +3 -0
  8. data/app/assets/images/dbdoc_engine/changelog.svg +3 -0
  9. data/app/assets/images/dbdoc_engine/column_stats_dbdocs.svg +23 -0
  10. data/app/assets/images/dbdoc_engine/diagram.svg +3 -0
  11. data/app/assets/images/dbdoc_engine/double_arrow.svg +4 -0
  12. data/app/assets/images/dbdoc_engine/group_bu.svg +3 -0
  13. data/app/assets/images/dbdoc_engine/japan_circle.png +0 -0
  14. data/app/assets/images/dbdoc_engine/log_in_image.png +0 -0
  15. data/app/assets/images/dbdoc_engine/logo.svg +12 -0
  16. data/app/assets/images/dbdoc_engine/orange_changelog.svg +3 -0
  17. data/app/assets/images/dbdoc_engine/orange_fields.svg +23 -0
  18. data/app/assets/images/dbdoc_engine/orange_logo.svg +12 -0
  19. data/app/assets/images/dbdoc_engine/orange_table.svg +21 -0
  20. data/app/assets/images/dbdoc_engine/orange_updates.svg +43 -0
  21. data/app/assets/images/dbdoc_engine/orange_wiki.svg +3 -0
  22. data/app/assets/images/dbdoc_engine/search.svg +3 -0
  23. data/app/assets/images/dbdoc_engine/setting.svg +3 -0
  24. data/app/assets/images/dbdoc_engine/table_dbdocs.svg +21 -0
  25. data/app/assets/images/dbdoc_engine/uk_circle_transparent.png +0 -0
  26. data/app/assets/images/dbdoc_engine/update_stats_dbdocs.svg +43 -0
  27. data/app/assets/images/dbdoc_engine/wiki.svg +3 -0
  28. data/app/assets/stylesheets/dbdoc_engine/admin.css +176 -0
  29. data/app/assets/stylesheets/dbdoc_engine/admin_header.css +179 -0
  30. data/app/assets/stylesheets/dbdoc_engine/application.scss +1 -0
  31. data/app/assets/stylesheets/dbdoc_engine/changelog.css +173 -0
  32. data/app/assets/stylesheets/dbdoc_engine/dashboard.css +513 -0
  33. data/app/assets/stylesheets/dbdoc_engine/dbdoc_application.css +117 -0
  34. data/app/assets/stylesheets/dbdoc_engine/ecommerce.css +253 -0
  35. data/app/assets/stylesheets/dbdoc_engine/group_details.css +178 -0
  36. data/app/assets/stylesheets/dbdoc_engine/header.css +212 -0
  37. data/app/assets/stylesheets/dbdoc_engine/loading_spinner.css +127 -0
  38. data/app/assets/stylesheets/dbdoc_engine/login.css +213 -0
  39. data/app/assets/stylesheets/dbdoc_engine/schema_diagram.css +149 -0
  40. data/app/assets/stylesheets/dbdoc_engine/sidebar.css +296 -0
  41. data/app/assets/stylesheets/dbdoc_engine/table_details.css +417 -0
  42. data/app/controllers/dbdoc_engine/admin/base_controller.rb +23 -0
  43. data/app/controllers/dbdoc_engine/admin/dashboard_controller.rb +16 -0
  44. data/app/controllers/dbdoc_engine/admin/data_transfer_controller.rb +63 -0
  45. data/app/controllers/dbdoc_engine/admin/db_design_dynamic_tables_controller.rb +198 -0
  46. data/app/controllers/dbdoc_engine/admin/db_design_table_groups_controller.rb +107 -0
  47. data/app/controllers/dbdoc_engine/application_controller.rb +65 -0
  48. data/app/controllers/dbdoc_engine/concerns/internationalization.rb +57 -0
  49. data/app/controllers/dbdoc_engine/db_doc_sessions_controller.rb +33 -0
  50. data/app/controllers/dbdoc_engine/home_controller.rb +79 -0
  51. data/app/controllers/dbdoc_engine/schema_diagram_controller.rb +293 -0
  52. data/app/helper/dbdoc_engine/application_helper.rb +35 -0
  53. data/app/helpers/dbdoc_engine/application_helper.rb +4 -0
  54. data/app/helpers/dbdoc_engine/changelogs_helper.rb +27 -0
  55. data/app/helpers/dbdoc_engine/column_helper.rb +30 -0
  56. data/app/helpers/dbdoc_engine/db_design_dynamic_tables_helper.rb +15 -0
  57. data/app/helpers/dbdoc_engine/home_helper.rb +75 -0
  58. data/app/javascript/dbdoc_engine/application.js +12 -0
  59. data/app/javascript/dbdoc_engine/controllers/application.js +29 -0
  60. data/app/javascript/dbdoc_engine/controllers/auto_submit_controller.js +17 -0
  61. data/app/javascript/dbdoc_engine/controllers/chart_controller.js +58 -0
  62. data/app/javascript/dbdoc_engine/controllers/column-type_controller.js +149 -0
  63. data/app/javascript/dbdoc_engine/controllers/column_controller.js +362 -0
  64. data/app/javascript/dbdoc_engine/controllers/column_search_controller.js +42 -0
  65. data/app/javascript/dbdoc_engine/controllers/dbdoc_accordion_controller.js +42 -0
  66. data/app/javascript/dbdoc_engine/controllers/ecommerce_controller.js +73 -0
  67. data/app/javascript/dbdoc_engine/controllers/group_details_controller.js +88 -0
  68. data/app/javascript/dbdoc_engine/controllers/import_export_controller.js +200 -0
  69. data/app/javascript/dbdoc_engine/controllers/index.js +9 -0
  70. data/app/javascript/dbdoc_engine/controllers/language_controller.js +100 -0
  71. data/app/javascript/dbdoc_engine/controllers/loading_spinner_controller.js +48 -0
  72. data/app/javascript/dbdoc_engine/controllers/login_controller.js +75 -0
  73. data/app/javascript/dbdoc_engine/controllers/notification_controller.js +15 -0
  74. data/app/javascript/dbdoc_engine/controllers/schema_diagram_controller.js +1129 -0
  75. data/app/javascript/dbdoc_engine/controllers/select2_controller.js +67 -0
  76. data/app/javascript/dbdoc_engine/controllers/sidebar_controller.js +943 -0
  77. data/app/javascript/dbdoc_engine/controllers/table_details_controller.js +245 -0
  78. data/app/javascript/dbdoc_engine/controllers/table_group_validation_controller.js +148 -0
  79. data/app/javascript/dbdoc_engine/controllers/table_validation_controller.js +423 -0
  80. data/app/jobs/dbdoc_engine/application_job.rb +4 -0
  81. data/app/mailers/dbdoc_engine/application_mailer.rb +6 -0
  82. data/app/models/dbdoc_engine/application_record.rb +6 -0
  83. data/app/models/dbdoc_engine/concerns/soft_deletable.rb +30 -0
  84. data/app/models/dbdoc_engine/db_design_changelog.rb +44 -0
  85. data/app/models/dbdoc_engine/db_design_dynamic_column.rb +211 -0
  86. data/app/models/dbdoc_engine/db_design_dynamic_table.rb +124 -0
  87. data/app/models/dbdoc_engine/db_design_table_group.rb +88 -0
  88. data/app/models/dbdoc_engine/user.rb +21 -0
  89. data/app/queries/dbdoc_engine/admin_dashboard_queries.rb +71 -0
  90. data/app/queries/dbdoc_engine/db_design_changelog_queries.rb +68 -0
  91. data/app/queries/dbdoc_engine/db_design_dynamic_column_queries.rb +37 -0
  92. data/app/queries/dbdoc_engine/db_design_dynamic_table_commands.rb +106 -0
  93. data/app/queries/dbdoc_engine/db_design_dynamic_table_queries.rb +194 -0
  94. data/app/queries/dbdoc_engine/db_design_table_group_queries.rb +154 -0
  95. data/app/services/dbdoc_engine/db_design_dynamic_table_export_service.rb +38 -0
  96. data/app/services/dbdoc_engine/db_design_dynamic_table_handler_service.rb +49 -0
  97. data/app/services/dbdoc_engine/db_design_dynamic_tables_service.rb +21 -0
  98. data/app/services/dbdoc_engine/error_handler_service.rb +43 -0
  99. data/app/services/dbdoc_engine/schema_rb_import_service.rb +194 -0
  100. data/app/services/dbdoc_engine/schema_rb_parser_service.rb +339 -0
  101. data/app/services/dbdoc_engine/table_filter_service.rb +35 -0
  102. data/app/services/dbdoc_engine/table_groups_service.rb +199 -0
  103. data/app/services/dbdoc_engine/table_management_service.rb +192 -0
  104. data/app/views/dbdoc_engine/admin/dashboard/_action_badge.html.erb +11 -0
  105. data/app/views/dbdoc_engine/admin/dashboard/_changelog_rows.html.erb +22 -0
  106. data/app/views/dbdoc_engine/admin/dashboard/_changelog_table_headers.html.erb +8 -0
  107. data/app/views/dbdoc_engine/admin/dashboard/_filter_fields.html.erb +43 -0
  108. data/app/views/dbdoc_engine/admin/dashboard/index.html.erb +159 -0
  109. data/app/views/dbdoc_engine/admin/db_design_dynamic_tables/_column_fields.html.erb +225 -0
  110. data/app/views/dbdoc_engine/admin/db_design_dynamic_tables/_deleted_table_index.html.erb +110 -0
  111. data/app/views/dbdoc_engine/admin/db_design_dynamic_tables/_foreign_key_fields.html.erb +51 -0
  112. data/app/views/dbdoc_engine/admin/db_design_dynamic_tables/_form.html.erb +75 -0
  113. data/app/views/dbdoc_engine/admin/db_design_dynamic_tables/_recent_activity.html.erb +39 -0
  114. data/app/views/dbdoc_engine/admin/db_design_dynamic_tables/_table_columns.html.erb +127 -0
  115. data/app/views/dbdoc_engine/admin/db_design_dynamic_tables/_table_index.html.erb +109 -0
  116. data/app/views/dbdoc_engine/admin/db_design_dynamic_tables/_table_information.html.erb +99 -0
  117. data/app/views/dbdoc_engine/admin/db_design_dynamic_tables/deleted_tables.html.erb +95 -0
  118. data/app/views/dbdoc_engine/admin/db_design_dynamic_tables/edit.html.erb +23 -0
  119. data/app/views/dbdoc_engine/admin/db_design_dynamic_tables/export_all_to_excel.xlsx.axlsx +240 -0
  120. data/app/views/dbdoc_engine/admin/db_design_dynamic_tables/export_to_excel.xlsx.axlsx +135 -0
  121. data/app/views/dbdoc_engine/admin/db_design_dynamic_tables/index.html.erb +109 -0
  122. data/app/views/dbdoc_engine/admin/db_design_dynamic_tables/new.html.erb +25 -0
  123. data/app/views/dbdoc_engine/admin/db_design_dynamic_tables/show_table_info.html.erb +125 -0
  124. data/app/views/dbdoc_engine/admin/db_design_table_groups/_deleted_table_groups_list.html.erb +75 -0
  125. data/app/views/dbdoc_engine/admin/db_design_table_groups/_form.html.erb +88 -0
  126. data/app/views/dbdoc_engine/admin/db_design_table_groups/_table_groups_list.html.erb +82 -0
  127. data/app/views/dbdoc_engine/admin/db_design_table_groups/deleted_groups.html.erb +60 -0
  128. data/app/views/dbdoc_engine/admin/db_design_table_groups/edit.html.erb +25 -0
  129. data/app/views/dbdoc_engine/admin/db_design_table_groups/index.html.erb +85 -0
  130. data/app/views/dbdoc_engine/admin/db_design_table_groups/new.html.erb +26 -0
  131. data/app/views/dbdoc_engine/db_doc_sessions/new.html.erb +59 -0
  132. data/app/views/dbdoc_engine/home/changelog_details.html.erb +80 -0
  133. data/app/views/dbdoc_engine/home/changelogs.html.erb +20 -0
  134. data/app/views/dbdoc_engine/home/group_details.html.erb +94 -0
  135. data/app/views/dbdoc_engine/home/index.html.erb +11 -0
  136. data/app/views/dbdoc_engine/home/partials/_action_badge.html.erb +11 -0
  137. data/app/views/dbdoc_engine/home/partials/_breadcrumb_navigation.html.erb +30 -0
  138. data/app/views/dbdoc_engine/home/partials/_changelog_rows.html.erb +35 -0
  139. data/app/views/dbdoc_engine/home/partials/_changelog_table_headers.html.erb +16 -0
  140. data/app/views/dbdoc_engine/home/partials/_column_headers.html.erb +23 -0
  141. data/app/views/dbdoc_engine/home/partials/_column_row.html.erb +157 -0
  142. data/app/views/dbdoc_engine/home/partials/_filter_form.html.erb +47 -0
  143. data/app/views/dbdoc_engine/home/partials/_group_section.html.erb +84 -0
  144. data/app/views/dbdoc_engine/home/partials/_pagination.html.erb +5 -0
  145. data/app/views/dbdoc_engine/home/partials/_stats_container.html.erb +46 -0
  146. data/app/views/dbdoc_engine/home/partials/_table_groups.html.erb +7 -0
  147. data/app/views/dbdoc_engine/home/partials/_table_information_section.html.erb +50 -0
  148. data/app/views/dbdoc_engine/home/partials/_table_section.html.erb +48 -0
  149. data/app/views/dbdoc_engine/home/table_details.html.erb +9 -0
  150. data/app/views/dbdoc_engine/schema_diagram/index.html.erb +102 -0
  151. data/app/views/dbdoc_engine/shared/_admin_header.html.erb +78 -0
  152. data/app/views/dbdoc_engine/shared/_header.html.erb +94 -0
  153. data/app/views/dbdoc_engine/shared/_js_translations.html.erb +3 -0
  154. data/app/views/dbdoc_engine/shared/_language_button.html.erb +14 -0
  155. data/app/views/dbdoc_engine/shared/_sidebar.html.erb +128 -0
  156. data/app/views/kaminari/dbdoc_engine/_first_page.html.erb +3 -0
  157. data/app/views/kaminari/dbdoc_engine/_gap.html.erb +3 -0
  158. data/app/views/kaminari/dbdoc_engine/_last_page.html.erb +3 -0
  159. data/app/views/kaminari/dbdoc_engine/_next_page.html.erb +3 -0
  160. data/app/views/kaminari/dbdoc_engine/_page.html.erb +9 -0
  161. data/app/views/kaminari/dbdoc_engine/_paginator.html.erb +17 -0
  162. data/app/views/kaminari/dbdoc_engine/_prev_page.html.erb +3 -0
  163. data/app/views/layouts/dbdoc_engine/application.html.erb +107 -0
  164. data/app/views/layouts/dbdoc_engine/header.html.erb +108 -0
  165. data/config/importmap.rb +11 -0
  166. data/config/locales/en.yml +307 -0
  167. data/config/locales/ja.yml +306 -0
  168. data/config/routes.rb +73 -0
  169. data/db/migrate/rails7/20250227060610_create_db_design_table_groups.rb +15 -0
  170. data/db/migrate/rails7/20250227094626_create_db_design_dynamic_tables.rb +19 -0
  171. data/db/migrate/rails7/20250228022732_create_db_design_dynamic_columns.rb +34 -0
  172. data/db/migrate/rails7/20250401051453_create_db_design_changelogs.rb +26 -0
  173. data/db/migrate/rails7/20250411040822_create_users.rb +14 -0
  174. data/db/migrate/rails7/20250421080851_add_missing_indexes_to_dbdoc_tables.rb +23 -0
  175. data/db/migrate/rails8/20250227060610_create_db_design_table_groups.rb +15 -0
  176. data/db/migrate/rails8/20250227094626_create_db_design_dynamic_tables.rb +19 -0
  177. data/db/migrate/rails8/20250228022732_create_db_design_dynamic_columns.rb +34 -0
  178. data/db/migrate/rails8/20250401051453_create_db_design_changelogs.rb +26 -0
  179. data/db/migrate/rails8/20250411040822_create_users.rb +14 -0
  180. data/db/migrate/rails8/20250421080851_add_missing_indexes_to_dbdoc_tables.rb +23 -0
  181. data/db/seeds.rb +28 -0
  182. data/lib/dbdoc_engine/engine.rb +57 -0
  183. data/lib/dbdoc_engine/version.rb +3 -0
  184. data/lib/dbdoc_engine.rb +9 -0
  185. data/lib/generators/dbdoc_engine/install/install_generator.rb +245 -0
  186. data/lib/generators/dbdoc_engine/uninstall/uninstall_generator.rb +196 -0
  187. data/lib/tasks/dbdoc_engine_tasks.rake +44 -0
  188. data/public/dbdoc_engine_assets/images/camel_chess_head.png +0 -0
  189. data/public/dbdoc_engine_assets/images/dblogo.svg +4 -0
  190. data/public/dbdoc_engine_assets/images/japan_circle.png +0 -0
  191. data/public/dbdoc_engine_assets/images/king_chess_head.png +0 -0
  192. data/public/dbdoc_engine_assets/images/login-bg.svg +44 -0
  193. data/public/dbdoc_engine_assets/images/logo.png +0 -0
  194. data/public/dbdoc_engine_assets/images/logo.svg +12 -0
  195. data/public/dbdoc_engine_assets/images/queen_chess_head.png +0 -0
  196. data/public/dbdoc_engine_assets/images/soldier_chess_headd.png +0 -0
  197. data/public/dbdoc_engine_assets/images/uk_circle_transparent.png +0 -0
  198. metadata +415 -0
@@ -0,0 +1,135 @@
1
+ # app/views/admin/db_design/dynamic_tables/export_to_excel.xlsx.axlsx
2
+ # rubocop:disable Metrics/BlockLength
3
+ wb = xlsx_package.workbook
4
+
5
+ t = ->(key) { I18n.t("dbdoc.excel.#{key}") }
6
+
7
+ # Table Info Sheet
8
+ wb.add_worksheet(name: @table.table_name.truncate(30, omission: "")) do |sheet|
9
+ sheet.sheet_view.show_grid_lines = false
10
+ # Styles
11
+ detail_header_style = sheet.styles.add_style(
12
+ bg_color: "FFFF00",
13
+ border: { style: :thin, color: "000000" }
14
+ )
15
+ column_header_style = sheet.styles.add_style(
16
+ bg_color: "FFFFFF",
17
+ b: true,
18
+ border: { style: :medium, color: "000000" },
19
+ alignment: { horizontal: :center, vertical: :center }
20
+ )
21
+ detail_cell_style = sheet.styles.add_style(
22
+ border: { style: :thin, color: "000000" },
23
+ alignment: { horizontal: :left }
24
+ )
25
+ centered_cell_style = sheet.styles.add_style(
26
+ border: { style: :thin, color: "000000" },
27
+ alignment: { horizontal: :center }
28
+ )
29
+ note_header_style = sheet.styles.add_style(
30
+ bg_color: "FFFFFF",
31
+ border: { style: :thin, color: "000000" },
32
+ alignment: { horizontal: :center }
33
+ )
34
+ no_border_style = sheet.styles.add_style(
35
+ bg_color: "FFFFFF"
36
+ )
37
+
38
+ # Table Header Section
39
+ sheet.add_row [ "", t.call("category"), t.call("master") ], style: [ no_border_style, detail_header_style, detail_header_style ]
40
+
41
+ sheet.rows.size
42
+
43
+ sheet.add_row([ "", t.call("no"), "1" ], style: [ no_border_style, detail_header_style, detail_cell_style ])
44
+ sheet.add_row([ "", t.call("physical_table_name"), @table.physical_table_name ], style: [ no_border_style, detail_header_style, detail_cell_style ])
45
+ sheet.add_row([ "", t.call("logical_table_name"), @table.table_name ], style: [ no_border_style, detail_header_style, detail_cell_style ])
46
+ sheet.add_row([ "", t.call("version"), "1.0" ], style: [ no_border_style, detail_header_style, detail_cell_style ])
47
+ sheet.add_row([ "", t.call("created_by"), @table.created_by ], style: [ no_border_style, detail_header_style, detail_cell_style ])
48
+ sheet.add_row([ "", t.call("created_date"), @table.created_at&.strftime("%Y-%m-%d") ], style: [ no_border_style, detail_header_style, detail_cell_style ])
49
+ sheet.add_row([ "", t.call("updated_by"), @table.updated_by ], style: [ no_border_style, detail_header_style, detail_cell_style ])
50
+ sheet.add_row([ "", t.call("updated_date"), @table.updated_at&.strftime("%Y-%m-%d") ], style: [ no_border_style, detail_header_style, detail_cell_style ])
51
+
52
+ # Empty row
53
+ sheet.add_row []
54
+
55
+ # Note section
56
+ sheet.rows.size
57
+ sheet.add_row([ "", t.call("overview") ], style: [ no_border_style, note_header_style ])
58
+ desc_row = sheet.rows.size + 1
59
+
60
+ note_border_style = sheet.styles.add_style(
61
+ border: { style: :medium, color: "000000" }
62
+ )
63
+
64
+ note_row_data = [ "" ]
65
+ note_row_data += [ @table.description.to_s ] + [ "" ] * 12
66
+ sheet.add_row(note_row_data, style: [ no_border_style ] + Array.new(13, note_border_style), height: 20)
67
+
68
+ sheet.merge_cells("B#{desc_row}:N#{desc_row}")
69
+
70
+ # Empty rows
71
+ sheet.add_row []
72
+ sheet.add_row []
73
+
74
+ # First column header row
75
+ first_header_row_styles = Array.new(14, no_border_style)
76
+ first_header_row_styles[3] = column_header_style
77
+ first_header_row_styles[4] = column_header_style
78
+ first_header_row_styles[5] = column_header_style
79
+
80
+ sheet.add_row [
81
+ "", "", "", t.call("data_type"), t.call("length"), t.call("decimal_places"), "", "", "", "", "", "", "", ""
82
+ ], style: first_header_row_styles, height: 20
83
+
84
+ # Column details header
85
+ sheet.add_row [
86
+ "No",
87
+ t.call("logical_column_name"),
88
+ t.call("physical_column_name"),
89
+ t.call("data_type"),
90
+ t.call("length"),
91
+ t.call("decimal_places"),
92
+ t.call("not_null"),
93
+ t.call("default"),
94
+ "PK",
95
+ "FK",
96
+ "CK",
97
+ "UK",
98
+ "INDEX",
99
+ t.call("remark")
100
+ ], style: Array.new(14, column_header_style), height: 40
101
+
102
+ # Column details
103
+ @table.db_design_dynamic_columns.each_with_index do |column, col_idx|
104
+ row_styles = Array.new(14, detail_cell_style)
105
+
106
+ (4..12).each do |idx|
107
+ row_styles[idx] = centered_cell_style
108
+ end
109
+
110
+ length_display = column.length.present? ? "#{column.length} bytes" : ""
111
+
112
+ col_data = [
113
+ col_idx + 1,
114
+ column.column_name,
115
+ column.physical_column_name,
116
+ column.data_type,
117
+ length_display,
118
+ column.decimal_precision,
119
+ column.not_null ? "〇" : "",
120
+ column.default_value,
121
+ column.is_primary_key ? "〇" : "",
122
+ column.is_foreign_key ? "〇" : "",
123
+ column.is_candidate_key ? "〇" : "",
124
+ column.is_unique_key ? "〇" : "",
125
+ column.is_indexed ? "〇" : "",
126
+ column.description
127
+ ]
128
+ sheet.add_row col_data, style: row_styles
129
+ end
130
+
131
+ # Set column widths
132
+ sheet.column_widths 5, 25, 30, 30, 15, 15, 20, 10, 5, 5, 5, 5, 10, 40
133
+ end
134
+
135
+ # rubocop:enable Metrics/BlockLength
@@ -0,0 +1,109 @@
1
+ <div class='container-fluid mt-4 ps-5 pe-5'>
2
+ <!-- Custom Styled Breadcrumbs -->
3
+ <div class='d-flex align-items-center mb-3 breadcrumb-container'>
4
+ <nav aria-label="breadcrumb">
5
+ <ol class="breadcrumb mb-3 breadcrumb-container align-items-center">
6
+ <li class="breadcrumb-item p-0 m-0">
7
+ <a href="<%= dbdoc_engine.root_path %>" class="text-decoration-none text-muted">
8
+ <small><i class="bi bi-house-door pe-2"></i></small>
9
+ </a>
10
+ </li>
11
+ <li class="breadcrumb-item p-0 m-0">
12
+ <a href="<%= dbdoc_engine.admin_dashboard_path(locale: I18n.locale) %>" class="text-decoration-none text-muted pe-2">
13
+ <small><%= t('dbdoc.dashboardbread') %></small>
14
+ </a>
15
+ </li>
16
+ <li class="breadcrumb-item active p-0 m-0" aria-current="page">
17
+ <small><span class="text-custom-primary fw-medium"><%= t('dbdoc.dynamic_tables_header') %></span></small>
18
+ </li>
19
+ </ol>
20
+ </nav>
21
+ </div>
22
+
23
+ <!-- Page Heading with Stats Summary -->
24
+ <div class='mb-4'>
25
+ <div class='d-flex justify-content-between align-items-center mb-4'>
26
+ <h4 class='fw-bold mb-0 text-custom-primary'>
27
+ <%= t('dbdoc.dynamic_tables') %>
28
+ </h4>
29
+
30
+ <!-- Quick Stats & Download Button -->
31
+ <div class='d-flex gap-3'>
32
+ <div class='rounded-pill px-3 py-2 shadow d-flex align-items-center'>
33
+ <small><i class='bi bi-folder text-success me-2'></i></small>
34
+ <span><small><strong><%= @total_group_count %></strong> <%= t('dbdoc.groups') %></small></span>
35
+ </div>
36
+ <div class='rounded-pill px-3 py-2 shadow d-flex align-items-center'>
37
+ <small><i class='bi bi-table text-primary me-2'></i></small>
38
+ <span><small><strong><%= @total_table_count %></strong> <%= t('dbdoc.tables') %></small></span>
39
+ </div>
40
+ <%= link_to dbdoc_engine.export_all_to_excel_admin_db_design_dynamic_tables_path(format: :xlsx),
41
+ class: 'btn btn-outline-primary',
42
+ target: '_blank',
43
+ data: { turbo: false } do %>
44
+ <small><i class='bi bi-download'></i></small>
45
+ <% end %>
46
+ </div>
47
+ </div>
48
+ <!-- Combined Search, Filter and Action Buttons Section -->
49
+ <div class='row mb-3'>
50
+ <div class='col-lg-8 col-md-7 col-sm-12 mb-2 mb-md-0'>
51
+ <%= form_with url: admin_db_design_dynamic_tables_path, method: :get, data: { controller: 'auto-submit', turbo_frame: 'tables_results' } do |f| %>
52
+ <%= f.hidden_field :locale, value: I18n.locale %>
53
+ <div class='input-group'>
54
+ <!-- Search Icon -->
55
+ <span class='input-group-text bg-white border-end-0'>
56
+ <small><i class='bi bi-search text-muted'></i></small>
57
+ </span>
58
+
59
+ <!-- Search Field -->
60
+ <%= f.text_field :search, value: params[:search], class: 'form-control border-start-0', placeholder: t('dbdoc.search_admin'), data: { action: 'input->auto-submit#submit' } %>
61
+ <!-- Group Filter Dropdown -->
62
+ <div class='col-md-4 ms-2' data-controller="select2">
63
+ <%= f.select :group_filter,
64
+ group_filter_options(@groups, params[:group_filter]),
65
+ { prompt: t('dbdoc.select_table_group') },
66
+ {
67
+ class: 'form-select border-start-0',
68
+ data: {
69
+ action: 'change->auto-submit#submit',
70
+ select2_target: "select",
71
+ select2_placeholder_value: t('dbdoc.select_table_group')
72
+ }
73
+ } %>
74
+ </div>
75
+
76
+ <!-- Clear Button -->
77
+ <% if params[:search].present? || params[:group_filter].present? %>
78
+ <%= link_to dbdoc_engine.admin_db_design_dynamic_tables_path, class: 'btn btn-outline-secondary' do %>
79
+ <small><i class='bi bi-x-circle'></i><%= t('dbdoc.clear') %></small>
80
+ <% end %>
81
+ <% end %>
82
+ </div>
83
+ <% end %>
84
+ </div>
85
+
86
+ <!-- Action Buttons Section -->
87
+ <div class='col-lg-4 col-md-5 col-sm-12 d-flex justify-content-md-end justify-content-sm-start mt-2 mt-md-0'>
88
+ <div class='d-flex gap-2'>
89
+ <!-- Show Deleted Tables (only for superadmin) -->
90
+ <% if can_delete? %>
91
+ <%= link_to dbdoc_engine.deleted_tables_admin_db_design_dynamic_tables_path, class: 'btn btn-outline-danger btn-sm shadow-sm d-flex align-items-center' do %>
92
+ <small><i class='bi bi-trash me-1'></i><span class="d-none d-sm-inline"><%= t('dbdoc.show_deleted') %></span></small>
93
+ <% end %>
94
+ <% end %>
95
+
96
+ <!-- New Table (for admin and superadmin) -->
97
+ <% if can_edit? %>
98
+ <%= link_to dbdoc_engine.new_admin_db_design_dynamic_table_path, class: 'btn btn-outline-success btn-sm shadow-sm d-flex align-items-center' do %>
99
+ <small><i class='bi bi-plus-circle-fill me-1'></i><span class="d-none d-sm-inline"><%= t('dbdoc.new') %></span></small>
100
+ <% end %>
101
+ <% end %>
102
+ </div>
103
+ </div>
104
+ </div>
105
+
106
+ <!-- Tables List Partial -->
107
+ <%= render 'table_index', tables: @tables %>
108
+ </div>
109
+ </div>
@@ -0,0 +1,25 @@
1
+ <%# Dynamic Tables - New Table Page This view provides the UI for creating a new dynamic table %>
2
+ <% content_for :title, t('dbdoc.new_table') %>
3
+ <!-- Custom Styled Breadcrumbs -->
4
+ <div class='d-flex align-items-center mb-3 breadcrumb-container mt-4 ms-5'>
5
+ <a href='<%= dbdoc_engine.root_path %>' class='text-decoration-none text-muted'>
6
+ <small><i class='bi bi-house-door'></i></small>
7
+ </a>
8
+ <span class='slash'> / </span>
9
+ <a href="<%= dbdoc_engine.admin_dashboard_path(locale: I18n.locale) %>" class='text-decoration-none text-muted'>
10
+ <small><%= t('dbdoc.dashboardbread') %></small>
11
+ </a>
12
+ <span class='slash'> / </span>
13
+ <a href='<%= dbdoc_engine.admin_db_design_dynamic_tables_path %>' class='text-decoration-none text-muted'>
14
+ <small><%= t('dbdoc.dynamic_tables_header') %></small>
15
+ </a>
16
+ <span class='slash'> / </span>
17
+ <small><span class='text-custom-primary fw-medium'><%= t('dbdoc.newtable') %></span></small>
18
+ </div>
19
+ <%# Page heading with icon %>
20
+ <h4 class="fw-bold mt-3 ms-5 mb-2 text-custom-primary">
21
+ <i class="bi bi-pencil-square me-1 text-custom-primary"></i><%= t('dbdoc.new_table') %>
22
+ </h4>
23
+ <%# Render the form partial with the new table instance %>
24
+ <%= render 'form', table: @table, other_tables: @other_tables, existing_tables: @existing_tables %>
25
+ <br>
@@ -0,0 +1,125 @@
1
+ <div class='container-fluid mt-4 ps-5 pe-5'>
2
+ <!-- Custom Styled Breadcrumbs -->
3
+ <div class='d-flex align-items-center mb-3 breadcrumb-container'>
4
+ <a href='<%= dbdoc_engine.root_path %>' class='text-decoration-none text-muted'>
5
+ <i class='bi bi-house-door'></i>
6
+ </a>
7
+ <span class='slash'> / </span>
8
+ <a href="<%= dbdoc_engine.admin_dashboard_path(locale: I18n.locale) %>" class='text-decoration-none text-muted'>
9
+ <small><%= t('dbdoc.dashboardbread') %></small>
10
+ </a>
11
+ <span class='slash'> / </span>
12
+ <a href='<%= dbdoc_engine.admin_db_design_dynamic_tables_path %>' class='text-decoration-none text-muted'>
13
+ <small><%= t('dbdoc.dynamic_tables_header') %></small>
14
+ </a>
15
+ <span class='slash'> / </span>
16
+ <span class='text-custom-primary fw-medium'><small><%= @table.table_name %></small></span>
17
+ </div>
18
+
19
+ <!-- Table Information Accordion -->
20
+ <div class='accordion mb-4'>
21
+ <div class='accordion-item shadow-sm' data-controller="dbdoc-accordion">
22
+ <h2 class='accordion-header' id='headingTableInfo'>
23
+ <button
24
+ class='accordion-button collapsed'
25
+ type='button'
26
+ data-action='click->dbdoc-accordion#toggle'
27
+ data-dbdoc-accordion-target="button"
28
+ aria-expanded='false'
29
+ aria-controls='collapseTableInfo'>
30
+ <div class='d-flex justify-content-between align-items-center w-100'>
31
+ <div>
32
+ <i class='bi bi-table me-2 text-primary'></i>
33
+ <%= @table.table_name %>
34
+ <span class='ms-2 text-muted fs-6 fst-italic'>
35
+ <small>(<%= @table.physical_table_name %>)</small>
36
+ </span>
37
+ </div>
38
+ </div>
39
+ </button>
40
+ </h2>
41
+ <div
42
+ id='collapseTableInfo'
43
+ class='accordion-collapse collapse'
44
+ data-dbdoc-accordion-target="content"
45
+ aria-labelledby='headingTableInfo'>
46
+ <div class='accordion-body'>
47
+ <!-- Table details in card-like sections -->
48
+ <div class='row g-3'>
49
+ <!-- Table Group Section -->
50
+ <div class='col-md-6'>
51
+ <div class='p-3 border rounded h-100 bg-light bg-opacity-50'>
52
+ <h6 class='d-flex align-items-center text-primary mb-3'>
53
+ <i class='bi bi-folder me-2'></i><%= t('dbdoc.table_group') %>
54
+ </h6>
55
+ <div class='d-flex align-items-center'>
56
+ <% group = DbdocEngine::DbDesignTableGroupQueries.find_group_with_tables(@table.db_design_table_group_id) %>
57
+ <span class='me-2 rounded-circle colour-circle'
58
+ style='background-color: <%= group.group_color %>; width: 12px; height: 12px; display: inline-block;'></span>
59
+ <span><%= group.group_name %></span>
60
+ </div>
61
+ </div>
62
+ </div>
63
+ <!-- User Information Section -->
64
+ <div class='col-md-6'>
65
+ <div class='p-3 border rounded h-100 bg-light bg-opacity-50'>
66
+ <h6 class='d-flex align-items-center text-primary mb-3'>
67
+ <i class='bi bi-person-badge me-2'></i><%= t('dbdoc.user_information') %>
68
+ </h6>
69
+ <!-- Created By Information -->
70
+ <div class='d-flex align-items-center mb-2'>
71
+ <div class='text-muted'>
72
+ <i class='bi bi-person-add me-1'></i> <%= t('dbdoc.created_by') %>:
73
+ </div>
74
+ <div class='ms-2'>
75
+ <%= @table.created_by %>
76
+ <span class='text-muted ms-1'>
77
+ (<%= l @table.created_at, format: :short %>)
78
+ </span>
79
+ </div>
80
+ </div>
81
+ <!-- Updated By Information -->
82
+ <div class='d-flex align-items-center'>
83
+ <div class='text-muted mt-2'>
84
+ <i class='bi bi-person-check me-1'></i> <%= t('dbdoc.updated_by') %>:
85
+ </div>
86
+ <div class='ms-2 mt-2'>
87
+ <%= @table.updated_by %>
88
+ <span class='text-muted ms-1'>
89
+ (<%= l @table.updated_at, format: :short %>)
90
+ </span>
91
+ </div>
92
+ </div>
93
+ </div>
94
+ </div>
95
+ <!-- Description Section -->
96
+ <div class='col-12'>
97
+ <div class='p-3 border rounded bg-light bg-opacity-50'>
98
+ <h6 class='d-flex align-items-center text-primary mb-3'>
99
+ <i class='bi bi-info-circle me-2'></i><%= t('dbdoc.description') %>
100
+ </h6>
101
+ <div class=''>
102
+ <%= @table.description.present? ?
103
+ @table.description :
104
+ content_tag(:span, 'No description provided', class: 'text-muted fst-italic') %>
105
+ </div>
106
+ </div>
107
+ </div>
108
+ </div>
109
+ </div>
110
+ <!-- Footer with Export Button -->
111
+ <div class='accordion-footer px-4 py-3 d-flex justify-content-end border-top'>
112
+ <%= link_to dbdoc_engine.export_to_excel_admin_db_design_dynamic_table_path(@table, format: :xlsx),
113
+ class: 'btn btn-outline-primary btn-sm px-3 shadow-sm',
114
+ target: '_blank',
115
+ data: { turbo: false } do %>
116
+ <i class='bi bi-file-excel me-2'></i><%= t('dbdoc.export_to_excel') %>
117
+ <% end %>
118
+ </div>
119
+ </div>
120
+ </div>
121
+ </div>
122
+
123
+ <%= render 'table_columns', columns: @columns %>
124
+ <%= render 'recent_activity', recent_changelogs: @recent_changelogs %>
125
+ </div>
@@ -0,0 +1,75 @@
1
+ <%= turbo_frame_tag 'deleted_table_groups_results' do %>
2
+ <% if table_groups.empty? %>
3
+ <!-- No Data Message -->
4
+ <div class='text-center py-5'>
5
+ <i class='bi bi-trash fs-1 text-muted mb-3'></i>
6
+ <h5 class='text-muted'><%= t('dbdoc.no_deleted_table_groups_found') %></h5>
7
+ <% if params[:search].present? %>
8
+ <p class='text-muted'><small><%= t('dbdoc.try_different_criteria') %><%= link_to t('dbdoc.view_all_deleted_groups'), dbdoc_engine.deleted_groups_admin_db_design_table_groups_path %></small></p>
9
+ <% end %>
10
+ </div>
11
+ <% else %>
12
+ <!-- Table Card -->
13
+ <div class='card card-custom shadow-sm mb-4'>
14
+ <div class='card-body p-0'>
15
+ <div class='table-responsive p-1'>
16
+ <table class='table'>
17
+ <thead class='table-light bg-light'>
18
+ <tr>
19
+ <th class='text-custom-secondary' width="35%"><small><%= t('dbdoc.group_name') %></small></th>
20
+ <th class='text-custom-secondary' width="35%"><small><%= t('dbdoc.tables') %></small></th>
21
+ <th class='text-custom-secondary' width="35%"><small><%= t('dbdoc.deleted_at') %></small></th>
22
+ <th class=' text-custom-secondary' width="10%"><small><%= t('dbdoc.actions') %></small></th>
23
+ </tr>
24
+ </thead>
25
+ <tbody>
26
+ <% table_groups.each do |group| %>
27
+ <tr class='table-danger bg-opacity-10'>
28
+ <!-- Group Name -->
29
+ <td>
30
+ <div class='d-flex align-items-center'>
31
+ <span class='me-2 colour-circle-1' style='background-color: <%= group.group_color %>;'></span>
32
+ <small><%= group.group_name %></small>
33
+ </div>
34
+ </td>
35
+ <td>
36
+ <small class='ms-3'>
37
+ <%= DbdocEngine::DbDesignDynamicTableQueries.count_tables_in_group(group, true) %>
38
+ </small>
39
+ </td>
40
+ <!-- Deleted at timestamp -->
41
+ <td>
42
+ <small class='text-danger'>
43
+ <i class='bi bi-calendar-x me-1'></i>
44
+ <%= group.deleted_at&.strftime('%Y-%m-%d %H:%M') %>
45
+ </small>
46
+ </td>
47
+ <td class='text-end'>
48
+ <div class='d-flex justify-content-end gap-2'>
49
+ <%= button_to dbdoc_engine.restore_admin_db_design_table_group_path(group),
50
+ method: :patch,
51
+ class: 'btn btn-outline-success btn-sm px-3 shadow-sm',
52
+ data: { turbo: false } do %>
53
+ <small><i class='bi bi-arrow-counterclockwise me-1'></i></small>
54
+ <% end %>
55
+ <%= button_to dbdoc_engine.permanent_destroy_admin_db_design_table_group_path(group),
56
+ method: :delete,
57
+ data: { confirm: 'Are you sure? This cannot be undone!', turbo: false },
58
+ class: 'btn btn-outline-danger btn-sm px-3 shadow-sm' do %>
59
+ <small><i class='bi bi-trash-fill me-1'></i></small>
60
+ <% end %>
61
+ </div>
62
+ </td>
63
+ </tr>
64
+ <% end %>
65
+ </tbody>
66
+ </table>
67
+ </div>
68
+ <!-- Pagination -->
69
+ <div class='d-flex mt-3 justify-content-end'>
70
+ <small><%= paginate table_groups, theme: 'dbdoc_engine' %></small>
71
+ </div>
72
+ </div>
73
+ </div>
74
+ <% end %>
75
+ <% end %>
@@ -0,0 +1,88 @@
1
+ <%# Table Group Form Partial - Updated to handle both created_by and updated_by %>
2
+ <div class="d-flex ms-5">
3
+ <div class="bg-white p-4 rounded shadow w-50">
4
+ <%= form_with(
5
+ model: [:admin, table_group],
6
+ local: true,
7
+ class: 'needs-validation p-4 bg-white rounded',
8
+ data: {
9
+ controller: 'table-group-validation',
10
+ action: 'submit->table-group-validation#validate',
11
+ table_group_validation_existing_names_value: [], # This will be populated via AJAX
12
+ table_group_id: table_group.persisted? ? table_group.id : nil,
13
+ original_group_name: table_group.persisted? ? table_group.group_name : nil
14
+ }
15
+ ) do |f| %>
16
+ <!-- Group Name Field -->
17
+ <div class='mb-4'>
18
+ <%= f.label :group_name, t('dbdoc.group_name'), class: 'form-label fw-semibold required-field' %>
19
+ <%= f.text_field :group_name,
20
+ class: 'form-control form-control',
21
+ placeholder: t('dbdoc.enter_group_name'),
22
+ data: {
23
+ table_group_validation_target: 'groupName'
24
+ }
25
+ %>
26
+ <% if table_group.errors[:group_name].any? %>
27
+ <div class='invalid-feedback d-block'>
28
+ <%= table_group.errors[:group_name].first %>
29
+ </div>
30
+ <% end %>
31
+ </div>
32
+
33
+ <% if table_group.new_record? %>
34
+ <!-- Created By Field - Only shown for new records -->
35
+ <div class='mb-4'>
36
+ <%= f.label :created_by, t('dbdoc.created_by'), class: 'form-label fw-semibold required-field' %>
37
+ <%= f.text_field :created_by,
38
+ class: 'form-control form-control',
39
+ placeholder: t('dbdoc.enter_your_name'),
40
+ data: {
41
+ table_group_validation_target: 'createdBy'
42
+ }
43
+ %>
44
+ </div>
45
+
46
+ <!-- Hidden Updated By Field - For new records -->
47
+ <%= f.hidden_field :updated_by,
48
+ data: {
49
+ table_group_validation_target: 'updatedBy'
50
+ }
51
+ %>
52
+ <% else %>
53
+ <!-- Updated By Field - Only shown for existing records -->
54
+ <div class='mb-4'>
55
+ <%= f.label :updated_by, t('dbdoc.updated_by'), class: 'form-label fw-semibold required-field' %>
56
+ <%= f.text_field :updated_by,
57
+ value: "",
58
+ class: 'form-control form-control',
59
+ placeholder: t('dbdoc.enter_your_name'),
60
+ data: {
61
+ table_group_validation_target: 'updatedBy'
62
+ }
63
+ %>
64
+ </div>
65
+ <% end %>
66
+
67
+ <!-- Group Color Field -->
68
+ <div class='mb-4'>
69
+ <%= f.label :group_color, t('dbdoc.group_color'), class: 'form-label fw-semibold required-field' %>
70
+ <%= f.color_field :group_color,
71
+ class: 'form-control form-control color-thin',
72
+ value: f.object.group_color || '#ff5733',
73
+ data: {
74
+ table_group_validation_target: 'groupColor'
75
+ }
76
+ %>
77
+ </div>
78
+
79
+ <!-- Submit Button -->
80
+ <div class='d-flex'>
81
+ <%# Submit button %>
82
+ <%= f.submit t('dbdoc.save_table_group'), class: 'btn btn-success btn-sm px-4 py-2 shadow-sm' %>
83
+ <%# Back button %>
84
+ <%= link_to t('dbdoc.back'), dbdoc_engine.admin_db_design_table_groups_path, class: 'btn btn-secondary btn-sm shadow px-4 py-2 ms-2' %>
85
+ </div>
86
+ <% end %>
87
+ </div>
88
+ </div>
@@ -0,0 +1,82 @@
1
+ <%= turbo_frame_tag 'table_groups_results' do %>
2
+ <% if table_groups.any? %>
3
+ <!-- Table Groups List -->
4
+ <div class='table-responsive p-1'>
5
+ <table class='table'>
6
+ <thead class='table-secondary bg-light'>
7
+ <tr>
8
+ <!-- Group Name Header -->
9
+ <th class='text-custom-secondary'><small><%= t('dbdoc.group_name') %></small></th>
10
+
11
+ <!-- Number of tables header -->
12
+ <th class='text-custom-secondary'><small><%= t('dbdoc.tables') %></small></th>
13
+
14
+ <!-- Actions Header - left aligned as requested -->
15
+ <th class='text-end pe-5 text-custom-secondary'><small><%= t('dbdoc.actions') %></small></th>
16
+ </tr>
17
+ </thead>
18
+ <tbody>
19
+ <% table_groups.each do |group| %>
20
+ <tr>
21
+ <!-- Group Name -->
22
+ <td>
23
+ <div class='d-flex align-items-center'>
24
+ <span class='me-2 colour-circle-1' style='background-color: <%= group.group_color %>;'></span>
25
+ <small><%= group.group_name %></small>
26
+ </div>
27
+ </td>
28
+
29
+ <!-- Number of tables associated with the group -->
30
+ <td>
31
+ <small>
32
+ <%= DbdocEngine::DbDesignDynamicTableQueries.count_tables_in_group(group) %>
33
+ </small>
34
+ </td>
35
+
36
+ <!-- Edit and Delete Buttons - still right-aligned -->
37
+ <td>
38
+ <div class='d-flex justify-content-end gap-2'>
39
+ <!-- Edit Group Button -->
40
+ <%= link_to dbdoc_engine.edit_admin_db_design_table_group_path(group),
41
+ class: 'btn btn-outline-warning btn-sm px-3 shadow-sm',
42
+ data: { turbo_frame: '_top' } do %>
43
+ <small><i class='bi bi-pencil-square me-1'></i></small>
44
+ <% end %>
45
+
46
+ <!-- Delete Group Button -->
47
+ <%= button_to dbdoc_engine.admin_db_design_table_group_path(group), method: :delete, data: { confirm: 'Are you sure?', turbo: false }, class: 'btn btn-outline-danger btn-sm px-3 shadow-sm' do %>
48
+ <small><i class='bi bi-trash-fill me-1'></i></small>
49
+ <% end %>
50
+ </div>
51
+ </td>
52
+ </tr>
53
+ <% end %>
54
+ </tbody>
55
+ </table>
56
+ </div>
57
+
58
+ <!-- Pagination Section -->
59
+ <div class='d-flex mt-3 justify-content-end mb-3'>
60
+ <small><%= paginate table_groups, theme: 'dbdoc_engine' %></small>
61
+ </div>
62
+ <% else %>
63
+ <!-- No Table Groups Found Message -->
64
+ <div class='text-center py-5'>
65
+ <i class='bi bi-search fs-1 text-muted mb-3'></i>
66
+ <h5 class='text-muted'><%= t('dbdoc.no_table_groups_found') %></h5>
67
+
68
+ <% if search_query.present? %>
69
+ <!-- Message when filter is applied but no results -->
70
+ <p class='text-muted'>
71
+ <small>
72
+ <%= t('dbdoc.try_different_criteria') %>
73
+ <%= link_to t('dbdoc.view_all_groups'), dbdoc_engine.admin_db_design_table_groups_path %>
74
+ </small>
75
+ </p>
76
+ <% else %>
77
+ <!-- Message when no groups exist -->
78
+ <p class='text-muted'><small><%= t('dbdoc.get_started_by_creating_new_table_group') %></small></p>
79
+ <% end %>
80
+ </div>
81
+ <% end %>
82
+ <% end %>