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.
- checksums.yaml +4 -4
- data/LICENCE +21 -0
- data/README.md +40 -0
- data/Rakefile +8 -0
- data/app/assets/config/oversee_manifest.js +1 -0
- data/app/assets/stylesheets/oversee/application.css +15 -0
- data/app/components/oversee/application_component.rb +5 -0
- data/app/components/oversee/card_component.rb +15 -0
- data/app/components/oversee/dashboard/sidebar_component.rb +127 -0
- data/app/components/oversee/field_component.rb +36 -0
- data/app/components/oversee/field_label_component.rb +155 -0
- data/app/components/oversee/fields/display_row_component.rb +58 -0
- data/app/components/oversee/fields/input/datetime_component.rb +27 -0
- data/app/components/oversee/fields/input/integer_component.rb +26 -0
- data/app/components/oversee/fields/input/string_component.rb +26 -0
- data/app/components/oversee/fields/value/boolean_component.rb +44 -0
- data/app/components/oversee/fields/value/datetime_component.rb +16 -0
- data/app/components/oversee/fields/value/enum_component.rb +16 -0
- data/app/components/oversee/fields/value/integer_component.rb +16 -0
- data/app/components/oversee/fields/value/string_component.rb +23 -0
- data/app/components/oversee/fields/value/text_component.rb +16 -0
- data/app/controllers/oversee/application_controller.rb +4 -0
- data/app/controllers/oversee/base_controller.rb +6 -0
- data/app/controllers/oversee/dashboard_controller.rb +21 -0
- data/app/controllers/oversee/resources/fields_controller.rb +45 -0
- data/app/controllers/oversee/resources_controller.rb +92 -0
- data/app/helpers/oversee/application_helper.rb +5 -0
- data/app/jobs/oversee/application_job.rb +4 -0
- data/app/mailers/oversee/application_mailer.rb +6 -0
- data/app/models/oversee/application_record.rb +5 -0
- data/app/oversee/cards.rb +2 -0
- data/app/views/layouts/oversee/application.html.erb +26 -0
- data/app/views/oversee/application/_javascript.html.erb +17 -0
- data/app/views/oversee/dashboard/show.html.erb +18 -0
- data/app/views/oversee/resources/_form.html.erb +10 -0
- data/app/views/oversee/resources/_input_field.html.erb +20 -0
- data/app/views/oversee/resources/edit.html.erb +31 -0
- data/app/views/oversee/resources/index.html.erb +59 -0
- data/app/views/oversee/resources/input_field.html.erb +1 -0
- data/app/views/oversee/resources/input_field.turbo_stream.erb +3 -0
- data/app/views/oversee/resources/show.html.erb +51 -0
- data/app/views/oversee/resources/update.turbo_stream.erb +3 -0
- data/app/views/shared/_sidebar.html.erb +32 -0
- data/config/routes.rb +10 -0
- data/lib/oversee/configuration.rb +27 -0
- data/lib/oversee/engine.rb +10 -0
- data/lib/oversee/version.rb +3 -0
- data/lib/oversee.rb +26 -4
- data/lib/tasks/oversee_tasks.rake +4 -0
- metadata +124 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 197a8356cd3b94594875d7ef8426abaf4718f3ac42dd35fed5ab8937615dde91
|
4
|
+
data.tar.gz: 883cfa8fa1e3de33bc6300064b7e801ee666b8d5b4abbea794ed8fa740a26be2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
+
[](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 @@
|
|
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,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
|