oversee 0.2.0 → 0.3.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.
Files changed (68) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +8 -3
  3. data/app/assets/config/oversee_manifest.js +2 -0
  4. data/app/components/oversee/dashboard/actions.rb +58 -0
  5. data/app/components/oversee/dashboard/filter.rb +12 -0
  6. data/app/components/oversee/dashboard/filters.rb +5 -51
  7. data/app/components/oversee/dashboard/header.rb +34 -18
  8. data/app/components/oversee/dashboard/index.rb +23 -11
  9. data/app/components/oversee/dashboard/javascript.rb +4 -4
  10. data/app/components/oversee/dashboard/pagination.rb +1 -1
  11. data/app/components/oversee/dashboard/sidebar.rb +38 -1
  12. data/app/components/oversee/dashboard/tailwind.rb +30 -1
  13. data/app/components/oversee/field/display.rb +12 -21
  14. data/app/components/oversee/field/form.rb +5 -37
  15. data/app/components/oversee/field/input/belongs_to.rb +5 -0
  16. data/app/components/oversee/field/input/boolean.rb +3 -18
  17. data/app/components/oversee/field/input/date.rb +5 -0
  18. data/app/components/oversee/field/input/datetime.rb +2 -17
  19. data/app/components/oversee/field/input/integer.rb +2 -17
  20. data/app/components/oversee/field/input/json.rb +5 -0
  21. data/app/components/oversee/field/input/rich_text.rb +10 -0
  22. data/app/components/oversee/field/input/string.rb +2 -17
  23. data/app/components/oversee/field/input.rb +13 -11
  24. data/app/components/oversee/field/label.rb +16 -15
  25. data/app/components/oversee/field/set.rb +36 -0
  26. data/app/components/oversee/field/value/belongs_to.rb +15 -0
  27. data/app/components/oversee/field/value/boolean.rb +2 -47
  28. data/app/components/oversee/field/value/date.rb +5 -0
  29. data/app/components/oversee/field/value/datetime.rb +2 -6
  30. data/app/components/oversee/field/value/enum.rb +2 -6
  31. data/app/components/oversee/field/value/integer.rb +2 -6
  32. data/app/components/oversee/field/value/json.rb +6 -0
  33. data/app/components/oversee/field/value/rich_text.rb +5 -0
  34. data/app/components/oversee/field/value/string.rb +3 -10
  35. data/app/components/oversee/field/value/text.rb +2 -6
  36. data/app/components/oversee/field/value.rb +14 -5
  37. data/app/components/oversee/field.rb +42 -0
  38. data/app/components/oversee/flash.rb +39 -0
  39. data/app/components/oversee/layout/application.rb +46 -0
  40. data/app/components/oversee/resources/index.rb +22 -3
  41. data/app/components/oversee/resources/new.rb +7 -3
  42. data/app/components/oversee/resources/show.rb +139 -68
  43. data/app/components/oversee/resources/table.rb +8 -2
  44. data/app/controllers/oversee/dashboard_controller.rb +1 -1
  45. data/app/controllers/oversee/resources/fields_controller.rb +24 -36
  46. data/app/controllers/oversee/resources_controller.rb +29 -24
  47. data/app/javascript/oversee/application.js +3 -0
  48. data/app/javascript/oversee/controllers/clipboard_controller.js +21 -0
  49. data/app/javascript/oversee/controllers/index.js +9 -0
  50. data/app/javascript/oversee/controllers/notification_controller.js +17 -0
  51. data/app/javascript/oversee/controllers/reveal_controller.js +19 -0
  52. data/app/javascript/oversee/controllers/sidebar/state_controller.js +21 -0
  53. data/app/models/oversee/resource.rb +49 -20
  54. data/app/{oversee → service/oversee}/filter.rb +2 -2
  55. data/app/{oversee → service/oversee}/search.rb +1 -1
  56. data/app/views/oversee/base.rb +5 -0
  57. data/config/importmap.rb +14 -0
  58. data/config/routes.rb +16 -10
  59. data/lib/generators/oversee/install_generator.rb +7 -0
  60. data/lib/oversee/engine.rb +19 -0
  61. data/lib/oversee/version.rb +1 -1
  62. data/lib/oversee.rb +13 -0
  63. data/lib/tasks/oversee_tasks.rake +6 -4
  64. metadata +71 -9
  65. data/app/jobs/oversee/application_job.rb +0 -4
  66. data/app/oversee/cards.rb +0 -2
  67. data/app/oversee/resource.rb +0 -10
  68. data/app/views/layouts/oversee/application.html.erb +0 -26
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: af99387ad6126bddd510d80a2fd929a776c48ef101e61a3ecfd93c1f8106fa87
4
- data.tar.gz: 1d8f34bc6c2fd6225b00edf30b833b4ba6bf52ced03c4c5b16be9a33162ad1a7
3
+ metadata.gz: 82a5bb3d0823ed6874fe8b7bb09934ed3b72b7b9a2964da6c6d8cdd7b82ac28a
4
+ data.tar.gz: 5ddf616584c7319a2ef611227fb4f5e0cf876c1dc20b1228c47330411715054c
5
5
  SHA512:
