plok 0.2.12 → 1.0.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/app/assets/javascripts/plok/sidebar.js +66 -0
- data/app/assets/stylesheets/plok/_sidebar.scss +86 -0
- data/app/assets/stylesheets/plok/_sidebar_compact.scss +66 -0
- data/config/initializers/module.rb +23 -0
- data/lib/generators/plok/sidebar/USAGE +8 -0
- data/lib/generators/plok/sidebar/sidebar_generator.rb +114 -0
- data/lib/generators/plok/sidebar/templates/_menu_item.html.erb +16 -0
- data/lib/generators/plok/sidebar/templates/_menu_items.html.erb +9 -0
- data/lib/generators/plok/sidebar/templates/_offcanvas_menu.html.erb +11 -0
- data/lib/generators/plok/sidebar/templates/_wrapper.html.erb +19 -0
- data/lib/plok/engine.rb +3 -0
- data/lib/plok/version.rb +1 -1
- metadata +13 -4
- data/config/plok.yml +0 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8824645af9b5b16c2e3540eb298a43be8df6b0e1539d2274bf833d62a4ee2c9b
|
4
|
+
data.tar.gz: 53298ba35f0393728429121aeb7ace1ebafca3b744bb3f47e584478eea6ae6e3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 54f0aec7e6af22ec5f1e9d988880ebf03e110a5c8f619169c1ad1a5a82188c11f9da0b28a71189cd9aac21824921223e035cc718d0c2de7e661812cc715d7576
|
7
|
+
data.tar.gz: 4a274b94c88692dadd40061cd90778a7c0c2d7c5d931ef0c123e2b1a6e13ead58331f60e26d3c8c14fdeb709a414b7d93d44be072e3b4b85b74710c8a2f959cd
|
@@ -0,0 +1,66 @@
|
|
1
|
+
var sidebar = {
|
2
|
+
init: () => {
|
3
|
+
sidebar.bind_mouse_events();
|
4
|
+
$('#hamburger').on('click', sidebar.toggle_hamburger_click_listener)
|
5
|
+
$(document).on('click', sidebar.document_click_listener)
|
6
|
+
},
|
7
|
+
|
8
|
+
bind_mouse_events: () => {
|
9
|
+
$('.wrapper.compact ul li.top-level')
|
10
|
+
.on('mouseenter', sidebar.list_item_mouseenter_listener)
|
11
|
+
.on('mouseleave', sidebar.list_item_mouseleave_listener)
|
12
|
+
},
|
13
|
+
|
14
|
+
close_all_submenus: () => {
|
15
|
+
$('[id^="nav-"]').each((_i, item) => { $(item).removeClass('show') })
|
16
|
+
$('a.top-level-anchor').each((_i, item) => { $(item).removeClass('bg-secondary') })
|
17
|
+
},
|
18
|
+
|
19
|
+
document_click_listener: (e) => {
|
20
|
+
if($('.compact:visible').length == 0) return
|
21
|
+
if($(e.target).closest('.sidebar-menu').length === 0)
|
22
|
+
sidebar.close_all_submenus();
|
23
|
+
},
|
24
|
+
|
25
|
+
list_item_mouseenter_listener: (e) => {
|
26
|
+
sidebar.list_item_mouseleave_listener(e)
|
27
|
+
|
28
|
+
let anchor = $(e.target)
|
29
|
+
if(!anchor.hasClass('top-level-anchor')) return
|
30
|
+
anchor.addClass('bg-secondary')
|
31
|
+
$(anchor.attr('href')).addClass('show')
|
32
|
+
},
|
33
|
+
|
34
|
+
list_item_mouseleave_listener: (e) => {
|
35
|
+
let anchor = $(e.target)
|
36
|
+
if(!anchor.hasClass('top-level-anchor')) return
|
37
|
+
sidebar.close_all_submenus();
|
38
|
+
},
|
39
|
+
|
40
|
+
toggle_hamburger_click_listener: e => {
|
41
|
+
e.preventDefault()
|
42
|
+
$('.wrapper').toggleClass('compact')
|
43
|
+
|
44
|
+
$('[id^="nav-"]').each((index, item) => {
|
45
|
+
if($('.wrapper').hasClass('compact')) {
|
46
|
+
$(item).removeClass('show')
|
47
|
+
}
|
48
|
+
})
|
49
|
+
|
50
|
+
if($('.wrapper').hasClass('compact')) {
|
51
|
+
sidebar.bind_mouse_events()
|
52
|
+
$('.sidebar-menu').removeClass('overflow-auto')
|
53
|
+
} else {
|
54
|
+
sidebar.unbind_mouse_events()
|
55
|
+
$('.sidebar-menu').addClass('overflow-auto')
|
56
|
+
}
|
57
|
+
},
|
58
|
+
|
59
|
+
unbind_mouse_events: () => {
|
60
|
+
$('.wrapper ul li.top-level')
|
61
|
+
.off('mouseenter')
|
62
|
+
.off('mouseleave')
|
63
|
+
}
|
64
|
+
}
|
65
|
+
|
66
|
+
$(() => { sidebar.init() })
|
@@ -0,0 +1,86 @@
|
|
1
|
+
.sidebar-menu {
|
2
|
+
bottom: 0;
|
3
|
+
position: fixed;
|
4
|
+
top: 0;
|
5
|
+
width: var(--sidebar-width);
|
6
|
+
transition: .5s;
|
7
|
+
z-index: 10;
|
8
|
+
|
9
|
+
a.logo {
|
10
|
+
display: block;
|
11
|
+
letter-spacing: 0.1em;
|
12
|
+
line-height: 45px;
|
13
|
+
text-decoration: none;
|
14
|
+
text-transform: uppercase;
|
15
|
+
}
|
16
|
+
|
17
|
+
a.home-icon {
|
18
|
+
display: none !important;
|
19
|
+
}
|
20
|
+
|
21
|
+
ul {
|
22
|
+
list-style-type: none;
|
23
|
+
padding-left: 0;
|
24
|
+
|
25
|
+
li {
|
26
|
+
cursor: pointer;
|
27
|
+
|
28
|
+
a {
|
29
|
+
color: #fff; // $color-contrast-light from the Bootstrap gem.
|
30
|
+
display: block;
|
31
|
+
font-size: 1rem;
|
32
|
+
padding: 10px;
|
33
|
+
padding-left: var(--sidebar-menu-item-left-margin);
|
34
|
+
text-decoration: none !important;
|
35
|
+
|
36
|
+
&:hover {
|
37
|
+
background-color: #6c757d; // $secondary from the Bootstrap gem.
|
38
|
+
}
|
39
|
+
}
|
40
|
+
|
41
|
+
&.top-level {
|
42
|
+
letter-spacing: .05em;
|
43
|
+
position: relative;
|
44
|
+
|
45
|
+
.fa {
|
46
|
+
font-size: 14px;
|
47
|
+
width: var(--sidebar-icon-width);
|
48
|
+
}
|
49
|
+
|
50
|
+
.text {
|
51
|
+
cursor: default;
|
52
|
+
font-size: 0.8rem;
|
53
|
+
padding: 16px 0 12px 0;
|
54
|
+
pointer-events: none;
|
55
|
+
text-transform: uppercase;
|
56
|
+
}
|
57
|
+
|
58
|
+
div[id^=nav-] {
|
59
|
+
h4 {
|
60
|
+
display: none;
|
61
|
+
}
|
62
|
+
|
63
|
+
ul li {
|
64
|
+
position: relative;
|
65
|
+
|
66
|
+
&::before {
|
67
|
+
content: '\25A1';
|
68
|
+
font-size: 0.4rem;
|
69
|
+
left: calc(var(--sidebar-menu-item-left-margin) + 15px);
|
70
|
+
position: absolute;
|
71
|
+
top: 15px;
|
72
|
+
}
|
73
|
+
|
74
|
+
a {
|
75
|
+
font-size: 0.8rem;
|
76
|
+
padding-left: calc(var(--sidebar-menu-item-left-margin) + var(--sidebar-icon-width) + 10px);
|
77
|
+
text-transform: uppercase;
|
78
|
+
}
|
79
|
+
}
|
80
|
+
}
|
81
|
+
|
82
|
+
}
|
83
|
+
}
|
84
|
+
}
|
85
|
+
|
86
|
+
}
|
@@ -0,0 +1,66 @@
|
|
1
|
+
.wrapper.compact {
|
2
|
+
.content {
|
3
|
+
margin-left: var(--sidebar-compact-width);
|
4
|
+
|
5
|
+
@include media-breakpoint-down(md) {
|
6
|
+
margin-left: 0;
|
7
|
+
}
|
8
|
+
}
|
9
|
+
|
10
|
+
.sidebar-menu {
|
11
|
+
width: var(--sidebar-compact-width);
|
12
|
+
|
13
|
+
@include media-breakpoint-down(md) {
|
14
|
+
width: 0;
|
15
|
+
}
|
16
|
+
|
17
|
+
a.logo {
|
18
|
+
display: none !important;
|
19
|
+
}
|
20
|
+
|
21
|
+
a.home-icon {
|
22
|
+
display: block !important;
|
23
|
+
}
|
24
|
+
|
25
|
+
ul li.top-level {
|
26
|
+
> a { // The icons in the compact view.
|
27
|
+
padding: 10px 0;
|
28
|
+
text-align: center;
|
29
|
+
}
|
30
|
+
|
31
|
+
h4 {
|
32
|
+
cursor: default;
|
33
|
+
display: inline-block;
|
34
|
+
font-size: .9rem;
|
35
|
+
padding: 13px 0 0 5px;
|
36
|
+
vertical-align: middle;
|
37
|
+
text-transform: uppercase;
|
38
|
+
}
|
39
|
+
|
40
|
+
ul li {
|
41
|
+
&::before {
|
42
|
+
left: calc(var(--sidebar-icon-width) - 5px);
|
43
|
+
}
|
44
|
+
|
45
|
+
a {
|
46
|
+
padding-left: calc(var(--sidebar-icon-width) + 10px);
|
47
|
+
|
48
|
+
&:hover {
|
49
|
+
background-color: $primary;
|
50
|
+
}
|
51
|
+
}
|
52
|
+
}
|
53
|
+
|
54
|
+
.fa { font-size: 20px; }
|
55
|
+
.text { display: none; }
|
56
|
+
|
57
|
+
.collapse {
|
58
|
+
background-color: $secondary;
|
59
|
+
left: var(--sidebar-compact-width);
|
60
|
+
position: absolute;
|
61
|
+
top: 0;
|
62
|
+
width: 240px;
|
63
|
+
}
|
64
|
+
}
|
65
|
+
}
|
66
|
+
}
|
@@ -0,0 +1,23 @@
|
|
1
|
+
def class_exists?(class_name)
|
2
|
+
klass = Module.const_get(class_name)
|
3
|
+
return klass.is_a?(Class)
|
4
|
+
rescue NameError
|
5
|
+
return false
|
6
|
+
end
|
7
|
+
|
8
|
+
class Module
|
9
|
+
def takes(*arg_names)
|
10
|
+
define_method(:initialize) do |*arg_values|
|
11
|
+
arg_names.zip(arg_values).each do |name, value|
|
12
|
+
if name.is_a?(Hash)
|
13
|
+
name, default_value = name.to_a.flatten
|
14
|
+
value = default_value if value.blank?
|
15
|
+
end
|
16
|
+
|
17
|
+
instance_variable_set(:"@#{name}", value)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
alias_method :let, :define_method
|
23
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
require 'rails/generators/base'
|
2
|
+
|
3
|
+
class Plok::SidebarGenerator < Rails::Generators::Base
|
4
|
+
source_root File.expand_path('templates', __dir__)
|
5
|
+
class_option :css_framework, type: :string, default: 'bs5'
|
6
|
+
|
7
|
+
def install
|
8
|
+
copy_sidebar_files('wrapper', 'menu_items', 'menu_item', 'offcanvas_menu')
|
9
|
+
add_scss_imports_to_application
|
10
|
+
add_js_imports_to_application
|
11
|
+
inject_wrapper_block_into_application_layout
|
12
|
+
say("\nAll done! Remember to reboot your server so the new assets can load.\n\n")
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def add_js_imports_to_application
|
18
|
+
if application_file(:js)
|
19
|
+
unless file_contains?(application_file(:js), /\/\/= require plok\/sidebar/)
|
20
|
+
append_to_file application_file(:js), "//= require plok/sidebar"
|
21
|
+
end
|
22
|
+
else
|
23
|
+
say("\nWARNING: No suitable application.js file found.\n")
|
24
|
+
say("Please add the following import to your backend application.js file:\n\n")
|
25
|
+
say("//= require plok/sidebar\n\n")
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def add_scss_imports_to_application
|
30
|
+
if application_file(:scss)
|
31
|
+
unless file_contains?(application_file(:scss), /@import 'plok\/sidebar'/)
|
32
|
+
append_to_file application_file(:scss), "@import 'plok/sidebar';\n"
|
33
|
+
end
|
34
|
+
|
35
|
+
unless file_contains?(application_file(:scss), /@import 'plok\/sidebar_compact'/)
|
36
|
+
append_to_file application_file(:scss), "@import 'plok/sidebar_compact';\n"
|
37
|
+
end
|
38
|
+
else
|
39
|
+
say("\nWARNING: No suitable application.scss file found.\n")
|
40
|
+
say("Please add the following imports to your backend application.scss file:\n\n")
|
41
|
+
say("@import 'plok/sidebar';\n")
|
42
|
+
say("@import 'plok/sidebar_compact';\n")
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def inject_wrapper_block_into_application_layout
|
47
|
+
# The sidebar wrapper already exists, so stop here.
|
48
|
+
return if file_contains?(application_layout_file, /sidebar\/wrapper/)
|
49
|
+
|
50
|
+
# The wrapper is missing, but we *need* a suitable spot for a closing tag.
|
51
|
+
unless file_contains?(application_layout_file, /yield\(:javascripts_early\)/)
|
52
|
+
say("\nWARNING: The generator could not inject the sidebar wrapper.\n")
|
53
|
+
say("You will have to wrap your backend application markup in this block:\n\n")
|
54
|
+
say("# #{application_layout_file}\n")
|
55
|
+
say("<%= render 'backend/#{options.css_framework}/sidebar/wrapper', brand_name: '#{app_name}' do %>\n")
|
56
|
+
say(" # ...your backend application markup here...\n")
|
57
|
+
say("<% end %>\n")
|
58
|
+
return
|
59
|
+
end
|
60
|
+
|
61
|
+
gsub_file(
|
62
|
+
application_layout_file,
|
63
|
+
/<body(.*)>\n/,
|
64
|
+
"<body\\1>\n <%= render 'backend/#{options.css_framework}/sidebar/wrapper', brand_name: '#{app_name}' do %>\n"
|
65
|
+
)
|
66
|
+
|
67
|
+
gsub_file(
|
68
|
+
application_layout_file,
|
69
|
+
/\n(.*)<%= yield\(:javascripts_early\) %>/,
|
70
|
+
" <% end %>\n\n\\1<%= yield(:javascripts_early) %>"
|
71
|
+
)
|
72
|
+
end
|
73
|
+
|
74
|
+
def app_name
|
75
|
+
Rails.application.class.name.split('::').first
|
76
|
+
end
|
77
|
+
|
78
|
+
def copy_sidebar_files(*partials)
|
79
|
+
partials.each do |partial_name|
|
80
|
+
copy_file "_#{partial_name}.html.erb", sidebar_partial_path(partial_name)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def sidebar_partial_path(partial_name)
|
85
|
+
"app/views/backend/#{options.css_framework}/sidebar/_#{partial_name}.html.erb"
|
86
|
+
end
|
87
|
+
|
88
|
+
def file_contains?(file, content)
|
89
|
+
File.readlines(file).grep(content).any?
|
90
|
+
end
|
91
|
+
|
92
|
+
def application_layout_file
|
93
|
+
if File.exists?("app/views/layouts/backend/#{options.css_framework}/application.html.erb")
|
94
|
+
return "app/views/layouts/backend/#{options.css_framework}/application.html.erb"
|
95
|
+
end
|
96
|
+
|
97
|
+
if File.exists?('app/views/layouts/backend/application.html.erb')
|
98
|
+
return 'app/views/layouts/backend/application.html.erb'
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def application_file(type)
|
103
|
+
namespace = 'stylesheets'
|
104
|
+
namespace = 'javascripts' if type.to_s == 'js'
|
105
|
+
|
106
|
+
if File.exists?("app/assets/#{namespace}/backend/#{options.css_framework}/application.#{type}")
|
107
|
+
return "app/assets/#{namespace}/backend/#{options.css_framework}/application.#{type}"
|
108
|
+
end
|
109
|
+
|
110
|
+
if File.exists?("app/assets/#{namespace}/backend/application.#{type}")
|
111
|
+
return "app/assets/#{namespace}/backend/application.#{type}"
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
<% lbl ||= t("b.#{name}") %>
|
2
|
+
<% href ||= defined?(path) ? path : "#nav-#{name}" %>
|
3
|
+
|
4
|
+
<%= content_tag :li, class: 'top-level' do %>
|
5
|
+
<%= link_to href, class: 'top-level-anchor link-light', data: { bs_toggle: ('collapse' unless defined?(path)) } do %>
|
6
|
+
<%= fa_icon icon, class: 'fa-fw' %>
|
7
|
+
<%= content_tag :span, lbl, class: 'text' %>
|
8
|
+
<% end %>
|
9
|
+
|
10
|
+
<% unless defined?(path) %>
|
11
|
+
<%= content_tag :div, id: "nav-#{name}", class: 'collapse' do %>
|
12
|
+
<h4><%= lbl %></h4>
|
13
|
+
<%= yield %>
|
14
|
+
<% end %>
|
15
|
+
<% end %>
|
16
|
+
<% end %>
|
@@ -0,0 +1,11 @@
|
|
1
|
+
<div class="offcanvas offcanvas-start bg-dark text-light" tabindex="-1" id="navigation-offcanvas">
|
2
|
+
<div class="offcanvas-header">
|
3
|
+
<h5 class="offcanvas-title"><%= brand_name %></h5>
|
4
|
+
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="offcanvas" aria-label="Close"></button>
|
5
|
+
</div>
|
6
|
+
<div class="offcanvas-body">
|
7
|
+
<div class="sidebar-menu position-static">
|
8
|
+
<%= render 'backend/bs5/sidebar/menu_items' %>
|
9
|
+
</div>
|
10
|
+
</div>
|
11
|
+
</div>
|
@@ -0,0 +1,19 @@
|
|
1
|
+
<div class="wrapper">
|
2
|
+
<div class="sidebar-menu text-light bg-dark overflow-auto">
|
3
|
+
<%= link_to backend_path, class: 'text-center navbar-brand logo text-light me-0' do %>
|
4
|
+
<%= brand_name %>
|
5
|
+
<% end %>
|
6
|
+
|
7
|
+
<%= link_to fa_icon(:'home'), backend_path, class: 'text-center navbar-brand home-icon text-light fs-2 me-0' %>
|
8
|
+
|
9
|
+
<nav class="mt-3">
|
10
|
+
<%= render 'backend/bs5/sidebar/menu_items' %>
|
11
|
+
</nav>
|
12
|
+
</div>
|
13
|
+
|
14
|
+
<div class="content">
|
15
|
+
<%= yield %>
|
16
|
+
</div>
|
17
|
+
</div>
|
18
|
+
|
19
|
+
<%= render 'backend/bs5/sidebar/offcanvas_menu', brand_name: brand_name %>
|
data/lib/plok/engine.rb
CHANGED
data/lib/plok/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: plok
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Davy Hellemans
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2022-
|
12
|
+
date: 2022-06-17 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rails
|
@@ -78,12 +78,15 @@ files:
|
|
78
78
|
- MIT-LICENSE
|
79
79
|
- Rakefile
|
80
80
|
- app/assets/config/plok_manifest.js
|
81
|
+
- app/assets/javascripts/plok/sidebar.js
|
82
|
+
- app/assets/stylesheets/plok/_sidebar.scss
|
83
|
+
- app/assets/stylesheets/plok/_sidebar_compact.scss
|
81
84
|
- app/controllers/catch_all_controller.rb
|
82
85
|
- app/controllers/plok/version_controller.rb
|
83
86
|
- app/models/concerns/plok/loggable.rb
|
84
87
|
- app/models/log.rb
|
85
88
|
- app/models/queued_task.rb
|
86
|
-
- config/
|
89
|
+
- config/initializers/module.rb
|
87
90
|
- config/routes.rb
|
88
91
|
- db/migrate/20211008130809_create_plok_logs.rb
|
89
92
|
- db/migrate/20211015141837_create_plok_queued_tasks.rb
|
@@ -93,6 +96,12 @@ files:
|
|
93
96
|
- db/migrate/20211203103118_add_file_to_logs.rb
|
94
97
|
- db/migrate/20220512141814_add_log_indexes_to_category_type_and_id.rb
|
95
98
|
- db/migrate/20220512142356_add_index_to_queued_task_weight.rb
|
99
|
+
- lib/generators/plok/sidebar/USAGE
|
100
|
+
- lib/generators/plok/sidebar/sidebar_generator.rb
|
101
|
+
- lib/generators/plok/sidebar/templates/_menu_item.html.erb
|
102
|
+
- lib/generators/plok/sidebar/templates/_menu_items.html.erb
|
103
|
+
- lib/generators/plok/sidebar/templates/_offcanvas_menu.html.erb
|
104
|
+
- lib/generators/plok/sidebar/templates/_wrapper.html.erb
|
96
105
|
- lib/plok.rb
|
97
106
|
- lib/plok/engine.rb
|
98
107
|
- lib/plok/version.rb
|
@@ -120,7 +129,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
120
129
|
- !ruby/object:Gem::Version
|
121
130
|
version: '0'
|
122
131
|
requirements: []
|
123
|
-
rubygems_version: 3.
|
132
|
+
rubygems_version: 3.3.9
|
124
133
|
signing_key:
|
125
134
|
specification_version: 4
|
126
135
|
summary: CMS basics
|