oversee 0.2.0 → 0.3.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 (51) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/config/oversee_manifest.js +2 -0
  3. data/app/components/oversee/dashboard/filters.rb +23 -19
  4. data/app/components/oversee/dashboard/header.rb +34 -18
  5. data/app/components/oversee/dashboard/index.rb +23 -11
  6. data/app/components/oversee/dashboard/javascript.rb +4 -4
  7. data/app/components/oversee/dashboard/pagination.rb +1 -1
  8. data/app/components/oversee/dashboard/sidebar.rb +38 -1
  9. data/app/components/oversee/dashboard/tailwind.rb +30 -1
  10. data/app/components/oversee/field/display.rb +19 -10
  11. data/app/components/oversee/field/form.rb +4 -23
  12. data/app/components/oversee/field/input/belongs_to.rb +22 -0
  13. data/app/components/oversee/field/input/boolean.rb +1 -11
  14. data/app/components/oversee/field/input/datetime.rb +1 -11
  15. data/app/components/oversee/field/input/integer.rb +1 -11
  16. data/app/components/oversee/field/input/rich_text.rb +18 -0
  17. data/app/components/oversee/field/input/string.rb +1 -11
  18. data/app/components/oversee/field/input.rb +13 -5
  19. data/app/components/oversee/field/label.rb +3 -2
  20. data/app/components/oversee/field/value/belongs_to.rb +21 -0
  21. data/app/components/oversee/field/value/datetime.rb +1 -1
  22. data/app/components/oversee/field/value/rich_text.rb +9 -0
  23. data/app/components/oversee/field/value.rb +11 -5
  24. data/app/components/oversee/layout/application.rb +46 -0
  25. data/app/components/oversee/resources/index.rb +21 -2
  26. data/app/components/oversee/resources/new.rb +7 -3
  27. data/app/components/oversee/resources/show.rb +150 -69
  28. data/app/components/oversee/resources/table.rb +7 -1
  29. data/app/controllers/oversee/dashboard_controller.rb +1 -1
  30. data/app/controllers/oversee/resources/fields_controller.rb +20 -36
  31. data/app/controllers/oversee/resources_controller.rb +22 -22
  32. data/app/javascript/oversee/application.js +3 -0
  33. data/app/javascript/oversee/controllers/index.js +8 -0
  34. data/app/javascript/oversee/controllers/reveal_controller.js +7 -0
  35. data/app/javascript/oversee/controllers/sidebar/state_controller.js +21 -0
  36. data/app/models/oversee/resource.rb +43 -17
  37. data/app/{oversee → service/oversee}/filter.rb +2 -2
  38. data/app/{oversee → service/oversee}/search.rb +1 -1
  39. data/app/views/oversee/base.rb +5 -0
  40. data/config/importmap.rb +14 -0
  41. data/config/routes.rb +16 -10
  42. data/lib/generators/oversee/install_generator.rb +7 -0
  43. data/lib/oversee/engine.rb +19 -0
  44. data/lib/oversee/version.rb +1 -1
  45. data/lib/oversee.rb +12 -0
  46. data/lib/tasks/oversee_tasks.rake +6 -4
  47. metadata +31 -8
  48. data/app/jobs/oversee/application_job.rb +0 -4
  49. data/app/oversee/cards.rb +0 -2
  50. data/app/oversee/resource.rb +0 -10
  51. 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: c31a8c277449dfaec238f66cfc8e404a64c51dff4beef1a944fee85c5935991c
4
+ data.tar.gz: f3fcd62d4ff3184f5b9f97273c2269e986b5f03736a9961440aca242b38a1292
5
5
  SHA512:
6
- metadata.gz: 577e608656e45f6797397728ec9820cd39854eccffa550d7d60b3735581f8480817a3d4ce235c49bcceab3b9394b06356637ec17c3c2808f2549158ad7a32ea1
7
- data.tar.gz: 4ef646cc6bef74b8ffccfbd97c796bc147d6f9a144ff5f4068630235e1967ff6fe6f9b4e08bfcdb899c49bdbe106e8a37cbde59603377edf2fd7c8866c115cbc
6
+ metadata.gz: ad42840ab6b72667e5e16853cea4d9028fc1356fd4ff2ec7d3909b6102c2fc80dca9287245ad4ab62021181c238beae371f77b473f1f9464bf0b1162a29946c5
7
+ data.tar.gz: 229f928f44cfe6d6535cd8ef6682472a9f5ecf59e29bc65714ed71e1c6147ab48b582e5c065fc1e9233d5e536155e16d8750a1fc92f3e74bd97e3720cbc58e42
@@ -0,0 +1,2 @@
1
+ //= link oversee/application.js
2
+ //= link_tree ../../javascript/oversee/controllers .js
@@ -8,29 +8,33 @@ class Oversee::Dashboard::Filters < Oversee::Base
8
8
  end
9
9
 
10
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
11
+ div(class: "flex items-center justify-between") do
12
+ div(class: "flex items-center gap-2") do
13
+ if show_action_section?
14
+ 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
15
+ render Phlex::Icons::Iconoir::FilterAlt.new(class: "size-3")
16
+ plain "Filters"
25
17
  end
26
18
  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") }
19
+ if false
20
+ 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
21
+ render Phlex::Icons::Iconoir::XMark.new(class: "size-4 text-gray-500")
22
+ plain "Clear sorting"
31
23
  end
32
24
  end
33
25
  end
26
+ div(class: "flex items-center gap-4") do
27
+ form(action: "", class: "flex items-center gap-2") do
28
+ input(
29
+ type: :search,
30
+ name: :query,
31
+ value: @params[:query],
32
+ placeholder: search_placeholder,
33
+ 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"
34
+ )
35
+ 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") }
36
+ end
37
+ end
34
38
  end
35
39
  end
36
40
 
@@ -46,7 +50,7 @@ class Oversee::Dashboard::Filters < Oversee::Base
46
50
  end
47
51
 
48
52
  def search_placeholder
49
- context = Search.new(collection: nil, resource_class: @params[:resource_class_name].constantize)
53
+ context = Oversee::Search.new(collection: nil, resource_class: @params[:resource_class_name].constantize)
50
54
  attr = context.default_searchable_attribute
51
55
 
52
56
  "Search by #{attr}"
@@ -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,38 @@
1
1
  class Oversee::Field::Display < Oversee::Base
2
- def initialize(resource:, key: nil, value: nil, datatype: :string, interactive: true)
2
+
3
+ attr_reader :resource
4
+ attr_reader :key
5
+ attr_reader :value
6
+ attr_reader :datatype
7
+
8
+ def initialize(resource:, key: nil, value: nil, datatype: :string, **options)
3
9
  @resource = resource
4
10
  @key = key
5
11
  @value = value
6
12
  @datatype = datatype
7
- @interactive = interactive
13
+ @options = options
8
14
  end
9
15
 
10
16
  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),
17
+ html_tag(
18
+ id: dom_id(resource, key),
19
+ href: helpers.resource_input_path(resource_class_name:, key:, datatype:),
14
20
  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)
21
+ data: { turbo_stream: true }
22
+ ) do
23
+ render Oversee::Field::Value.new(key:, value:, datatype:, **@options)
17
24
  end
18
25
  end
19
26
 
20
27
  private
21
28
 
22
29
  def resource_class_name
23
- @resource.class.name
30
+ @resource_class_name ||= @resource.class.name
24
31
  end
25
32
 
26
- def wrapper_tag(...)
27
- @interactive ? a(...) : div(...)
33
+ def html_tag(...)
34
+ edittable? ? a(...) : div(...)
28
35
  end
36
+
37
+ def edittable? = @options[:edittable] || true
29
38
  end
@@ -1,21 +1,22 @@
1
1
  class Oversee::Field::Form < Oversee::Base
2
2
  include Phlex::Rails::Helpers::FormWith
3
3
 
4
- def initialize(resource:, key: nil, value: nil, datatype: :string, method: :patch)
4
+ def initialize(resource:, key: nil, value: nil, datatype: :string, method: :patch, **options)
5
5
  @resource = resource
6
6
  @key = key
7
7
  @value = value
8
8
  @datatype = datatype
9
9
  @method = method
10
+ @options = options
10
11
  end
11
12
 
12
13
  def view_template
13
14
  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|