6
- metadata.gz: 577e608656e45f6797397728ec9820cd39854eccffa550d7d60b3735581f8480817a3d4ce235c49bcceab3b9394b06356637ec17c3c2808f2549158ad7a32ea1
7
- data.tar.gz: 4ef646cc6bef74b8ffccfbd97c796bc147d6f9a144ff5f4068630235e1967ff6fe6f9b4e08bfcdb899c49bdbe106e8a37cbde59603377edf2fd7c8866c115cbc
6
+ metadata.gz: 16cf0583966c0f07deae2be76299544a4fb5678efc5345a292acc0ad628d263a979b44e2d60f8749cc87bbfd5471eb85cfe5619fdc58af5bedb8b9e5a0efe755
7
+ data.tar.gz: f0d8ae31255ca03aecb010393356d55a9ac63b99699b50b8c9b6bae8d6c11c8f1d3b876dcd6fe9c9118e19c6015989f45f3e7ed74eadb259e885007eb215e764
data/README.md CHANGED
@@ -1,10 +1,14 @@
1
-
2
1
  # Oversee
3
2
 
4
- Plug & play admin dashboard for Rails applications.
3
+ Plug & play content management system (CMS) for Rails applications. Some may call it an admin dashboard too.
5
4
 
5
+ <a href="https://rubygems.org/gems/oversee">
6
+ <img alt="Oversee GEM Version" src="https://img.shields.io/gem/v/oversee?color=10b981&include_prereleases&logo=ruby&logoColor=f43f5e">
7
+ </a>
6
8
 
