oversee 0.2.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +8 -3
- data/app/assets/config/oversee_manifest.js +2 -0
- data/app/components/oversee/dashboard/actions.rb +58 -0
- data/app/components/oversee/dashboard/filter.rb +12 -0
- data/app/components/oversee/dashboard/filters.rb +5 -51
- data/app/components/oversee/dashboard/header.rb +34 -18
- data/app/components/oversee/dashboard/index.rb +23 -11
- data/app/components/oversee/dashboard/javascript.rb +4 -4
- data/app/components/oversee/dashboard/pagination.rb +1 -1
- data/app/components/oversee/dashboard/sidebar.rb +38 -1
- data/app/components/oversee/dashboard/tailwind.rb +30 -1
- data/app/components/oversee/field/display.rb +12 -21
- data/app/components/oversee/field/form.rb +5 -37
- data/app/components/oversee/field/input/belongs_to.rb +5 -0
- data/app/components/oversee/field/input/boolean.rb +3 -18
- data/app/components/oversee/field/input/date.rb +5 -0
- data/app/components/oversee/field/input/datetime.rb +2 -17
- data/app/components/oversee/field/input/integer.rb +2 -17
- data/app/components/oversee/field/input/json.rb +5 -0
- data/app/components/oversee/field/input/rich_text.rb +10 -0
- data/app/components/oversee/field/input/string.rb +2 -17
- data/app/components/oversee/field/input.rb +13 -11
- data/app/components/oversee/field/label.rb +16 -15
- data/app/components/oversee/field/set.rb +36 -0
- data/app/components/oversee/field/value/belongs_to.rb +15 -0
- data/app/components/oversee/field/value/boolean.rb +2 -47
- data/app/components/oversee/field/value/date.rb +5 -0
- data/app/components/oversee/field/value/datetime.rb +2 -6
- data/app/components/oversee/field/value/enum.rb +2 -6
- data/app/components/oversee/field/value/integer.rb +2 -6
- data/app/components/oversee/field/value/json.rb +6 -0
- data/app/components/oversee/field/value/rich_text.rb +5 -0
- data/app/components/oversee/field/value/string.rb +3 -10
- data/app/components/oversee/field/value/text.rb +2 -6
- data/app/components/oversee/field/value.rb +14 -5
- data/app/components/oversee/field.rb +42 -0
- data/app/components/oversee/flash.rb +39 -0
- data/app/components/oversee/layout/application.rb +46 -0
- data/app/components/oversee/resources/index.rb +22 -3
- data/app/components/oversee/resources/new.rb +7 -3
- data/app/components/oversee/resources/show.rb +139 -68
- data/app/components/oversee/resources/table.rb +8 -2
- data/app/controllers/oversee/dashboard_controller.rb +1 -1
- data/app/controllers/oversee/resources/fields_controller.rb +24 -36
- data/app/controllers/oversee/resources_controller.rb +29 -24
- data/app/javascript/oversee/application.js +3 -0
- data/app/javascript/oversee/controllers/clipboard_controller.js +21 -0
- data/app/javascript/oversee/controllers/index.js +9 -0
- data/app/javascript/oversee/controllers/notification_controller.js +17 -0
- data/app/javascript/oversee/controllers/reveal_controller.js +19 -0
- data/app/javascript/oversee/controllers/sidebar/state_controller.js +21 -0
- data/app/models/oversee/resource.rb +49 -20
- data/app/{oversee → service/oversee}/filter.rb +2 -2
- data/app/{oversee → service/oversee}/search.rb +1 -1
- data/app/views/oversee/base.rb +5 -0
- data/config/importmap.rb +14 -0
- data/config/routes.rb +16 -10
- data/lib/generators/oversee/install_generator.rb +7 -0
- data/lib/oversee/engine.rb +19 -0
- data/lib/oversee/version.rb +1 -1
- data/lib/oversee.rb +13 -0
- data/lib/tasks/oversee_tasks.rake +6 -4
- metadata +71 -9
- data/app/jobs/oversee/application_job.rb +0 -4
- data/app/oversee/cards.rb +0 -2
- data/app/oversee/resource.rb +0 -10
- 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:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 82a5bb3d0823ed6874fe8b7bb09934ed3b72b7b9a2964da6c6d8cdd7b82ac28a
|
4
|
+
data.tar.gz: 5ddf616584c7319a2ef611227fb4f5e0cf876c1dc20b1228c47330411715054c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 16cf0583966c0f07deae2be76299544a4fb5678efc5345a292acc0ad628d263a979b44e2d60f8749cc87bbfd5471eb85cfe5619fdc58af5bedb8b9e5a0efe755
|
7
|
+
data.tar.gz: f0d8ae31255ca03aecb010393356d55a9ac63b99699b50b8c9b6bae8d6c11c8f1d3b876dcd6fe9c9118e19c6015989f45f3e7ed74eadb259e885007eb215e764
|
data/README.md
CHANGED
@@ -1,10 +1,14 @@
|
|
1
|
-
|
2
1
|
# Oversee
|
3
2
|
|
4
|
-
Plug & play
|
3
|
+
Plug & play content management system (CMS) for Rails applications. Some may call it an admin dashboard too.
|
5
4
|
|
5
|
+
<a href="https://rubygems.org/gems/oversee">
|
6
|
+
<img alt="Oversee GEM Version" src="https://img.shields.io/gem/v/oversee?color=10b981&include_prereleases&logo=ruby&logoColor=f43f5e">
|
7
|
+
</a>
|
6
8
|
|
7
|
-
|
9
|
+
<a href="https://rubygems.org/gems/oversee">
|
10
|
+
<img alt="Oversee GEM Version" src="https://img.shields.io/gem/dt/oversee?color=10b981&include_prereleases&logo=ruby&logoColor=f43f5e">
|
11
|
+
</a>
|
8
12
|
|
9
13
|
---
|
10
14
|
|
@@ -35,6 +39,7 @@ $ bundle add oversee
|
|
35
39
|
|
36
40
|
> [!TIP]
|
37
41
|
> Currently, we don't release new gem versions too often due to the fragile nature of the gem. However, you can use the edge version of the gem by pointing directly to the git repository.
|
42
|
+
>
|
38
43
|
> ```ruby
|
39
44
|
> gem "oversee", git: "https://github.com/primevise/oversee", branch: :main
|
40
45
|
> ```
|
@@ -0,0 +1,58 @@
|
|
1
|
+
class Oversee::Dashboard::Actions < Oversee::Base
|
2
|
+
def initialize(params: nil)
|
3
|
+
@params = params
|
4
|
+
end
|
5
|
+
|
6
|
+
def view_template(&)
|
7
|
+
div(class: "flex items-center justify-between") do
|
8
|
+
div(class: "flex items-center gap-2") do
|
9
|
+
if show_action_section?
|
10
|
+
button(
|
11
|
+
class:"rounded-full bg-gray-100 inline-flex gap-2 items-center text-xs px-4 py-2 font-medium hover:bg-gray-200",
|
12
|
+
data: { controller: "reveal", action: "reveal#toggle", reveal_revealable_id_value: "oversee-filters" }
|
13
|
+
) do
|
14
|
+
render Phlex::Icons::Iconoir::FilterAlt.new(class: "size-3")
|
15
|
+
plain "Filters"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
if false
|
19
|
+
a(class:"rounded-full bg-gray-100 inline-flex gap-2 items-center text-xs px-4 py-2 font-medium hover:bg-gray-200") do
|
20
|
+
render Phlex::Icons::Iconoir::XMark.new(class: "size-4 text-gray-500")
|
21
|
+
plain "Clear sorting"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
div(class: "flex items-center gap-4") do
|
26
|
+
form(action: "", class: "flex items-center gap-2") do
|
27
|
+
input(
|
28
|
+
type: :search,
|
29
|
+
name: :query,
|
30
|
+
value: @params[:query],
|
31
|
+
placeholder: search_placeholder,
|
32
|
+
class: "flex bg-gray-100 min-w-64 w-64 focus:w-96 transition-all h-10 items-center pl-4 py-2 placeholder:text-gray-500 rounded-sm text-sm"
|
33
|
+
)
|
34
|
+
button(class: "size-10 inline-flex items-center justify-center bg-gray-100 hover:bg-gray-200 transition-colors") { render Phlex::Icons::Iconoir::Search.new(class: "size-4 text-gray-600") }
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
render Oversee::Dashboard::Filters.new if show_action_section?
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def show_action_section?
|
44
|
+
Rails.env.development? || @params[:experimental] == "true"
|
45
|
+
end
|
46
|
+
|
47
|
+
def sortless_path
|
48
|
+
sortless_query_params = @params.except(:sort_attribute, :sort_direction, :controller, :action)
|
49
|
+
# helpers.resources_path(sortless_query_params)
|
50
|
+
end
|
51
|
+
|
52
|
+
def search_placeholder
|
53
|
+
context = Oversee::Search.new(collection: nil, resource_class: @params[:resource_class_name].constantize)
|
54
|
+
attr = context.default_searchable_attribute
|
55
|
+
|
56
|
+
"Search by #{attr}"
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
class Oversee::Dashboard::Filter < Oversee::Base
|
3
|
+
def view_template
|
4
|
+
div(class: "flex items-center gap-2") do
|
5
|
+
render Phlex::Icons::Iconoir::LongArrowDownRight.new(class: "size-4 text-gray-500")
|
6
|
+
form(action: "", class: "flex items-center gap-2") do
|
7
|
+
input(type: :text, placeholder: "Title [EQ]", name: "filters[title][eq][]", class: "bg-gray-100 px-4 py-2 text-xs")
|
8
|
+
button(type: :submit, class: "button", class: "bg-gray-900 text-white px-4 py-2 text-xs font-medium") { plain "Apply" }
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -1,54 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
class Oversee::Dashboard::Filters < Oversee::Base
|
2
|
-
def
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
puts "params: #{params}"
|
7
|
-
puts "sortless_path: #{sortless_path}"
|
8
|
-
end
|
9
|
-
|
10
|
-
def view_template(&)
|
11
|
-
div(class: "border-b p-4") do
|
12
|
-
div(class: "flex items-center justify-between") do
|
13
|
-
div(class: "flex items-center gap-2") do
|
14
|
-
if show_action_section?
|
15
|
-
button(class:"rounded-full bg-gray-100 inline-flex gap-2 items-center text-xs px-4 py-2 font-medium hover:bg-gray-200") do
|
16
|
-
render Phlex::Icons::Iconoir::FilterAlt.new(class: "size-3")
|
17
|
-
plain "Filters"
|
18
|
-
end
|
19
|
-
end
|
20
|
-
if false
|
21
|
-
a(class:"rounded-full bg-gray-100 inline-flex gap-2 items-center text-xs px-4 py-2 font-medium hover:bg-gray-200") do
|
22
|
-
render Phlex::Icons::Iconoir::XMark.new(class: "size-4 text-gray-500")
|
23
|
-
plain "Clear sorting"
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
div(class: "flex items-center gap-4") do
|
28
|
-
form(action: "", class: "flex items-center gap-2") do
|
29
|
-
input(type: :search, name: :query, class: "flex bg-gray-100 min-w-80 h-10 items-center pl-4 py-2 placeholder:text-gray-500 rounded-sm text-sm", placeholder: search_placeholder, value: @params[:query])
|
30
|
-
button(class: "size-10 inline-flex items-center justify-center bg-gray-100 hover:bg-gray-200 transition-colors") { render Phlex::Icons::Iconoir::Search.new(class: "size-4 text-gray-600") }
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
3
|
+
def view_template
|
4
|
+
div(id: :oversee_filters, class: "hidden pt-4 mt-4 border-t flex flex-col gap-2") do
|
5
|
+
render Oversee::Dashboard::Filter.new
|
34
6
|
end
|
35
7
|
end
|
36
|
-
|
37
|
-
private
|
38
|
-
|
39
|
-
def show_action_section?
|
40
|
-
Rails.env.development? || @params[:experimental] == "true"
|
41
|
-
end
|
42
|
-
|
43
|
-
def sortless_path
|
44
|
-
sortless_query_params = @params.except(:sort_attribute, :sort_direction, :controller, :action)
|
45
|
-
# helpers.resources_path(sortless_query_params)
|
46
|
-
end
|
47
|
-
|
48
|
-
def search_placeholder
|
49
|
-
context = Search.new(collection: nil, resource_class: @params[:resource_class_name].constantize)
|
50
|
-
attr = context.default_searchable_attribute
|
51
|
-
|
52
|
-
"Search by #{attr}"
|
53
|
-
end
|
54
|
-
end
|
8
|
+
end
|
@@ -1,4 +1,9 @@
|
|
1
1
|
class Oversee::Dashboard::Header < Oversee::Base
|
2
|
+
attr_reader :title
|
3
|
+
attr_reader :subtitle
|
4
|
+
attr_reader :return_path
|
5
|
+
attr_reader :show_back_button
|
6
|
+
|
2
7
|
def initialize(title: nil, subtitle: nil, return_path: nil, show_back_button: true)
|
3
8
|
@title = title || "Dashboard"
|
4
9
|
@subtitle = subtitle || "Manage your account"
|
@@ -7,31 +12,42 @@ class Oversee::Dashboard::Header < Oversee::Base
|
|
7
12
|
end
|
8
13
|
|
9
14
|
def view_template(&)
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
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
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
)
|
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: "
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
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
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
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://
|
4
|
-
|
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:"
|
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
|
-
|
52
|
+
|
53
|
+
details(
|
54
|
+
id: "resources-menu",
|
55
|
+
class: "group",
|
56
|
+
# open: true,
|
57
|
+
data: {
|
58
|
+
controller: "sidebar--state",
|
59
|
+
action: "sidebar--state#persist",
|
60
|
+
sidebar__state_target: "expandable"
|
61
|
+
}
|
62
|
+
) do
|
26
63
|
summary(class: "flex items-center justify-between cursor-pointer") do
|
27
64
|
p(class: "text-[0.7rem] uppercase text-gray-400 font-medium") { "Resources" }
|
28
65
|
render Phlex::Icons::Iconoir::NavArrowDown.new(class: "size-4 text-gray-400 transform transition-transform group-open:rotate-180 group-hover:text-blue-500")
|
@@ -1,11 +1,40 @@
|
|
1
1
|
class Oversee::Dashboard::Tailwind < Phlex::HTML
|
2
2
|
def view_template
|
3
|
-
script(src: "https://cdn.tailwindcss.com?plugins=typography")
|
3
|
+
script(src: "https://cdn.tailwindcss.com/3.4.15?plugins=typography@0.5.15")
|
4
4
|
style(type:"text/tailwindcss") do
|
5
5
|
raw pagy_css.html_safe
|
6
|
+
raw trix_css.html_safe
|
6
7
|
end
|
7
8
|
end
|
8
9
|
|
10
|
+
def trix_css
|
11
|
+
<<~CSS
|
12
|
+
trix-editor {
|
13
|
+
@apply rounded-b rounded-t-none border border-t-0 border-gray-200 !ring-0;
|
14
|
+
}
|
15
|
+
|
16
|
+
.trix-active {
|
17
|
+
@apply !bg-gray-100 !text-blue-500;
|
18
|
+
}
|
19
|
+
|
20
|
+
.trix-button-row {
|
21
|
+
@apply overflow-hidden rounded-t border;
|
22
|
+
}
|
23
|
+
|
24
|
+
.trix-button {
|
25
|
+
@apply !relative !inline-flex !h-7 !items-center !justify-center border-0 !border-b-0 !border-l-0 !px-7 !py-4;
|
26
|
+
}
|
27
|
+
|
28
|
+
.trix-button::before {
|
29
|
+
@apply !top-1.5 !h-5;
|
30
|
+
}
|
31
|
+
|
32
|
+
.trix-button-group {
|
33
|
+
@apply !mb-0 rounded-b-none !border-0 border-gray-200;
|
34
|
+
}
|
35
|
+
CSS
|
36
|
+
end
|
37
|
+
|
9
38
|
def pagy_css
|
10
39
|
<<~CSS
|
11
40
|
.pagy {
|
@@ -1,29 +1,20 @@
|
|
1
|
-
class Oversee::Field::Display < Oversee::
|
2
|
-
def initialize(resource:, key: nil, value: nil, datatype: :string, interactive: true)
|
3
|
-
@resource = resource
|
4
|
-
@key = key
|
5
|
-
@value = value
|
6
|
-
@datatype = datatype
|
7
|
-
@interactive = interactive
|
8
|
-
end
|
9
|
-
|
1
|
+
class Oversee::Field::Display < Oversee::Field
|
10
2
|
def view_template
|
11
|
-
|
12
|
-
id: dom_id(
|
13
|
-
href: helpers.
|
14
|
-
|
15
|
-
|
16
|
-
|
3
|
+
html_tag(
|
4
|
+
id: dom_id(resource, key),
|
5
|
+
href: helpers.resource_input_path(resource_class_name:, key:, datatype:),
|
6
|
+
title: key.to_s.titleize,
|
7
|
+
class: "bg-gray-100 h-10 flex items-center justify-between px-4 py-2 hover:bg-gray-200 transition-colors w-full cursor-pointer group",
|
8
|
+
data: { turbo_stream: true }
|
9
|
+
) do
|
10
|
+
render Oversee::Field::Value.new(key:, value:, datatype:, **@options)
|
11
|
+
render Phlex::Icons::Iconoir::Edit.new(class: "text-gray-500 size-4 opacity-0 group-hover:opacity-100 transition-opacity", stroke_width: 1.75)
|
17
12
|
end
|
18
13
|
end
|
19
14
|
|
20
15
|
private
|
21
16
|
|
22
|
-
def
|
23
|
-
@resource.class.name
|
24
|
-
end
|
17
|
+
def edittable? = @options[:edittable] || true
|
25
18
|
|
26
|
-
def
|
27
|
-
@interactive ? a(...) : div(...)
|
28
|
-
end
|
19
|
+
def html_tag(...) = edittable? ? a(...) : div(...)
|
29
20
|
end
|
@@ -1,49 +1,17 @@
|
|
1
|
-
class Oversee::Field::Form < Oversee::
|
1
|
+
class Oversee::Field::Form < Oversee::Field
|
2
2
|
include Phlex::Rails::Helpers::FormWith
|
3
3
|
|
4
|
-
def initialize(resource:, key: nil, value: nil, datatype: :string, method: :patch)
|
5
|
-
@resource = resource
|
6
|
-
@key = key
|
7
|
-
@value = value
|
8
|
-
@datatype = datatype
|
9
|
-
@method = method
|
10
|
-
end
|
11
|
-
|
12
4
|
def view_template
|
13
|
-
form_with(id:
|
5
|
+
form_with(id: field_form_id, model: resource, url: helpers.update_resource_path(resource_class_name: resource_class_name, id: @resource.id), method: @method, class: "flex items-center w-full gap-4") do |form|
|
14
6
|
input type: :hidden, id: "oversee_key", name: "oversee_key", value: @key.to_s
|
15
7
|
input type: :hidden, id: "oversee_datatype", name: "oversee_datatype", value: @datatype
|
16
|
-
render Oversee::Field::Input.new(key: @key, value: @value, datatype: @datatype)
|
17
|
-
button(class:"h-9 bg-gray-900 hover:bg-gray-700 text-white inline-flex items-center cursor-pointer gap-2 px-4 rounded-full text-xs font-medium") {
|
18
|
-
save_icon
|
19
|
-
plain "Save"
|
20
|
-
}
|
8
|
+
render Oversee::Field::Input.new(key: @key, value: @value, datatype: @datatype, **@options)
|
21
9
|
end
|
22
10
|
end
|
23
11
|
|
24
12
|
private
|
25
13
|
|
26
|
-
def
|
27
|
-
@
|
28
|
-
end
|
29
|
-
|
30
|
-
def save_icon
|
31
|
-
svg(
|
32
|
-
stroke_width: "2.5",
|
33
|
-
viewbox: "0 0 24 24",
|
34
|
-
fill: "none",
|
35
|
-
xmlns: "http://www.w3.org/2000/svg",
|
36
|
-
class: "size-4",
|
37
|
-
color: "currentColor"
|
38
|
-
) do |s|
|
39
|
-
s.path(
|
40
|
-
d: "M5 13L9 17L19 7",
|
41
|
-
stroke: "currentColor",
|
42
|
-
stroke_width: "2.5",
|
43
|
-
stroke_linecap: "round",
|
44
|
-
stroke_linejoin: "round"
|
45
|
-
)
|
46
|
-
end
|
14
|
+
def method
|
15
|
+
@method ||= @options[:method] || :patch
|
47
16
|
end
|
48
|
-
|
49
17
|
end
|
@@ -1,23 +1,8 @@
|
|
1
|
-
class Oversee::Field::Input::Boolean <
|
2
|
-
def initialize(key:, value:)
|
3
|
-
@key = key
|
4
|
-
@value = value
|
5
|
-
end
|
6
|
-
|
1
|
+
class Oversee::Field::Input::Boolean < Oversee::Field::Input
|
7
2
|
def view_template
|
8
3
|
select(id: field_id, name: field_name, class: "flex w-full border rounded-sm px-4 py-2 text-sm") do
|
9
|
-
option(value: 1, selected:
|
10
|
-
option(value: 0, selected:
|
4
|
+
option(value: 1, selected: value) { "True" }
|
5
|
+
option(value: 0, selected: !value) { "False" }
|
11
6
|
end
|
12
7
|
end
|
13
|
-
|
14
|
-
private
|
15
|
-
|
16
|
-
def field_id
|
17
|
-
"resource_#{@key.to_s}"
|
18
|
-
end
|
19
|
-
|
20
|
-
def field_name
|
21
|
-
"resource[#{@key.to_s}]"
|
22
|
-
end
|
23
8
|
end
|
@@ -1,20 +1,5 @@
|
|
1
|
-
class Oversee::Field::Input::Datetime <
|
2
|
-
def initialize(key:, value:)
|
3
|
-
@key = key
|
4
|
-
@value = value
|
5
|
-
end
|
6
|
-
|
1
|
+
class Oversee::Field::Input::Datetime < Oversee::Field::Input
|
7
2
|
def view_template
|
8
|
-
input
|
9
|
-
end
|
10
|
-
|
11
|
-
private
|
12
|
-
|
13
|
-
def field_id
|
14
|
-
"resource_#{@key.to_s}"
|
15
|
-
end
|
16
|
-
|
17
|
-
def field_name
|
18
|
-
"resource[#{@key.to_s}]"
|
3
|
+
input(type: "datetime-local", id: field_id, name: field_name, value: value&.strftime("%Y-%m-%dT%T"), class: "flex w-full border rounded-sm px-4 py-2 text-sm")
|
19
4
|
end
|
20
5
|
end
|
@@ -1,20 +1,5 @@
|
|
1
|
-
class Oversee::Field::Input::Integer <
|
2
|
-
def initialize(key:, value:)
|
3
|
-
@key = key
|
4
|
-
@value = value
|
5
|
-
end
|
6
|
-
|
1
|
+
class Oversee::Field::Input::Integer < Oversee::Field::Input
|
7
2
|
def view_template
|
8
|
-
input
|
9
|
-
end
|
10
|
-
|
11
|
-
private
|
12
|
-
|
13
|
-
def field_id
|
14
|
-
"resource_#{@key.to_s}"
|
15
|
-
end
|
16
|
-
|
17
|
-
def field_name
|
18
|
-
"resource[#{@key.to_s}]"
|
3
|
+
input(type: "number", id: field_id, name: field_name, value:, class: "flex w-full border rounded-sm px-4 py-2 text-sm")
|
19
4
|
end
|
20
5
|
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
class Oversee::Field::Input::RichText < Oversee::Field::Input
|
2
|
+
register_element :trix_editor
|
3
|
+
|
4
|
+
def view_template
|
5
|
+
div do
|
6
|
+
input(type: "hidden", id: field_id, name: field_name, value:)
|
7
|
+
trix_editor(id: "#{field_id}_trix_editor", input: field_id)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
@@ -1,20 +1,5 @@
|
|
1
|
-
class Oversee::Field::Input::String <
|
2
|
-
def initialize(key:, value:)
|
3
|
-
@key = key
|
4
|
-
@value = value
|
5
|
-
end
|
6
|
-
|
1
|
+
class Oversee::Field::Input::String < Oversee::Field::Input
|
7
2
|
def view_template
|
8
|
-
input
|
9
|
-
end
|
10
|
-
|
11
|
-
private
|
12
|
-
|
13
|
-
def field_id
|
14
|
-
"resource_#{@key.to_s}"
|
15
|
-
end
|
16
|
-
|
17
|
-
def field_name
|
18
|
-
"resource[#{@key.to_s}]"
|
3
|
+
input(type: "text", id: field_id, name: field_name, value:, class: "flex border px-4 py-2 text-sm w-full rounded-sm")
|
19
4
|
end
|
20
5
|
end
|