14
15
  input type: :hidden, id: "oversee_key", name: "oversee_key", value: @key.to_s
15
16
  input type: :hidden, id: "oversee_datatype", name: "oversee_datatype", value: @datatype
16
- render Oversee::Field::Input.new(key: @key, value: @value, datatype: @datatype)
17
+ render Oversee::Field::Input.new(key: @key, value: @value, datatype: @datatype, **@options)
17
18
  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
+ render Phlex::Icons::Iconoir::Check.new(class: "size-4")
19
20
  plain "Save"
20
21
  }
21
22
  end
@@ -26,24 +27,4 @@ class Oversee::Field::Form < Oversee::Base
26
27
  def resource_class_name
27
28
  @resource.class.name
28
29
  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
47
- end
48
-
49
30
  end
@@ -0,0 +1,22 @@
1
+ class Oversee::Field::Input::BelongsTo < Oversee::Field::Input
2
+ def initialize(key:, value:, **options)
3
+ @key = key
4
+ @value = value
5
+ end
6
+
7
+ 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
+
10
+ # select(id: field_id, name: field_name, class: "flex w-full border rounded-sm px-4 py-2 text-sm") do
11
+
12
+ # option(value: 1, selected: @value) { "True" }
13
+ # option(value: 0, selected: !@value) { "False" }
14
+ # end
15
+ end
16
+
17
+ private
18
+
19
+ def select_values
20
+
21
+ end
22
+ end
@@ -1,4 +1,4 @@
1
- class Oversee::Field::Input::Boolean < Phlex::HTML
1
+ class Oversee::Field::Input::Boolean < Oversee::Field::Input
2
2
  def initialize(key:, value:)
3
3
  @key = key
4
4
  @value = value
@@ -10,14 +10,4 @@ class Oversee::Field::Input::Boolean < Phlex::HTML
10
10
  option(value: 0, selected: !@value) { "False" }
11
11
  end
12
12
  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
13
  end
@@ -1,4 +1,4 @@
1
- class Oversee::Field::Input::Datetime < Phlex::HTML
1
+ class Oversee::Field::Input::Datetime < Oversee::Field::Input
2
2
  def initialize(key:, value:)
3
3
  @key = key
4
4
  @value = value
@@ -7,14 +7,4 @@ class Oversee::Field::Input::Datetime < Phlex::HTML
7
7
  def view_template
8
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
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}]"
19
- end
20
10
  end
@@ -1,4 +1,4 @@
1
- class Oversee::Field::Input::Integer < Phlex::HTML
1
+ class Oversee::Field::Input::Integer < Oversee::Field::Input
2
2
  def initialize(key:, value:)
3
3
  @key = key
4
4
  @value = value
@@ -7,14 +7,4 @@ class Oversee::Field::Input::Integer < Phlex::HTML
7
7
  def view_template
8
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
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}]"
19
- end
20
10
  end
@@ -0,0 +1,18 @@
1
+ class Oversee::Field::Input::RichText < Oversee::Field::Input
2
+ register_element :trix_editor
3
+
4
+ attr_reader :key
5
+ attr_reader :value
6
+
7
+ def initialize(key:, value:)
8
+ @key = key
9
+ @value = value
10
+ end
11
+
12
+ def view_template
13
+ div do
14
+ input(type: "hidden", id: field_id, name: field_name, value:)
15
+ trix_editor(id: "#{field_id}_trix_editor", input: field_id)
16
+ end
17
+ end
18
+ end
@@ -1,4 +1,4 @@
1
- class Oversee::Field::Input::String < Phlex::HTML
1
+ class Oversee::Field::Input::String < Oversee::Field::Input
2
2
  def initialize(key:, value:)
3
3
  @key = key
4
4
  @value = value
@@ -7,14 +7,4 @@ class Oversee::Field::Input::String < Phlex::HTML
7
7
  def view_template
8
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
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}]"
19
- end
20
10
  end
@@ -1,21 +1,24 @@
1
1
  class Oversee::Field::Input < Oversee::Base