7
- [![Gem Version](https://badge.fury.io/rb/oversee.svg)](https://badge.fury.io/rb/oversee)
9
+ <a href="https://rubygems.org/gems/oversee">
10
+ <img alt="Oversee GEM Version" src="https://img.shields.io/gem/dt/oversee?color=10b981&include_prereleases&logo=ruby&logoColor=f43f5e">
11
+ </a>
8
12
 
9
13
  ---
10
14
 
@@ -35,6 +39,7 @@ $ bundle add oversee
35
39
 
36
40
  > [!TIP]
37
41
  > Currently, we don't release new gem versions too often due to the fragile nature of the gem. However, you can use the edge version of the gem by pointing directly to the git repository.
42
+ >
38
43
  > ```ruby
39
44
  > gem "oversee", git: "https://github.com/primevise/oversee", branch: :main
40
45
  > ```
@@ -0,0 +1,2 @@
1
+ //= link oversee/application.js
2
+ //= link_tree ../../javascript/oversee/controllers .js
@@ -0,0 +1,58 @@
1
+ class Oversee::Dashboard::Actions < Oversee::Base
2
+ def initialize(params: nil)
3
+ @params = params
4
+ end
5
+
6
+ def view_template(&)
7
+ div(class: "flex items-center justify-between") do
8
+ div(class: "flex items-center gap-2") do
9
+ if show_action_section?
10
+ button(
11
+ class:"rounded-full bg-gray-100 inline-flex gap-2 items-center text-xs px-4 py-2 font-medium hover:bg-gray-200",
12
+ data: { controller: "reveal", action: "reveal#toggle", reveal_revealable_id_value: "oversee-filters" }
13
+ ) do
14
+ render Phlex::Icons::Iconoir::FilterAlt.new(class: "size-3")
15
+ plain "Filters"
16
+ end
17
+ end
18
+ if false
19
+ a(class:"rounded-full bg-gray-100 inline-flex gap-2 items-center text-xs px-4 py-2 font-medium hover:bg-gray-200") do
20
+ render Phlex::Icons::Iconoir::XMark.new(class: "size-4 text-gray-500")
21
+ plain "Clear sorting"
22
+ end
23
+ end
24
+ end
25
+ div(class: "flex items-center gap-4") do
26
+ form(action: "", class: "flex items-center gap-2") do
27
+ input(
28
+ type: :search,
29
+ name: :query,
30
+ value: @params[:query],
31
+ placeholder: search_placeholder,
32
+ class: "flex bg-gray-100 min-w-64 w-64 focus:w-96 transition-all h-10 items-center pl-4 py-2 placeholder:text-gray-500 rounded-sm text-sm"
33
+ )
34
+ button(class: "size-10 inline-flex items-center justify-center bg-gray-100 hover:bg-gray-200 transition-colors") { render Phlex::Icons::Iconoir::Search.new(class: "size-4 text-gray-600") }
35
+ end
36
+ end
37
+ end
38
+ render Oversee::Dashboard::Filters.new if show_action_section?
39
+ end
40
+
41
+ private
42
+
43
+ def show_action_section?
44
+ Rails.env.development? || @params[:experimental] == "true"
45
+ end
46
+
47
+ def sortless_path
48
+ sortless_query_params = @params.except(:sort_attribute, :sort_direction, :controller, :action)
49
+ # helpers.resources_path(sortless_query_params)
50
+ end
51
+
52
+ def search_placeholder
53
+ context = Oversee::Search.new(collection: nil, resource_class: @params[:resource_class_name].constantize)
54
+ attr = context.default_searchable_attribute
55
+
56
+ "Search by #{attr}"
57
+ end
58
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+ class Oversee::Dashboard::Filter < Oversee::Base
3
+ def view_template
4
+ div(class: "flex items-center gap-2") do
5
+ render Phlex::Icons::Iconoir::LongArrowDownRight.new(class: "size-4 text-gray-500")
6
+ form(action: "", class: "flex items-center gap-2") do
7
+ input(type: :text, placeholder: "Title [EQ]", name: "filters[title][eq][]", class: "bg-gray-100 px-4 py-2 text-xs")
8
+ button(type: :submit, class: "button", class: "bg-gray-900 text-white px-4 py-2 text-xs font-medium") { plain "Apply" }
9
+ end
10
+ end
11
+ end
12
+ end
@@ -1,54 +1,8 @@
1
+ # frozen_string_literal: true
1
2
  class Oversee::Dashboard::Filters < Oversee::Base
2
- def initialize(params: nil)
3
-
4
- @params = params
5
-
6
- puts "params: #{params}"
7
- puts "sortless_path: #{sortless_path}"
8
- end
9
-
10
- def view_template(&)
11
- div(class: "border-b p-4") do
12
- div(class: "flex items-center justify-between") do
13
- div(class: "flex items-center gap-2") do
14
- if show_action_section?
15
- button(class:"rounded-full bg-gray-100 inline-flex gap-2 items-center text-xs px-4 py-2 font-medium hover:bg-gray-200") do
16
- render Phlex::Icons::Iconoir::FilterAlt.new(class: "size-3")
17
- plain "Filters"
18
- end
19
- end
20
- if false
21
- a(class:"rounded-full bg-gray-100 inline-flex gap-2 items-center text-xs px-4 py-2 font-medium hover:bg-gray-200") do
22
- render Phlex::Icons::Iconoir::XMark.new(class: "size-4 text-gray-500")
23
- plain "Clear sorting"
24
- end
25
- end
26
- end
27
- div(class: "flex items-center gap-4") do
28
- form(action: "", class: "flex items-center gap-2") do
29
- input(type: :search, name: :query, class: "flex bg-gray-100 min-w-80 h-10 items-center pl-4 py-2 placeholder:text-gray-500 rounded-sm text-sm", placeholder: search_placeholder, value: @params[:query])
30
- button(class: "size-10 inline-flex items-center justify-center bg-gray-100 hover:bg-gray-200 transition-colors") { render Phlex::Icons::Iconoir::Search.new(class: "size-4 text-gray-600") }
31
- end
32
- end
33
- end
3
+ def view_template
4
+ div(id: :oversee_filters, class: "hidden pt-4 mt-4 border-t flex flex-col gap-2") do
5
+ render Oversee::Dashboard::Filter.new
34
6
  end
35
7
  end
36
-
37
- private
38
-
39
- def show_action_section?
40
- Rails.env.development? || @params[:experimental] == "true"
41
- end
42
-
43
- def sortless_path
44
- sortless_query_params = @params.except(:sort_attribute, :sort_direction, :controller, :action)
45
- # helpers.resources_path(sortless_query_params)
46
- end
47
-
48
- def search_placeholder
49
- context = Search.new(collection: nil, resource_class: @params[:resource_class_name].constantize)
50
- attr = context.default_searchable_attribute
51
-
52
- "Search by #{attr}"
53
- end
54
- end
8
+ end
@@ -1,4 +1,9 @@
1
1
  class Oversee::Dashboard::Header < Oversee::Base
2
+ attr_reader :title
3
+ attr_reader :subtitle
4
+ attr_reader :return_path
5
+ attr_reader :show_back_button
6
+
2
7
  def initialize(title: nil, subtitle: nil, return_path: nil, show_back_button: true)
3
8
  @title = title || "Dashboard"
4
9
  @subtitle = subtitle || "Manage your account"
@@ -7,31 +12,42 @@ class Oversee::Dashboard::Header < Oversee::Base
7
12
  end
8
13
 
9
14
  def view_template(&)
10
- div(id: "dashboard_header", class: "p-8 border-b flex items-center justify-between") do
11
- div(class: "flex items-center gap-4") do
12
- back_button
13
- div do
14
- h1(class: "text-xl text-gray-800") { @title }
15
- p(class: "text-sm text-gray-600") { @subtitle }
16
- end
17
- end
18
- div(class: "flex items-center gap-2") do
19
- yield if block_given?
15
+
16
+ div(class: "min-h-10 flex items-center justify-between") do
17
+ if block_given?
18
+ yield(self)
19
+ else
20
+ left
21
+ right
20
22
  end
21
23
  end
22
24
  end
23
25
 
26
+ def left(&)
27
+ div(class: "flex items-center gap-2") do
28
+ back_button if show_back_button
29
+ h3(class: "text-lg font-medium text-gray-900") { title } if title.present?
30
+ yield if block_given?
31
+ end
32
+ end
33
+
34
+ def right(&)
35
+ div(class: "flex items-center gap-4", &)
36
+ end
37
+
38
+ def separator
39
+ render Phlex::Icons::Iconoir::Slash.new(class: "size-4 text-gray-300", stroke_width: 1.75)
40
+ end
41
+
24
42
  private
25
43
 
26
44
  def back_button
27
- if @show_back_button
28
- a(
29
- href: return_button_path,
30
- class: "size-10 inline-flex items-center justify-center bg-gray-50 text-gray-500 hover:text-gray-900 hover:bg-gray-200 transition-colors",
31
- data: { controller: "back", action: "back#navigate", turbo_action: "replace" }
32
- ) do
33
- render Phlex::Icons::Iconoir::ArrowLeft.new(class: "size-4 text-gray-900")
34
- end
45
+ a(
46
+ href: return_button_path,
47
+ class: "mr-2 size-8 inline-flex items-center justify-center bg-gray-50 text-gray-500 hover:text-gray-900 hover:bg-gray-200 transition-colors",
48
+ data: { controller: "back", action: "back#navigate", turbo_action: "replace" }
49
+ ) do
50
+ render Phlex::Icons::Iconoir::ArrowLeft.new(class: "size-3", stroke_width: 2.5)
35
51
  end
36
52
  end
37
53
 
@@ -1,23 +1,35 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Oversee::Dashboard::Index < Oversee::Base
4
+
5
+ def around_template
6
+ render Oversee::Layout::Application.new { super }
7
+ end
8
+
4
9
  def view_template
5
- div(class: "p-8") do
6
- div(class: "flex items-center justify-between") do
7
- div do
8
- p(class: "text-xs uppercase font-medium text-gray-400") { "Dashboard" }
9
- h1(class: "text-xl") { "Welcome" }
10
+ div(class: "flex items-center justify-between") do
11
+ h1(class: "text-lg font-medium text-gray-900") { "Dashboard" }
12
+ h1(class: "text-sm font-medium text-gray-500") { Date.current.to_fs(:long) }
13
+ end
14
+
15
+ if Oversee.card_class_names.present?
16
+ div(class: "grid grid-cols-4 gap-4") do
17
+ Oversee.card_class_names.each do |card_name|
18
+ render Oversee::Card.new(card_name: card_name)
10
19
  end
11
20
  end
12
21
  end
13
22
 
14
- if Oversee.card_class_names.present?
15
- div(class: "p-8") do
16
- div(class: "grid grid-cols-4 gap-4") do
17
- Oversee.card_class_names.each do |card_name|
18
- render Oversee::Card.new(card_name: card_name)
23
+ hr(class: "my-4")
24
+
25
+ div(class: "grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-4 gap-4") do
26
+ Oversee.application_resource_names.sort.each do |resource_class_name|
27
+ a(href: helpers.resources_path(resource_class_name:), class: "w-full bg-gray-100/75 block hover:bg-gray-50 p-4 truncate") do
28
+ div(class: "flex items-center justify-center size-8 bg-white") do
29
+ render Phlex::Icons::Iconoir::Folder.new(class: "size-4 text-gray-400")
30
+ end
31
+ p(class: "mt-4 font-medium text-gray-700") { resource_class_name }
19
32
  end
20
- end
21
33
  end
22
34
  end
23
35
  end
@@ -1,9 +1,9 @@
1
1
  class Oversee::Dashboard::Javascript < Phlex::HTML
2
+ include Phlex::Rails::Helpers::JavascriptImportmapTags
3
+
2
4
  def view_template
3
- script(async: true, src:"https://unpkg.com/es-module-shims/dist/es-module-shims.js")
4
- script(type: "importmap", data_turbo_track: "reload") do
5
- raw %({"imports":{"@hotwired/stimulus":"https://unpkg.com/@hotwired/stimulus/dist/stimulus.js","@hotwired/turbo":"https://unpkg.com/@hotwired/turbo","@hotwired/turbo-rails":"https://unpkg.com/@hotwired/turbo-rails"}}).html_safe
6
- end
5
+ script(async: true, src:"https://ga.jspm.io/npm:es-module-shims@1.8.2/dist/es-module-shims.js")
6
+ javascript_importmap_tags("application", importmap: Oversee.importmap)
7
7
  script(type: "module") { raw %(import * as Turbo from "@hotwired/turbo-rails").html_safe }
8
8
  end
9
9
  end
@@ -9,7 +9,7 @@ class Oversee::Dashboard::Pagination < Oversee::Base
9
9
  end
10
10
 
11
11
  def view_template
12
- div(class:"p-4 border-t flex items-center justify-between") do
12
+ div(class:"mt-4 flex items-center justify-between") do
13
13
 
14
14
  div(class: "font-regular text-xs") do
15
15
  raw pagy_info(@pagy).html_safe
@@ -21,8 +21,45 @@ class Oversee::Dashboard::Sidebar < Oversee::Base
21
21
  end
22
22
  end
23
23
 
24
+ if Rails.env.development?
25
+ hr(class: "my-4 -mx-4")
26
+ details(
27
+ id: "links-menu",
28
+ class: "group",
29
+ # open: true,
30
+ data: {
31
+ controller: "sidebar--state",
32
+ action: "sidebar--state#persist",
33
+ sidebar__state_target: "expandable"
34
+ }
35
+ ) do
36
+ summary(class: "flex items-center justify-between cursor-pointer") do
37
+ p(class: "text-[0.7rem] uppercase text-gray-400 font-medium") { "Links" }
38
+ render Phlex::Icons::Iconoir::NavArrowDown.new(class: "size-4 text-gray-400 transform transition-transform group-open:rotate-180 group-hover:text-blue-500")
39
+ end
40
+ ul(class: "mt-2 text-sm text-gray-700 overflow-x-hidden") do
41
+ li do
42
+ a(href: "https://github.com/primevise/oversee", target: "_blank", class: "flex items-center gap-2 hover:bg-gray-50 p-2 truncate") do
43
+ render Phlex::Icons::Iconoir::ArrowUpRightSquare.new(class: "size-4 text-gray-400")
44
+ span { "Repository" }
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+
24
51
  hr(class: "my-4 -mx-4")
25
- details(open: true, class: "group") do
52
+
53
+ details(
54
+ id: "resources-menu",
55
+ class: "group",
56
+ # open: true,
57
+ data: {
58
+ controller: "sidebar--state",
59
+ action: "sidebar--state#persist",
60
+ sidebar__state_target: "expandable"
61
+ }
62
+ ) do
26
63
  summary(class: "flex items-center justify-between cursor-pointer") do
27
64
  p(class: "text-[0.7rem] uppercase text-gray-400 font-medium") { "Resources" }
28
65
  render Phlex::Icons::Iconoir::NavArrowDown.new(class: "size-4 text-gray-400 transform transition-transform group-open:rotate-180 group-hover:text-blue-500")
@@ -1,11 +1,40 @@
1
1
  class Oversee::Dashboard::Tailwind < Phlex::HTML
2
2
  def view_template
3
- script(src: "https://cdn.tailwindcss.com?plugins=typography")
3
+ script(src: "https://cdn.tailwindcss.com/3.4.15?plugins=typography@0.5.15")
4
4
  style(type:"text/tailwindcss") do
5
5
  raw pagy_css.html_safe
6
+ raw trix_css.html_safe
6
7
  end
7
8
  end
8
9
 
10
+ def trix_css
11
+ <<~CSS
12
+ trix-editor {
13
+ @apply rounded-b rounded-t-none border border-t-0 border-gray-200 !ring-0;
14
+ }
15
+
16
+ .trix-active {
17
+ @apply !bg-gray-100 !text-blue-500;
18
+ }
19
+
20
+ .trix-button-row {
21
+ @apply overflow-hidden rounded-t border;
22
+ }
23
+
24
+ .trix-button {
25
+ @apply !relative !inline-flex !h-7 !items-center !justify-center border-0 !border-b-0 !border-l-0 !px-7 !py-4;
26
+ }
27
+
28
+ .trix-button::before {
29
+ @apply !top-1.5 !h-5;
30
+ }
31
+
32
+ .trix-button-group {
33
+ @apply !mb-0 rounded-b-none !border-0 border-gray-200;
34
+ }
35
+ CSS
36
+ end
37
+
9
38
  def pagy_css
10
39
  <<~CSS
11
40
  .pagy {
@@ -1,29 +1,20 @@
1
- class Oversee::Field::Display < Oversee::Base
2
- def initialize(resource:, key: nil, value: nil, datatype: :string, interactive: true)
3
- @resource = resource
4
- @key = key
5
- @value = value
6
- @datatype = datatype
7
- @interactive = interactive
8
- end
9
-
1
+ class Oversee::Field::Display < Oversee::Field
10
2
  def view_template
11
- wrapper_tag(
12
- id: dom_id(@resource, @key),
13
- href: helpers.resource_input_field_path(resource_class_name: resource_class_name, key: @key),
14
- class: "bg-gray-100 h-10 flex items-center px-4 py-2 hover:bg-gray-200 transition-colors w-full cursor-pointer",
15
- data: { turbo_stream: true }) do
16
- render Oversee::Field::Value.new(key: @key, value: @resource.send(@key), datatype: @datatype)
3
+ html_tag(
4
+ id: dom_id(resource, key),
5
+ href: helpers.resource_input_path(resource_class_name:, key:, datatype:),
6
+ title: key.to_s.titleize,
7
+ class: "bg-gray-100 h-10 flex items-center justify-between px-4 py-2 hover:bg-gray-200 transition-colors w-full cursor-pointer group",
8
+ data: { turbo_stream: true }
9
+ ) do
10
+ render Oversee::Field::Value.new(key:, value:, datatype:, **@options)
11
+ render Phlex::Icons::Iconoir::Edit.new(class: "text-gray-500 size-4 opacity-0 group-hover:opacity-100 transition-opacity", stroke_width: 1.75)
17
12
  end
18
13
  end
19
14
 
20
15
  private
21
16
 
22
- def resource_class_name
23
- @resource.class.name
24
- end
17
+ def edittable? = @options[:edittable] || true
25
18
 
26
- def wrapper_tag(...)
27
- @interactive ? a(...) : div(...)
28
- end
19
+ def html_tag(...) = edittable? ? a(...) : div(...)
29
20
  end
@@ -1,49 +1,17 @@
1
- class Oversee::Field::Form < Oversee::Base
1
+ class Oversee::Field::Form < Oversee::Field
2
2
  include Phlex::Rails::Helpers::FormWith
3
3
 
4
- def initialize(resource:, key: nil, value: nil, datatype: :string, method: :patch)
5
- @resource = resource
6
- @key = key
7
- @value = value
8
- @datatype = datatype
9
- @method = method
10
- end
11
-
12
4
  def view_template
13
- form_with(id: dom_id(@resource, @key), model: @resource, url: helpers.update_resource_path(resource_class_name: resource_class_name, id: @resource.id), method: @method, class: "flex items-center w-full gap-4") do |form|
5
+ form_with(id: field_form_id, model: resource, url: helpers.update_resource_path(resource_class_name: resource_class_name, id: @resource.id), method: @method, class: "flex items-center w-full gap-4") do |form|
14
6
  input type: :hidden, id: "oversee_key", name: "oversee_key", value: @key.to_s
15
7
  input type: :hidden, id: "oversee_datatype", name: "oversee_datatype", value: @datatype
16
- render Oversee::Field::Input.new(key: @key, value: @value, datatype: @datatype)
17
- button(class:"h-9 bg-gray-900 hover:bg-gray-700 text-white inline-flex items-center cursor-pointer gap-2 px-4 rounded-full text-xs font-medium") {
18
- save_icon
19
- plain "Save"
20
- }
8
+ render Oversee::Field::Input.new(key: @key, value: @value, datatype: @datatype, **@options)
21
9
  end
22
10
  end
23
11
 
24
12
  private
25
13
 
26
- def resource_class_name
27
- @resource.class.name
28
- end
29
-
30
- def save_icon
31
- svg(
32
- stroke_width: "2.5",
33
- viewbox: "0 0 24 24",
34
- fill: "none",
35
- xmlns: "http://www.w3.org/2000/svg",
36
- class: "size-4",
37
- color: "currentColor"
38
- ) do |s|
39
- s.path(
40
- d: "M5 13L9 17L19 7",
41
- stroke: "currentColor",
42
- stroke_width: "2.5",
43
- stroke_linecap: "round",
44
- stroke_linejoin: "round"
45
- )
46
- end
14
+ def method
15
+ @method ||= @options[:method] || :patch
47
16
  end
48
-
49
17
  end
@@ -0,0 +1,5 @@
1
+ class Oversee::Field::Input::BelongsTo < Oversee::Field::Input
2
+ def view_template
3
+ input(type: "text", id: field_id, name: field_name, value:, class: "flex border px-4 py-2 text-sm w-full rounded-sm")
4
+ end
5
+ end
@@ -1,23 +1,8 @@
1
- class Oversee::Field::Input::Boolean < Phlex::HTML
2
- def initialize(key:, value:)
3
- @key = key
4
- @value = value
5
- end
6
-
1
+ class Oversee::Field::Input::Boolean < Oversee::Field::Input
7
2
  def view_template
8
3
  select(id: field_id, name: field_name, class: "flex w-full border rounded-sm px-4 py-2 text-sm") do
9
- option(value: 1, selected: @value) { "True" }
10
- option(value: 0, selected: !@value) { "False" }
4
+ option(value: 1, selected: value) { "True" }
5
+ option(value: 0, selected: !value) { "False" }
11
6
  end
12
7
  end
13
-
14
- private
15
-
16
- def field_id
17
- "resource_#{@key.to_s}"
18
- end
19
-
20
- def field_name
21
- "resource[#{@key.to_s}]"
22
- end
23
8
  end
@@ -0,0 +1,5 @@
1
+ class Oversee::Field::Input::Date < Oversee::Field::Input
2
+ def view_template
3
+ input(type: "datetime-local", id: field_id, name: field_name, value: value&.strftime("%Y-%m-%dT%T"), class: "flex w-full border rounded-sm px-4 py-2 text-sm")
4
+ end
5
+ end
@@ -1,20 +1,5 @@
1
- class Oversee::Field::Input::Datetime < Phlex::HTML
2
- def initialize(key:, value:)
3
- @key = key
4
- @value = value
5
- end
6
-
1
+ class Oversee::Field::Input::Datetime < Oversee::Field::Input
7
2
  def view_template
8
- input type: "datetime-local", id: field_id, name: field_name, value: @value&.strftime("%Y-%m-%dT%T"), class: "flex w-full border rounded-sm px-4 py-2 text-sm"
9
- end
10
-
11
- private
12
-
13
- def field_id
14
- "resource_#{@key.to_s}"
15
- end
16
-
17
- def field_name
18
- "resource[#{@key.to_s}]"
3
+ input(type: "datetime-local", id: field_id, name: field_name, value: value&.strftime("%Y-%m-%dT%T"), class: "flex w-full border rounded-sm px-4 py-2 text-sm")
19
4
  end
20
5
  end
@@ -1,20 +1,5 @@
1
- class Oversee::Field::Input::Integer < Phlex::HTML
2
- def initialize(key:, value:)
3
- @key = key
4
- @value = value
5
- end
6
-
1
+ class Oversee::Field::Input::Integer < Oversee::Field::Input
7
2
  def view_template
8
- input type: "number", id: field_id, name: field_name, value: @value, class: "flex w-full border rounded-sm px-4 py-2 text-sm"
9
- end
10
-
11
- private
12
-
13
- def field_id
14
- "resource_#{@key.to_s}"
15
- end
16
-
17
- def field_name
18
- "resource[#{@key.to_s}]"
3
+ input(type: "number", id: field_id, name: field_name, value:, class: "flex w-full border rounded-sm px-4 py-2 text-sm")
19
4
  end
20
5
  end
@@ -0,0 +1,5 @@
1
+ class Oversee::Field::Input::Json < Oversee::Field::Input
2
+ def view_template
3
+ textarea(type: "text", id: field_id, name: field_name, class: "flex border px-4 py-2 text-sm w-full rounded-sm") { value.to_s }
4
+ end
5
+ end
@@ -0,0 +1,10 @@
1
+ class Oversee::Field::Input::RichText < Oversee::Field::Input
2
+ register_element :trix_editor
3
+
4
+ def view_template
5
+ div do
6
+ input(type: "hidden", id: field_id, name: field_name, value:)
7
+ trix_editor(id: "#{field_id}_trix_editor", input: field_id)
8
+ end
9
+ end
10
+ end
@@ -1,20 +1,5 @@
1
- class Oversee::Field::Input::String < Phlex::HTML
2
- def initialize(key:, value:)
3
- @key = key
4
- @value = value
5
- end
6
-
1
+ class Oversee::Field::Input::String < Oversee::Field::Input
7
2
  def view_template
8
- input type: "text", id: field_id, name: field_name, value: @value, class: "flex border px-4 py-2 text-sm w-full rounded-sm"
9
- end
10
-
11
- private
12
-
13
- def field_id
14
- "resource_#{@key.to_s}"
15
- end
16
-
17
- def field_name
18
- "resource[#{@key.to_s}]"
3
+ input(type: "text", id: field_id, name: field_name, value:, class: "flex border px-4 py-2 text-sm w-full rounded-sm")
19
4
  end
20
5
  end