oversee 0.0.1 → 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 (50) hide show
  1. checksums.yaml +4 -4
  2. data/LICENCE +21 -0
  3. data/README.md +40 -0
  4. data/Rakefile +8 -0
  5. data/app/assets/config/oversee_manifest.js +1 -0
  6. data/app/assets/stylesheets/oversee/application.css +15 -0
  7. data/app/components/oversee/application_component.rb +5 -0
  8. data/app/components/oversee/card_component.rb +15 -0
  9. data/app/components/oversee/dashboard/sidebar_component.rb +127 -0
  10. data/app/components/oversee/field_component.rb +36 -0
  11. data/app/components/oversee/field_label_component.rb +155 -0
  12. data/app/components/oversee/fields/display_row_component.rb +58 -0
  13. data/app/components/oversee/fields/input/datetime_component.rb +27 -0
  14. data/app/components/oversee/fields/input/integer_component.rb +26 -0
  15. data/app/components/oversee/fields/input/string_component.rb +26 -0
  16. data/app/components/oversee/fields/value/boolean_component.rb +44 -0
  17. data/app/components/oversee/fields/value/datetime_component.rb +16 -0
  18. data/app/components/oversee/fields/value/enum_component.rb +16 -0
  19. data/app/components/oversee/fields/value/integer_component.rb +16 -0
  20. data/app/components/oversee/fields/value/string_component.rb +23 -0
  21. data/app/components/oversee/fields/value/text_component.rb +16 -0
  22. data/app/controllers/oversee/application_controller.rb +4 -0
  23. data/app/controllers/oversee/base_controller.rb +6 -0
  24. data/app/controllers/oversee/dashboard_controller.rb +21 -0
  25. data/app/controllers/oversee/resources/fields_controller.rb +45 -0
  26. data/app/controllers/oversee/resources_controller.rb +92 -0
  27. data/app/helpers/oversee/application_helper.rb +5 -0
  28. data/app/jobs/oversee/application_job.rb +4 -0
  29. data/app/mailers/oversee/application_mailer.rb +6 -0
  30. data/app/models/oversee/application_record.rb +5 -0
  31. data/app/oversee/cards.rb +2 -0
  32. data/app/views/layouts/oversee/application.html.erb +26 -0
  33. data/app/views/oversee/application/_javascript.html.erb +17 -0
  34. data/app/views/oversee/dashboard/show.html.erb +18 -0
  35. data/app/views/oversee/resources/_form.html.erb +10 -0
  36. data/app/views/oversee/resources/_input_field.html.erb +20 -0
  37. data/app/views/oversee/resources/edit.html.erb +31 -0
  38. data/app/views/oversee/resources/index.html.erb +59 -0
  39. data/app/views/oversee/resources/input_field.html.erb +1 -0
  40. data/app/views/oversee/resources/input_field.turbo_stream.erb +3 -0
  41. data/app/views/oversee/resources/show.html.erb +51 -0
  42. data/app/views/oversee/resources/update.turbo_stream.erb +3 -0
  43. data/app/views/shared/_sidebar.html.erb +32 -0
  44. data/config/routes.rb +10 -0
  45. data/lib/oversee/configuration.rb +27 -0
  46. data/lib/oversee/engine.rb +10 -0
  47. data/lib/oversee/version.rb +3 -0
  48. data/lib/oversee.rb +26 -4
  49. data/lib/tasks/oversee_tasks.rake +4 -0
  50. metadata +124 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1afb6e8a272250deb0cfd34142f7bf2b69fa0821c94de917613bef0b7f7b818f
4
- data.tar.gz: 3f5fbcfa55ecc3697e98e2073cde72e2c083efe3d4c4040f597597167e1bd264
3
+ metadata.gz: 197a8356cd3b94594875d7ef8426abaf4718f3ac42dd35fed5ab8937615dde91
4
+ data.tar.gz: 883cfa8fa1e3de33bc6300064b7e801ee666b8d5b4abbea794ed8fa740a26be2
5
5
  SHA512:
6
- metadata.gz: c09214f0ae7aac99a224fa358658b073250ad87c03ff9cd5d28d09fed6a611e3eb28150a58c0ff9ee324423055edea2b9e3d529af9a6183e993e17f29c4e2782
7
- data.tar.gz: ae3ceed82a37946a7c4005512c6dc74964a86ba4d7f0945c61baf77bdade783099da4fa13a306f796945c9e86515bfe29a79347a6268bc43a7cac741a6232890
6
+ metadata.gz: 7e35bb4c48f9b971cf95e9659f662054fe0917973f87a89d9837027cf99c6e40a9f498fcc2505191e20072ce42e8ac524ce916767fccef03ef28e5fc39785c23
7
+ data.tar.gz: 1e371d883dada238d0f9a333db69a67b8ad5fd0e360e5d348fc5b232d844648d8b163b566dd0b0900e0cd7f4206b07b5e254478ae557de93ce22d4c9cbd521e3
data/LICENCE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2023 Primevise
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,40 @@
1
+ [![Gem Version](https://badge.fury.io/rb/oversee.svg)](https://badge.fury.io/rb/oversee)
2
+
3
+ # 👓 Oversee
4
+ Plug & play admin dashboard for Rails applications.
5
+
6
+ Developed by [Primevise](https://primevise.com)
7
+
8
+ > [!NOTE]
9
+ > Oversee is still rather incomplete and only has the very basic features. It might significantly change and break things before a stable release.
10
+
11
+ ## Installation
12
+ Add it to your application by running
13
+
14
+ ```bash
15
+ $ bundle add oversee
16
+ ```
17
+
18
+
19
+ or add this line to your application's Gemfile:
20
+
21
+ ```ruby
22
+ gem "oversee"
23
+ ```
24
+
25
+ And then run:
26
+ ```bash
27
+ $ bundle
28
+ ```
29
+
30
+ ## Contributing
31
+ TBA
32
+
33
+ ## Notable mentions
34
+ This gem is inspired by other open source admin dashboards. A big thank you goes to these projects:
35
+
36
+ - [madmin](https://github.com/excid3/madmin)
37
+ - [Avo](https://github.com/avo-hq/avo)
38
+
39
+ ## License
40
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require "bundler/setup"
2
+
3
+ APP_RAKEFILE = File.expand_path("test/dummy/Rakefile", __dir__)
4
+ load "rails/tasks/engine.rake"
5
+
6
+ load "rails/tasks/statistics.rake"
7
+
8
+ require "bundler/gem_tasks"
@@ -0,0 +1 @@
1
+ //= link_directory ../stylesheets/oversee .css
@@ -0,0 +1,15 @@
1
+ /*
2
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
3
+ * listed below.
4
+ *
5
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6
+ * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
7
+ *
8
+ * You're free to add application-wide styles to this file and they'll appear at the bottom of the
9
+ * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
10
+ * files in this directory. Styles in this file should be added after the last require_* statement.
11
+ * It is generally better to create a new file per style scope.
12
+ *
13
+ *= require_tree .
14
+ *= require_self
15
+ */
@@ -0,0 +1,5 @@
1
+ class Oversee::ApplicationComponent < Phlex::HTML
2
+ include Phlex::Rails::Helpers::DOMID
3
+ include Phlex::Rails::Helpers::Routes
4
+ include Phlex::Rails::Helpers::LinkTo
5
+ end
@@ -0,0 +1,15 @@
1
+ module Oversee
2
+ class CardComponent < Phlex::HTML
3
+ def initialize(card_name: )
4
+ @card_name = card_name
5
+ @card = card_name.constantize.new
6
+ end
7
+
8
+ def view_template
9
+ div(class: "bg-white rounded-md border shadow-sm p-4") do
10
+ p(class: "text-xs uppercase font-medium text-gray-400") { @card.label }
11
+ h4(class: "mt-2 text-gray-900 text-2xl") { @card.value }
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,127 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Oversee::Dashboard::SidebarComponent < Oversee::ApplicationComponent
4
+ include Phlex::Rails::Helpers::LinkTo
5
+ include Phlex::Rails::Helpers::ButtonTo
6
+
7
+ def view_template
8
+ div(class: "bg-white border p-4 rounded-lg") do
9
+
10
+ p(class: "text-[0.7rem] uppercase text-gray-400 font-medium mb-2") { "Menu" }
11
+ ul(class: "text-sm text-gray-700") do
12
+ li do
13
+ link_to root_path,
14
+ class:
15
+ "flex items-center gap-2 hover:bg-gray-50 p-2 rounded-lg" do
16
+ layout_icon
17
+ span { "Dashboard" }
18
+ end
19
+ end
20
+ li do
21
+ link_to helpers.main_app.root_path,
22
+ class:
23
+ "flex items-center gap-2 hover:bg-gray-50 p-2 rounded-lg" do
24
+ main_app_icon
25
+ span { "Return to app" }
26
+ end
27
+ end
28
+ end
29
+
30
+ hr(class: "my-4")
31
+ p(class: "text-[0.7rem] uppercase text-gray-400 font-medium mb-2") { "Resources" }
32
+ ul(class: "text-sm text-gray-700") do
33
+ ApplicationRecord.descendants.map(&:to_s).sort.each do |resource_name|
34
+ li do
35
+ link_to helpers.resources_path(resource: resource_name), class: "flex items-center gap-2 hover:bg-gray-50 p-2 rounded-lg" do
36
+ folder_icon
37
+ span { resource_name }
38
+ end
39
+ end
40
+ end
41
+ end
42
+
43
+ hr(class: "my-4")
44
+ p(class: "text-xs text-gray-500") do
45
+ plain("Powered by ")
46
+ a(
47
+ href: "https://github.com/primevise/oversee",
48
+ class: "text-blue-500 hover:underline",
49
+ target: "_blank"
50
+ ) { "Oversee" }
51
+ end
52
+ end
53
+ end
54
+
55
+ private
56
+
57
+ def folder_icon
58
+ svg(
59
+ xmlns: "http://www.w3.org/2000/svg",
60
+ width: "24",
61
+ height: "24",
62
+ viewbox: "0 0 24 24",
63
+ fill: "none",
64
+ stroke: "currentColor",
65
+ stroke_width: "2",
66
+ stroke_linecap: "round",
67
+ stroke_linejoin: "round",
68
+ class: "h-4 w-4 text-gray-400"
69
+ ) do |s|
70
+ s.path(stroke: "none", d: "M0 0h24v24H0z", fill: "none")
71
+ s.path(
72
+ d:
73
+ "M5 4h4l3 3h7a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-14a2 2 0 0 1 -2 -2v-11a2 2 0 0 1 2 -2"
74
+ )
75
+ end
76
+ end
77
+
78
+ def main_app_icon
79
+ svg(
80
+ xmlns: "http://www.w3.org/2000/svg",
81
+ width: "24",
82
+ height: "24",
83
+ viewbox: "0 0 24 24",
84
+ fill: "none",
85
+ stroke: "currentColor",
86
+ stroke_width: "2",
87
+ stroke_linecap: "round",
88
+ stroke_linejoin: "round",
89
+ class: "h-4 w-4 text-gray-400"
90
+ ) do |s|
91
+ s.path(stroke: "none", d: "M0 0h24v24H0z", fill: "none")
92
+ s.path(d: "M9 21v-6a2 2 0 0 1 2 -2h2c.247 0 .484 .045 .702 .127")
93
+ s.path(d: "M19 12h2l-9 -9l-9 9h2v7a2 2 0 0 0 2 2h5")
94
+ s.path(d: "M16 22l5 -5")
95
+ s.path(d: "M21 21.5v-4.5h-4.5")
96
+ end
97
+ end
98
+
99
+ def layout_icon
100
+ svg(
101
+ xmlns: "http://www.w3.org/2000/svg",
102
+ width: "24",
103
+ height: "24",
104
+ viewbox: "0 0 24 24",
105
+ fill: "none",
106
+ stroke: "currentColor",
107
+ stroke_width: "2",
108
+ stroke_linecap: "round",
109
+ stroke_linejoin: "round",
110
+ class: "h-4 w-4 text-gray-400"
111
+ ) do |s|
112
+ s.path(stroke: "none", d: "M0 0h24v24H0z", fill: "none")
113
+ s.path(
114
+ d:
115
+ "M4 4m0 2a2 2 0 0 1 2 -2h2a2 2 0 0 1 2 2v1a2 2 0 0 1 -2 2h-2a2 2 0 0 1 -2 -2z"
116
+ )
117
+ s.path(
118
+ d:
119
+ "M4 13m0 2a2 2 0 0 1 2 -2h2a2 2 0 0 1 2 2v3a2 2 0 0 1 -2 2h-2a2 2 0 0 1 -2 -2z"
120
+ )
121
+ s.path(
122
+ d:
123
+ "M14 4m0 2a2 2 0 0 1 2 -2h2a2 2 0 0 1 2 2v12a2 2 0 0 1 -2 2h-2a2 2 0 0 1 -2 -2z"
124
+ )
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,36 @@
1
+ module Oversee
2
+ class FieldComponent < Phlex::HTML
3
+ # A map for components to use when rendering a value
4
+ VALUE_MAP = {
5
+ string: Oversee::Fields::Value::StringComponent,
6
+ boolean: Oversee::Fields::Value::BooleanComponent,
7
+ integer: Oversee::Fields::Value::IntegerComponent,
8
+ datetime: Oversee::Fields::Value::DatetimeComponent,
9
+ text: Oversee::Fields::Value::TextComponent,
10
+ enum: Oversee::Fields::Value::EnumComponent
11
+ }
12
+
13
+ # A map for components to use when rendering a form input field
14
+ INPUT_MAP ={
15
+ string: Oversee::Fields::Input::StringComponent,
16
+ integer: Oversee::Fields::Input::IntegerComponent,
17
+ datetime: Oversee::Fields::Input::DatetimeComponent,
18
+ }
19
+
20
+ MAP = {
21
+ value: VALUE_MAP,
22
+ input: INPUT_MAP,
23
+ }
24
+
25
+ def initialize(resource: nil, datatype: :string, kind: :value, key: nil, value: nil)
26
+ @kind = kind
27
+ @datatype = VALUE_MAP.key?(datatype) ? datatype : :text
28
+ @key = key
29
+ @value = value
30
+ end
31
+
32
+ def view_template
33
+ render MAP[@kind][@datatype.to_sym].new(key: @key, value: @value)
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,155 @@
1
+ module Oversee
2
+ class FieldLabelComponent < Phlex::HTML
3
+ def initialize(datatype: :string, key: nil)
4
+ @datatype = datatype
5
+ @key = key
6
+ end
7
+
8
+ def view_template
9
+ div(class:"inline-flex items-center space-x-2") do
10
+ div(class: "h-5 w-5 bg-gray-100 inline-flex items-center justify-center rounded") do
11
+ respond_to?("#{@datatype}_icon", true) ? send("#{@datatype}_icon") : data_icon
12
+ end
13
+ p(class: "uppercase text-xs text-gray-500 font-medium") { @key.to_s.humanize }
14
+ end
15
+ end
16
+
17
+ private
18
+
19
+ def string_icon
20
+ svg(
21
+ xmlns: "http://www.w3.org/2000/svg",
22
+ class: "h-2.5 w-2.5",
23
+ viewbox: "0 0 24 24",
24
+ stroke_width: "2",
25
+ stroke: "currentColor",
26
+ fill: "none",
27
+ stroke_linecap: "round",
28
+ stroke_linejoin: "round"
29
+ ) do |s|
30
+ s.path(stroke: "none", d: "M0 0h24v24H0z", fill: "none")
31
+ s.path(d: "M6 4l12 0")
32
+ s.path(d: "M12 4l0 16")
33
+ end
34
+ end
35
+
36
+ def integer_icon
37
+ svg(
38
+ xmlns: "http://www.w3.org/2000/svg",
39
+ class: "h-2.5 w-2.5",
40
+ viewbox: "0 0 24 24",
41
+ stroke_width: "2",
42
+ stroke: "currentColor",
43
+ fill: "none",
44
+ stroke_linecap: "round",
45
+ stroke_linejoin: "round"
46
+ ) do |s|
47
+ s.path(stroke: "none", d: "M0 0h24v24H0z", fill: "none")
48
+ s.path(d: "M4 17v-10l7 10v-10")
49
+ s.path(d: "M15 17h5")
50
+ s.path(d: "M17.5 10m-2.5 0a2.5 3 0 1 0 5 0a2.5 3 0 1 0 -5 0")
51
+ end
52
+ end
53
+
54
+ def text_icon
55
+ svg(
56
+ xmlns: "http://www.w3.org/2000/svg",
57
+ class: "h-2.5 w-2.5",
58
+ viewbox: "0 0 24 24",
59
+ stroke_width: "2",
60
+ stroke: "currentColor",
61
+ fill: "none",
62
+ stroke_linecap: "round",
63
+ stroke_linejoin: "round"
64
+ ) do |s|
65
+ s.path(stroke: "none", d: "M0 0h24v24H0z", fill: "none")
66
+ s.path(d: "M6 4l12 0")
67
+ s.path(d: "M12 4l0 16")
68
+ end
69
+ end
70
+
71
+ def boolean_icon
72
+ svg(
73
+ xmlns: "http://www.w3.org/2000/svg",
74
+ class: "h-2.5 w-2.5",
75
+ viewbox: "0 0 24 24",
76
+ stroke_width: "2",
77
+ stroke: "currentColor",
78
+ fill: "none",
79
+ stroke_linecap: "round",
80
+ stroke_linejoin: "round"
81
+ ) do |s|
82
+ s.path(stroke: "none", d: "M0 0h24v24H0z", fill: "none")
83
+ s.path(d: "M8 12m-2 0a2 2 0 1 0 4 0a2 2 0 1 0 -4 0")
84
+ s.path(
85
+ d:
86
+ "M2 6m0 6a6 6 0 0 1 6 -6h8a6 6 0 0 1 6 6v0a6 6 0 0 1 -6 6h-8a6 6 0 0 1 -6 -6z"
87
+ )
88
+ end
89
+ end
90
+
91
+ def enum_icon
92
+ svg(
93
+ xmlns: "http://www.w3.org/2000/svg",
94
+ class: "h-2.5 w-2.5",
95
+ viewbox: "0 0 24 24",
96
+ stroke_width: "2",
97
+ stroke: "currentColor",
98
+ fill: "none",
99
+ stroke_linecap: "round",
100
+ stroke_linejoin: "round"
101
+ ) do |s|
102
+ s.path(stroke: "none", d: "M0 0h24v24H0z", fill: "none")
103
+ s.path(
104
+ d:
105
+ "M3 3m0 2a2 2 0 0 1 2 -2h14a2 2 0 0 1 2 2v14a2 2 0 0 1 -2 2h-14a2 2 0 0 1 -2 -2z"
106
+ )
107
+ s.path(d: "M9 11l3 3l3 -3")
108
+ end
109
+ end
110
+
111
+ def datetime_icon
112
+ svg(
113
+ xmlns: "http://www.w3.org/2000/svg",
114
+ class: "h-2.5 w-2.5",
115
+ viewbox: "0 0 24 24",
116
+ stroke_width: "2",
117
+ stroke: "currentColor",
118
+ fill: "none",
119
+ stroke_linecap: "round",
120
+ stroke_linejoin: "round"
121
+ ) do |s|
122
+ s.path(stroke: "none", d: "M0 0h24v24H0z", fill: "none")
123
+ s.path(
124
+ d:
125
+ "M4 7a2 2 0 0 1 2 -2h12a2 2 0 0 1 2 2v12a2 2 0 0 1 -2 2h-12a2 2 0 0 1 -2 -2v-12z"
126
+ )
127
+ s.path(d: "M16 3v4")
128
+ s.path(d: "M8 3v4")
129
+ s.path(d: "M4 11h16")
130
+ s.path(d: "M11 15h1")
131
+ s.path(d: "M12 15v3")
132
+ end
133
+ end
134
+
135
+ def data_icon
136
+ svg(
137
+ xmlns: "http://www.w3.org/2000/svg",
138
+ viewbox: "0 0 24 24",
139
+ fill: "none",
140
+ stroke: "currentColor",
141
+ stroke_width: "2",
142
+ stroke_linecap: "round",
143
+ stroke_linejoin: "round",
144
+ class: "h-2.5 w-2.5",
145
+ ) do |s|
146
+ s.path(stroke: "none", d: "M0 0h24v24H0z", fill: "none")
147
+ s.path(d: "M15 12h.01")
148
+ s.path(d: "M12 12h.01")
149
+ s.path(d: "M9 12h.01")
150
+ s.path(d: "M6 19a2 2 0 0 1 -2 -2v-4l-1 -1l1 -1v-4a2 2 0 0 1 2 -2")
151
+ s.path(d: "M18 19a2 2 0 0 0 2 -2v-4l1 -1l-1 -1v-4a2 2 0 0 0 -2 -2")
152
+ end
153
+ end
154
+ end
155
+ end
@@ -0,0 +1,58 @@
1
+ class Oversee::Fields::DisplayRowComponent < Phlex::HTML
2
+ include Phlex::Rails::Helpers::DOMID
3
+ include Phlex::Rails::Helpers::Routes
4
+
5
+ def initialize(key:, resource:, datatype:, value:)
6
+ @datatype = datatype
7
+ @resource = resource
8
+ @key = key
9
+ @value = value
10
+ end
11
+
12
+ def view_template
13
+ div(
14
+ id: dom_id(@resource, @key),
15
+ class:
16
+ "py-4 px-8 hover:bg-gray-50 group flex items-center justify-between"
17
+ ) do
18
+ div do
19
+ render Oversee::FieldLabelComponent.new(key: @key, datatype: @datatype)
20
+ div(class: "mt-2 bg-gray-100 rounded px-4 py-2 min-w-64") do
21
+ render Oversee::FieldComponent.new(kind: :value, datatype: @datatype, value: @resource.send(@key))
22
+ end
23
+ end
24
+ div do
25
+ a(
26
+ href:
27
+ (
28
+ helpers.input_field_resource_path(
29
+ @resource.id,
30
+ resource: @resource.class,
31
+ key: @key
32
+ )
33
+ ),
34
+ data_turbo_stream: "true",
35
+ class:
36
+ "opacity-0 group-hover:opacity-100 transition h-8 w-8 rounded-md bg-white border inline-flex justify-center items-center text-gray-400 hover:text-gray-800"
37
+ ) do
38
+ svg(
39
+ xmlns: "http://www.w3.org/2000/svg",
40
+ viewbox: "0 0 16 16",
41
+ fill: "currentColor",
42
+ data_slot: "icon",
43
+ class: "w-4 h-4"
44
+ ) do |s|
45
+ s.path(
46
+ d:
47
+ "M13.488 2.513a1.75 1.75 0 0 0-2.475 0L6.75 6.774a2.75 2.75 0 0 0-.596.892l-.848 2.047a.75.75 0 0 0 .98.98l2.047-.848a2.75 2.75 0 0 0 .892-.596l4.261-4.262a1.75 1.75 0 0 0 0-2.474Z"
48
+ )
49
+ s.path(
50
+ d:
51
+ "M4.75 3.5c-.69 0-1.25.56-1.25 1.25v6.5c0 .69.56 1.25 1.25 1.25h6.5c.69 0 1.25-.56 1.25-1.25V9A.75.75 0 0 1 14 9v2.25A2.75 2.75 0 0 1 11.25 14h-6.5A2.75 2.75 0 0 1 2 11.25v-6.5A2.75 2.75 0 0 1 4.75 2H7a.75.75 0 0 1 0 1.5H4.75Z"
52
+ )
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,27 @@
1
+
2
+ module Oversee
3
+ module Fields
4
+ module Input
5
+ class DatetimeComponent < Phlex::HTML
6
+ def initialize(key:, value:)
7
+ @key = key
8
+ @value = value
9
+ end
10
+
11
+ def view_template
12
+ input type: "datetime-local", id: field_id, name: field_name, value: @value.strftime("%Y-%m-%dT%T"), class: "border rounded-md px-4 py-2 text-sm"
13
+ end
14
+
15
+ private
16
+
17
+ def field_id
18
+ "resource_#{@key.to_s}"
19
+ end
20
+
21
+ def field_name
22
+ "resource[#{@key.to_s}]"
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,26 @@
1
+ module Oversee
2
+ module Fields
3
+ module Input
4
+ class IntegerComponent < Phlex::HTML
5
+ def initialize(key:, value:)
6
+ @key = key
7
+ @value = value
8
+ end
9
+
10
+ def view_template
11
+ input type: "number", id: field_id, name: field_name, value: @value, class: "border rounded-md px-4 py-2 text-sm"
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
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,26 @@
1
+ module Oversee
2
+ module Fields
3
+ module Input
4
+ class StringComponent < Phlex::HTML
5
+ def initialize(key:, value:)
6
+ @key = key
7
+ @value = value
8
+ end
9
+
10
+ def view_template
11
+ input type: "text", id: field_id, name: field_name, value: @value, class: "border rounded-md px-4 py-2 text-sm"
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
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,44 @@
1
+ module Oversee
2
+ module Fields
3
+ module Value
4
+ class BooleanComponent < Phlex::HTML
5
+ def initialize(key: nil, value: nil, kind: :value)
6
+ @value = value
7
+ end
8
+
9
+ def view_template
10
+ return p(class: "text-gray-500 text-xs"){ "—" } if @value.blank?
11
+ if @value
12
+ svg(
13
+ xmlns: "http://www.w3.org/2000/svg",
14
+ viewbox: "0 0 16 16",
15
+ fill: "currentColor",
16
+ data_slot: "icon",
17
+ class: "w-4 h-4 text-emerald-500"
18
+ ) do |s|
19
+ s.path(
20
+ fill_rule: "evenodd",
21
+ d:
22
+ "M12.416 3.376a.75.75 0 0 1 .208 1.04l-5 7.5a.75.75 0 0 1-1.154.114l-3-3a.75.75 0 0 1 1.06-1.06l2.353 2.353 4.493-6.74a.75.75 0 0 1 1.04-.207Z",
23
+ clip_rule: "evenodd"
24
+ )
25
+ end
26
+ else
27
+ svg(
28
+ xmlns: "http://www.w3.org/2000/svg",
29
+ viewbox: "0 0 16 16",
30
+ fill: "currentColor",
31
+ data_slot: "icon",
32
+ class: "w-4 h-4 text-red-400"
33
+ ) do |s|
34
+ s.path(
35
+ d:
36
+ "M5.28 4.22a.75.75 0 0 0-1.06 1.06L6.94 8l-2.72 2.72a.75.75 0 1 0 1.06 1.06L8 9.06l2.72 2.72a.75.75 0 1 0 1.06-1.06L9.06 8l2.72-2.72a.75.75 0 0 0-1.06-1.06L8 6.94 5.28 4.22Z"
37
+ )
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,16 @@
1
+ module Oversee
2
+ module Fields
3
+ module Value
4
+ class DatetimeComponent < Phlex::HTML
5
+ def initialize(key: nil, value: nil, kind: :value)
6
+ @value = value
7
+ end
8
+
9
+ def view_template
10
+ return p(class: "text-gray-500 text-xs"){ "—" } if @value.blank?
11
+ p { @value&.to_fs(:short) || "N/A" }
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ module Oversee
2
+ module Fields
3
+ module Value
4
+ class EnumComponent < Phlex::HTML
5
+ def initialize(key: nil, value: nil, kind: :value)
6
+ @value = value
7
+ end
8
+
9
+ def view_template
10
+ return p(class: "text-gray-500 text-xs"){ "—" } if @value.blank?
11
+ p { @value.to_s }
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ module Oversee
2
+ module Fields
3
+ module Value
4
+ class IntegerComponent < Phlex::HTML
5
+ def initialize(key: nil, value: nil, kind: :value)
6
+ @value = value
7
+ end
8
+
9
+ def view_template
10
+ return p(class: "text-gray-500 text-xs"){ "—" } if @value.blank?
11
+ p { @value }
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end