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