oversee 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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