2
2
  MAP = {
3
- string: Oversee::Field::Input::String,
3
+ belongs_to: Oversee::Field::Input::BelongsTo,
4
4
  boolean: Oversee::Field::Input::Boolean,
5
- integer: Oversee::Field::Input::Integer,
6
5
  datetime: Oversee::Field::Input::Datetime,
6
+ enum: Oversee::Field::Input::String,
7
+ integer: Oversee::Field::Input::Integer,
8
+ rich_text: Oversee::Field::Input::RichText,
9
+ string: Oversee::Field::Input::String,
7
10
  text: Oversee::Field::Input::String,
8
- enum: Oversee::Field::Input::String
9
11
  }
10
12
 
11
- def initialize(key: nil, value: nil, datatype: :string)
13
+ def initialize(key: nil, value: nil, datatype: :string, **options)
12
14
  @key = key
13
15
  @value = value
14
16
  @datatype = datatype
17
+ @options = options
15
18
  end
16
19
 
17
20
  def view_template
18
- render component_class.new(key: @key, value: @value)
21
+ render component_class.new(key: @key, value: @value, **@options)
19
22
  end
20
23
 
21
24
  private
@@ -23,4 +26,9 @@ class Oversee::Field::Input < Oversee::Base
23
26
  def component_class
24
27
  MAP[@datatype.to_sym] || Oversee::Field::Input::String
25
28
  end
29
+
30
+ private
31
+
32
+ def field_id = "resource_#{@key.to_s}"
33
+ def field_name = "resource[#{@key.to_s}]"
26
34
  end
@@ -2,6 +2,7 @@ class Oversee::Field::Label < Oversee::Base
2
2
  ICON_MAP = {
3
3
  string: Phlex::Icons::Iconoir::Text,
4
4
  text: Phlex::Icons::Iconoir::TextSquare,
5
+ rich_text: Phlex::Icons::Iconoir::TextSquare,
5
6
  integer: Phlex::Icons::Iconoir::Number0Square,
6
7
  datetime: Phlex::Icons::Iconoir::Calendar,
7
8
  boolean: Phlex::Icons::Iconoir::SwitchOn,
@@ -14,11 +15,11 @@ class Oversee::Field::Label < Oversee::Base
14
15
  end
15
16
 
16
17
  def view_template
17
- div(class:"inline-flex items-center space-x-2") do
18
+ div(id: "#{@key}_label", class:"inline-flex items-center space-x-2") do
18
19
  div(class: "size-5 bg-gray-100 inline-flex items-center justify-center") do
19
20
  render ICON_MAP[@datatype] ? ICON_MAP[@datatype].new(class: "size-3") : ICON_MAP[:data].new(class: "size-3")
20
21
  end
21
- label(class: "uppercase text-xs text-gray-š00 font-medium block") { @key.to_s.humanize(keep_id_suffix: true) }
22
+ label(class: "uppercase text-xs text-gray-700 font-medium block cursor-auto") { @key.to_s.humanize(keep_id_suffix: true) }
22
23
  end
23
24
  end
24
25
  end
@@ -0,0 +1,21 @@
1
+ class Oversee::Field::Value::BelongsTo < Phlex::HTML
2
+ def initialize(key: nil, value: nil, **options)
3
+ @key = key
4
+ @value = value
5
+ @options = options
6
+ end
7
+
8
+ def view_template
9
+ p(title: @value, class:"inline-flex items-center gap-1") do
10
+ if display_key?
11
+ span { @key.humanize }
12
+ span {"|"}
13
+ end
14
+ span { @value }
15
+ end
16
+ end
17
+
18
+ private
19
+
20
+ def display_key? = !!@options[:display_key]
21
+ end
@@ -4,6 +4,6 @@ class Oversee::Field::Value::Datetime < Phlex::HTML
4
4
  end
5
5
 
6
6
  def view_template
7
- time(title: @value) { @value&.to_fs(:long) || "N/A" }
7
+ time(title: @value.to_s) { @value&.to_fs(:long) || "N/A" }
8
8
  end
9
9
  end
@@ -0,0 +1,9 @@
1
+ class Oversee::Field::Value::RichText < Phlex::HTML
2
+ def initialize(datatype: :string, key: nil, value: nil, kind: :value)
3
+ @value = value
4
+ end
5
+
6
+ def view_template
7
+ p(class: "truncate") { @value }
8
+ end
9
+ end