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
@@ -1,21 +1,20 @@
|
|
1
|
-
class Oversee::Field::Input < Oversee::
|
1
|
+
class Oversee::Field::Input < Oversee::Field
|
2
2
|
MAP = {
|
3
|
-
|
3
|
+
belongs_to: Oversee::Field::Input::BelongsTo,
|
4
4
|
boolean: Oversee::Field::Input::Boolean,
|
5
|
-
|
5
|
+
date: Oversee::Field::Input::Date,
|
6
6
|
datetime: Oversee::Field::Input::Datetime,
|
7
|
+
enum: Oversee::Field::Input::String,
|
8
|
+
integer: Oversee::Field::Input::Integer,
|
9
|
+
json: Oversee::Field::Input::Json,
|
10
|
+
jsonb: Oversee::Field::Input::Json,
|
11
|
+
rich_text: Oversee::Field::Input::RichText,
|
12
|
+
string: Oversee::Field::Input::String,
|
7
13
|
text: Oversee::Field::Input::String,
|
8
|
-
enum: Oversee::Field::Input::String
|
9
14
|
}
|
10
15
|
|
11
|
-
def initialize(key: nil, value: nil, datatype: :string)
|
12
|
-
@key = key
|
13
|
-
@value = value
|
14
|
-
@datatype = datatype
|
15
|
-
end
|
16
|
-
|
17
16
|
def view_template
|
18
|
-
render component_class.new(key
|
17
|
+
render component_class.new(key:, value:, **@options)
|
19
18
|
end
|
20
19
|
|
21
20
|
private
|
@@ -23,4 +22,7 @@ class Oversee::Field::Input < Oversee::Base
|
|
23
22
|
def component_class
|
24
23
|
MAP[@datatype.to_sym] || Oversee::Field::Input::String
|
25
24
|
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
26
28
|
end
|
@@ -1,24 +1,25 @@
|
|
1
|
-
class Oversee::Field::Label < Oversee::
|
1
|
+
class Oversee::Field::Label < Oversee::Field
|
2
2
|
ICON_MAP = {
|
3
|
-
string: Phlex::Icons::Iconoir::Text,
|
4
|
-
text: Phlex::Icons::Iconoir::TextSquare,
|
5
|
-
integer: Phlex::Icons::Iconoir::Number0Square,
|
6
|
-
datetime: Phlex::Icons::Iconoir::Calendar,
|
7
3
|
boolean: Phlex::Icons::Iconoir::SwitchOn,
|
8
4
|
data: Phlex::Icons::Iconoir::Page,
|
5
|
+
date: Phlex::Icons::Iconoir::Calendar,
|
6
|
+
datetime: Phlex::Icons::Iconoir::Calendar,
|
7
|
+
integer: Phlex::Icons::Iconoir::Number0Square,
|
8
|
+
json: Phlex::Icons::Iconoir::CodeBracketsSquare,
|
9
|
+
jsonb: Phlex::Icons::Iconoir::CodeBracketsSquare,
|
10
|
+
rich_text: Phlex::Icons::Iconoir::TextSquare,
|
11
|
+
string: Phlex::Icons::Iconoir::Text,
|
12
|
+
text: Phlex::Icons::Iconoir::TextSquare,
|
9
13
|
}
|
10
14
|
|
11
|
-
def initialize(datatype: :string, key: nil)
|
12
|
-
@datatype = datatype
|
13
|
-
@key = key
|
14
|
-
end
|
15
|
-
|
16
15
|
def view_template
|
17
|
-
div(class:"inline-flex items-center space-x-2") do
|
18
|
-
div(class: "size-5 bg-gray-100 inline-flex items-center justify-center")
|
19
|
-
|
20
|
-
end
|
21
|
-
label(class: "uppercase text-xs text-gray-š00 font-medium block") { @key.to_s.humanize(keep_id_suffix: true) }
|
16
|
+
div(id: "#{key}_label", class:"inline-flex items-center space-x-2") do
|
17
|
+
div(class: "size-5 bg-gray-100 inline-flex items-center justify-center") { render icon.new(class: "size-3") }
|
18
|
+
label(class: "uppercase text-xs text-gray-700 font-medium block cursor-auto", for: key) { key.to_s.humanize(keep_id_suffix: true) }
|
22
19
|
end
|
23
20
|
end
|
21
|
+
|
22
|
+
def icon
|
23
|
+
ICON_MAP[datatype&.to_sym] || ICON_MAP[:data]
|
24
|
+
end
|
24
25
|
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Oversee::Field::Set < Oversee::Field
|
4
|
+
def view_template
|
5
|
+
div(id: dom_id(resource, key), class:"flex flex-col gap-2") do
|
6
|
+
div(class:"flex items-center justify-between h-10 gap-4") do
|
7
|
+
render Oversee::Field::Label.new(key:, datatype:)
|
8
|
+
button(type: :submit, class: "bg-black text-white text-xs font-medium px-6 py-2 hover:opacity-75 transition-opacity", form: field_form_id) { "Save" } if state == :input
|
9
|
+
end
|
10
|
+
div(class: "flex items-center justify-between gap-2") { send("#{state}_state") }
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def value_state
|
15
|
+
render Oversee::Field::Display.new(resource:, key:, value:, datatype:, **@options)
|
16
|
+
div(id: dom_id(@resource, :"#{key}_actions")) do
|
17
|
+
button(
|
18
|
+
class: "bg-gray-100 hover:bg-gray-200 text-gray-400 hover:text-blue-500 size-10 aspect-square inline-flex items-center justify-center transition-colors",
|
19
|
+
data: { controller: "clipboard", action: "click->clipboard#copy", clipboard_content_value: value.to_s }
|
20
|
+
) do
|
21
|
+
span(class: "hidden", data: { clipboard_target: "successIcon"}) { render Phlex::Icons::Iconoir::Check.new(class: "size-4 text-emerald-500", stroke_width: 1.75) }
|
22
|
+
span(data: { clipboard_target: "copyIcon"}) { render Phlex::Icons::Iconoir::Copy.new(class: "size-4", stroke_width: 1.75) }
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def input_state
|
28
|
+
render Oversee::Field::Form.new(resource: @resource, datatype:, key:, value:)
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def state
|
34
|
+
@state ||= @options[:state] || :value
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class Oversee::Field::Value::BelongsTo < Oversee::Field::Value
|
2
|
+
def view_template
|
3
|
+
p(title: value, class:"inline-flex items-center gap-1") do
|
4
|
+
if display_key?
|
5
|
+
span { key.humanize }
|
6
|
+
span {"|"}
|
7
|
+
end
|
8
|
+
span { value }
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def display_key? = !!@options[:display_key]
|
15
|
+
end
|
@@ -1,50 +1,5 @@
|
|
1
|
-
class Oversee::Field::Value::Boolean <
|
2
|
-
def initialize(key: nil, value: nil, kind: :value)
|
3
|
-
@value = value
|
4
|
-
end
|
5
|
-
|
1
|
+
class Oversee::Field::Value::Boolean < Oversee::Field::Value
|
6
2
|
def view_template
|
7
|
-
|
8
|
-
end
|
9
|
-
|
10
|
-
private
|
11
|
-
|
12
|
-
def check_icon
|
13
|
-
svg(
|
14
|
-
stroke_width: "2",
|
15
|
-
viewbox: "0 0 24 24",
|
16
|
-
fill: "none",
|
17
|
-
xmlns: "http://www.w3.org/2000/svg",
|
18
|
-
color: "currentColor",
|
19
|
-
class: "size-4 text-emerald-500"
|
20
|
-
) do |s|
|
21
|
-
s.path(
|
22
|
-
d: "M5 13L9 17L19 7",
|
23
|
-
stroke: "currentColor",
|
24
|
-
stroke_width: "2",
|
25
|
-
stroke_linecap: "round",
|
26
|
-
stroke_linejoin: "round"
|
27
|
-
)
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
def x_icon
|
32
|
-
svg(
|
33
|
-
stroke_width: "1.5",
|
34
|
-
viewbox: "0 0 24 24",
|
35
|
-
fill: "none",
|
36
|
-
xmlns: "http://www.w3.org/2000/svg",
|
37
|
-
color: "currentColor",
|
38
|
-
class: "size-4 text-rose-500"
|
39
|
-
) do |s|
|
40
|
-
s.path(
|
41
|
-
d:
|
42
|
-
"M6.75827 17.2426L12.0009 12M17.2435 6.75736L12.0009 12M12.0009 12L6.75827 6.75736M12.0009 12L17.2435 17.2426",
|
43
|
-
stroke: "currentColor",
|
44
|
-
stroke_width: "1.5",
|
45
|
-
stroke_linecap: "round",
|
46
|
-
stroke_linejoin: "round"
|
47
|
-
)
|
48
|
-
end
|
3
|
+
render value ? Phlex::Icons::Iconoir::Check.new(class: "size-4 text-emerald-500") : Phlex::Icons::Iconoir::Xmark.new(class: "size-4 text-rose-500")
|
49
4
|
end
|
50
5
|
end
|
@@ -1,9 +1,5 @@
|
|
1
|
-
class Oversee::Field::Value::Datetime <
|
2
|
-
def initialize(key: nil, value: nil, kind: :value)
|
3
|
-
@value = value
|
4
|
-
end
|
5
|
-
|
1
|
+
class Oversee::Field::Value::Datetime < Oversee::Field::Value
|
6
2
|
def view_template
|
7
|
-
time(title:
|
3
|
+
time(title: value.to_s) { value&.to_fs(:long) || "N/A" }
|
8
4
|
end
|
9
5
|
end
|
@@ -1,9 +1,5 @@
|
|
1
|
-
class Oversee::Field::Value::Enum <
|
2
|
-
def initialize(key: nil, value: nil, kind: :value)
|
3
|
-
@value = value
|
4
|
-
end
|
5
|
-
|
1
|
+
class Oversee::Field::Value::Enum < Oversee::Field::Value
|
6
2
|
def view_template
|
7
|
-
p(class:"inline-flex px-2 py-1 text-red-500") {
|
3
|
+
p(class:"inline-flex px-2 py-1 text-red-500") { value.to_s }
|
8
4
|
end
|
9
5
|
end
|
@@ -1,20 +1,13 @@
|
|
1
|
-
class Oversee::Field::Value::String <
|
2
|
-
def initialize(key: nil, value: nil, kind: :value)
|
3
|
-
@key = key
|
4
|
-
@value = value
|
5
|
-
@kind = kind
|
6
|
-
end
|
7
|
-
|
1
|
+
class Oversee::Field::Value::String < Oversee::Field::Value
|
8
2
|
def view_template
|
9
3
|
return p(class: "text-gray-400 text-xs uppercase") { "Empty" } if @value == ""
|
10
4
|
return p(class: "text-gray-400 text-xs uppercase") { "Redacted" } if sensitive?
|
11
|
-
|
12
|
-
p(class: "truncate") { @value }
|
5
|
+
p(class: "truncate") { value }
|
13
6
|
end
|
14
7
|
|
15
8
|
private
|
16
9
|
|
17
10
|
def sensitive?
|
18
|
-
|
11
|
+
key&.downcase&.include?("password") || key&.downcase&.include?("token")
|
19
12
|
end
|
20
13
|
end
|
@@ -1,9 +1,5 @@
|
|
1
|
-
class Oversee::Field::Value::Text <
|
2
|
-
def initialize(datatype: :string, key: nil, value: nil, kind: :value)
|
3
|
-
@value = value
|
4
|
-
end
|
5
|
-
|
1
|
+
class Oversee::Field::Value::Text < Oversee::Field::Value
|
6
2
|
def view_template
|
7
|
-
p(class: "truncate") {
|
3
|
+
p(class: "truncate") { value }
|
8
4
|
end
|
9
5
|
end
|
@@ -1,13 +1,22 @@
|
|
1
1
|
class Oversee::Field::Value < Oversee::Base
|
2
2
|
MAP = {
|
3
3
|
string: Oversee::Field::Value::String,
|
4
|
+
belongs_to: Oversee::Field::Value::BelongsTo,
|
4
5
|
boolean: Oversee::Field::Value::Boolean,
|
5
|
-
|
6
|
+
date: Oversee::Field::Value::Date,
|
6
7
|
datetime: Oversee::Field::Value::Datetime,
|
8
|
+
enum: Oversee::Field::Value::Enum,
|
9
|
+
integer: Oversee::Field::Value::Integer,
|
10
|
+
json: Oversee::Field::Value::Json,
|
11
|
+
jsonb: Oversee::Field::Value::Json,
|
12
|
+
rich_text: Oversee::Field::Value::RichText,
|
7
13
|
text: Oversee::Field::Value::Text,
|
8
|
-
enum: Oversee::Field::Value::Enum
|
9
14
|
}
|
10
15
|
|
16
|
+
attr_reader :key
|
17
|
+
attr_reader :value
|
18
|
+
attr_reader :datatype
|
19
|
+
|
11
20
|
def initialize(key: nil, value: nil, datatype: :string, **options)
|
12
21
|
@key = key
|
13
22
|
@value = value
|
@@ -18,14 +27,14 @@ class Oversee::Field::Value < Oversee::Base
|
|
18
27
|
end
|
19
28
|
|
20
29
|
def view_template
|
21
|
-
return p(class: "text-gray-400 text-xs"){ "—" } if
|
22
|
-
render component_class.new(key
|
30
|
+
return p(class: "text-gray-400 text-xs"){ "—" } if value.nil?
|
31
|
+
render component_class.new(key:, value:, **@options)
|
23
32
|
end
|
24
33
|
|
25
34
|
private
|
26
35
|
|
27
36
|
def component_class
|
28
|
-
MAP[
|
37
|
+
MAP[datatype.to_sym] || Oversee::Field::Value::String
|
29
38
|
end
|
30
39
|
|
31
40
|
def for_table?
|
@@ -0,0 +1,42 @@
|
|
1
|
+
class Oversee::Field < Oversee::Base
|
2
|
+
attr_reader :resource
|
3
|
+
attr_reader :key
|
4
|
+
attr_reader :value
|
5
|
+
attr_reader :datatype
|
6
|
+
|
7
|
+
def initialize(resource: nil, key: nil, value: nil, datatype: nil, **options)
|
8
|
+
@resource = resource
|
9
|
+
@key = key
|
10
|
+
@value = value
|
11
|
+
@datatype = datatype
|
12
|
+
@options = options
|
13
|
+
end
|
14
|
+
|
15
|
+
def view_template
|
16
|
+
plain "Oversee::Field"
|
17
|
+
end
|
18
|
+
|
19
|
+
# Sub-components
|
20
|
+
def __LABEL__ = Oversee::Field::Label.new(resource:, key:, value:, datatype:, **@options)
|
21
|
+
def __VALUE__ = Oversee::Field::Value.new(resource:, key:, value:, datatype:, **@options)
|
22
|
+
def __INPUT__ = Oversee::Field::Input.new(resource:, key:, value:, datatype:, **@options)
|
23
|
+
def __FORM__ = Oversee::Field::Form.new(resource:, key:, value:, datatype:, **@options)
|
24
|
+
def __SET__ = Oversee::Field::Set.new(resource:, key:, value:, datatype:, **@options)
|
25
|
+
|
26
|
+
# Helpers & Decorators
|
27
|
+
def field_id
|
28
|
+
@field_id ||= "resource_#{key}"
|
29
|
+
end
|
30
|
+
|
31
|
+
def field_name
|
32
|
+
@field_name ||= "resource[#{key}]"
|
33
|
+
end
|
34
|
+
|
35
|
+
def field_form_id
|
36
|
+
@form_id ||= dom_id(resource, "#{key}_form")
|
37
|
+
end
|
38
|
+
|
39
|
+
def resource_class_name
|
40
|
+
@resource_class_name ||= @resource.class.name
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Oversee::Flash < Phlex::HTML
|
4
|
+
include Phlex::Rails::Helpers::Flash
|
5
|
+
|
6
|
+
def view_template
|
7
|
+
div(id: :flash, class: "fixed bottom-0 right-0 mb-8 mr-8 w-80 z-50") do
|
8
|
+
if !flash.empty?
|
9
|
+
div(
|
10
|
+
class: "flex flex-col gap-2 p-4 bg-white border border-gray-200/75 border-b-2 rounded-lg transition-all opacity-0 transform duration-300",
|
11
|
+
data: { controller: :notification }
|
12
|
+
) do
|
13
|
+
notice if notice?
|
14
|
+
alert if alert?
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def notice?
|
23
|
+
flash[:notice].present?
|
24
|
+
end
|
25
|
+
|
26
|
+
def notice
|
27
|
+
render Phlex::Icons::Iconoir::CheckCircle.new(class: "size-5 text-emerald-500", stroke_width: 2)
|
28
|
+
p(class: "text-sm text-gray-700") { flash[:notice] }
|
29
|
+
end
|
30
|
+
|
31
|
+
def alert?
|
32
|
+
flash[:alert].present?
|
33
|
+
end
|
34
|
+
|
35
|
+
def alert
|
36
|
+
render Phlex::Icons::Iconoir::MessageAlert.new(class: "size-5 text-red-500", stroke_width: 2)
|
37
|
+
p(class: "text-sm text-gray-700") { flash[:alert] }
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Oversee::Layout::Application < Oversee::Base
|
4
|
+
extend Phlex::Kit
|
5
|
+
|
6
|
+
include Phlex::Rails::Helpers::CSPMetaTag
|
7
|
+
include Phlex::Rails::Helpers::CSRFMetaTags
|
8
|
+
include Phlex::Rails::Helpers::StylesheetLinkTag
|
9
|
+
include Phlex::Rails::Helpers::JavascriptImportmapTags
|
10
|
+
|
11
|
+
def view_template
|
12
|
+
doctype
|
13
|
+
html do
|
14
|
+
# render Head
|
15
|
+
head do
|
16
|
+
csrf_meta_tags
|
17
|
+
csp_meta_tag
|
18
|
+
|
19
|
+
title { "Oversee | #{Oversee.application_name}" }
|
20
|
+
|
21
|
+
meta(name: "viewport", content: "width=device-width, initial-scale=1.0")
|
22
|
+
meta(name: "ROBOTS", content: "NOODP")
|
23
|
+
|
24
|
+
link(rel: "stylesheet", type: "text/css", href: "https://unpkg.com/trix@2.1.8/dist/trix.css")
|
25
|
+
|
26
|
+
render Oversee::Dashboard::Javascript.new
|
27
|
+
render Oversee::Dashboard::Tailwind.new
|
28
|
+
end
|
29
|
+
|
30
|
+
body(class: "min-h-screen bg-gray-100 p-4") do
|
31
|
+
render Oversee::Flash.new
|
32
|
+
|
33
|
+
div(class: "flex gap-4 w-full") do
|
34
|
+
div(class: "w-72 shrink-0") { render Oversee::Dashboard::Sidebar.new }
|
35
|
+
div(class: "w-full overflow-scroll") do
|
36
|
+
div(class: "bg-white rounded-lg overflow-clip p-4") do
|
37
|
+
yield
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -9,12 +9,31 @@ class Oversee::Resources::Index < Oversee::Base
|
|
9
9
|
end
|
10
10
|
|
11
11
|
|
12
|
+
def around_template
|
13
|
+
render Oversee::Layout::Application.new { super }
|
14
|
+
end
|
15
|
+
|
12
16
|
def view_template
|
13
|
-
render Oversee::Dashboard::Header.new(title: @resource_class.to_s
|
14
|
-
|
17
|
+
render Oversee::Dashboard::Header.new(title: @resource_class.to_s.pluralize) do |h|
|
18
|
+
h.left
|
19
|
+
h.right do
|
20
|
+
a(
|
21
|
+
href: helpers.new_resource_path(@params[:resource_class_name]),
|
22
|
+
target: "_top",
|
23
|
+
class: "inline-flex items-center justify-center gap-1.5 h-8 px-4 rounded-full bg-transparent text-gray-900 hover:bg-gray-100 text-sm font-medium transition group"
|
24
|
+
) do
|
25
|
+
render Phlex::Icons::Iconoir::Plus.new(class: "size-4 text-gray-500 group-hover:text-blue-500", stroke_width: 2.5)
|
26
|
+
plain "Add new"
|
27
|
+
end
|
28
|
+
end
|
15
29
|
end
|
16
|
-
|
30
|
+
hr(class: "my-4")
|
31
|
+
|
32
|
+
render Oversee::Dashboard::Actions.new(params: @params)
|
33
|
+
|
34
|
+
hr(class: "mt-4")
|
17
35
|
render Oversee::Resources::Table.new(resource_class: @resource_class, resources: @resources, params: @params)
|
36
|
+
hr()
|
18
37
|
render Oversee::Dashboard::Pagination.new(pagy: @pagy, params: @params)
|
19
38
|
end
|
20
39
|
|
@@ -7,11 +7,15 @@ class Oversee::Resources::New < Oversee::Base
|
|
7
7
|
@params = params
|
8
8
|
end
|
9
9
|
|
10
|
+
def around_template
|
11
|
+
render Oversee::Layout::Application.new { super }
|
12
|
+
end
|
13
|
+
|
10
14
|
def view_template
|
11
15
|
render Oversee::Dashboard::Header.new(title: @resource_class.to_s, subtitle: "Creating new record")
|
12
16
|
|
13
|
-
|
14
|
-
|
15
|
-
|
17
|
+
hr(class: "my-4")
|
18
|
+
|
19
|
+
render Oversee::Resources::Form.new(resource: @resource)
|
16
20
|
end
|
17
21
|
end
|