ditty 0.7.1 → 0.10.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/.env.test +2 -0
- data/.gitignore +3 -0
- data/.pryrc +2 -0
- data/.rubocop.yml +24 -8
- data/.travis.yml +4 -8
- data/CNAME +1 -0
- data/Dockerfile +18 -0
- data/Gemfile.ci +0 -15
- data/Rakefile +5 -4
- data/Readme.md +24 -2
- data/_config.yml +1 -0
- data/config.ru +4 -4
- data/ditty.gemspec +31 -20
- data/docs/CNAME +1 -0
- data/docs/_config.yml +1 -0
- data/docs/index.md +34 -0
- data/exe/ditty +2 -0
- data/lib/ditty.rb +30 -4
- data/lib/ditty/cli.rb +38 -5
- data/lib/ditty/components/ditty.rb +82 -0
- data/lib/ditty/controllers/application_controller.rb +267 -0
- data/lib/ditty/controllers/{audit_logs.rb → audit_logs_controller.rb} +5 -7
- data/lib/ditty/controllers/{auth.rb → auth_controller.rb} +56 -32
- data/lib/ditty/controllers/{component.rb → component_controller.rb} +35 -24
- data/lib/ditty/controllers/{main.rb → main_controller.rb} +7 -7
- data/lib/ditty/controllers/roles_controller.rb +23 -0
- data/lib/ditty/controllers/user_login_traits_controller.rb +46 -0
- data/lib/ditty/controllers/{users.rb → users_controller.rb} +17 -20
- data/lib/ditty/db.rb +9 -5
- data/lib/ditty/emails/base.rb +48 -34
- data/lib/ditty/generators/crud_generator.rb +114 -0
- data/lib/ditty/generators/migration_generator.rb +26 -0
- data/lib/ditty/generators/project_generator.rb +52 -0
- data/lib/ditty/helpers/authentication.rb +6 -5
- data/lib/ditty/helpers/component.rb +11 -2
- data/lib/ditty/helpers/pundit.rb +24 -8
- data/lib/ditty/helpers/response.rb +38 -15
- data/lib/ditty/helpers/views.rb +48 -6
- data/lib/ditty/listener.rb +44 -14
- data/lib/ditty/memcached.rb +8 -0
- data/lib/ditty/middleware/accept_extension.rb +4 -2
- data/lib/ditty/middleware/error_catchall.rb +4 -2
- data/lib/ditty/models/audit_log.rb +1 -0
- data/lib/ditty/models/base.rb +13 -0
- data/lib/ditty/models/identity.rb +10 -7
- data/lib/ditty/models/role.rb +2 -0
- data/lib/ditty/models/user.rb +40 -3
- data/lib/ditty/models/user_login_trait.rb +17 -0
- data/lib/ditty/policies/audit_log_policy.rb +6 -6
- data/lib/ditty/policies/role_policy.rb +3 -3
- data/lib/ditty/policies/user_login_trait_policy.rb +45 -0
- data/lib/ditty/policies/user_policy.rb +3 -3
- data/lib/ditty/rubocop.rb +3 -0
- data/lib/ditty/seed.rb +2 -0
- data/lib/ditty/services/authentication.rb +31 -15
- data/lib/ditty/services/email.rb +22 -12
- data/lib/ditty/services/logger.rb +30 -13
- data/lib/ditty/services/pagination_wrapper.rb +9 -5
- data/lib/ditty/services/settings.rb +19 -7
- data/lib/ditty/tasks/ditty.rake +127 -0
- data/lib/ditty/tasks/omniauth-ldap.rake +43 -0
- data/lib/ditty/templates/.gitignore +5 -0
- data/lib/ditty/templates/.rspec +2 -0
- data/lib/ditty/templates/.rubocop.yml +7 -0
- data/lib/ditty/templates/Rakefile +12 -0
- data/lib/ditty/templates/application.rb +12 -0
- data/lib/ditty/templates/config.ru +37 -0
- data/lib/ditty/templates/controller.rb.erb +64 -0
- data/lib/ditty/templates/env.example +4 -0
- data/lib/ditty/templates/lib/project.rb.erb +5 -0
- data/lib/ditty/templates/migration.rb.erb +7 -0
- data/lib/ditty/templates/model.rb.erb +26 -0
- data/lib/ditty/templates/pids/.empty_directory +0 -0
- data/lib/ditty/templates/policy.rb.erb +48 -0
- data/{public → lib/ditty/templates/public}/browserconfig.xml +0 -0
- data/lib/ditty/templates/public/css/sb-admin-2.min.css +10 -0
- data/lib/ditty/templates/public/css/styles.css +13 -0
- data/lib/ditty/templates/public/favicon.ico +0 -0
- data/{public → lib/ditty/templates/public}/images/apple-icon.png +0 -0
- data/{public → lib/ditty/templates/public}/images/favicon-16x16.png +0 -0
- data/{public → lib/ditty/templates/public}/images/favicon-32x32.png +0 -0
- data/{public → lib/ditty/templates/public}/images/launcher-icon-1x.png +0 -0
- data/{public → lib/ditty/templates/public}/images/launcher-icon-2x.png +0 -0
- data/{public → lib/ditty/templates/public}/images/launcher-icon-4x.png +0 -0
- data/{public → lib/ditty/templates/public}/images/mstile-150x150.png +0 -0
- data/{public → lib/ditty/templates/public}/images/safari-pinned-tab.svg +0 -0
- data/lib/ditty/templates/public/js/sb-admin-2.min.js +7 -0
- data/lib/ditty/templates/public/js/scripts.js +1 -0
- data/{public/manifest.json → lib/ditty/templates/public/manifest.json.erb} +2 -2
- data/lib/ditty/templates/settings.yml.erb +19 -0
- data/lib/ditty/templates/sidekiq.rb +18 -0
- data/lib/ditty/templates/sidekiq.yml +9 -0
- data/lib/ditty/templates/spec_helper.rb +43 -0
- data/lib/ditty/templates/type.rb.erb +21 -0
- data/lib/ditty/templates/views/display.haml.tt +20 -0
- data/lib/ditty/templates/views/edit.haml.tt +10 -0
- data/lib/ditty/templates/views/form.haml.tt +11 -0
- data/lib/ditty/templates/views/index.haml.tt +29 -0
- data/lib/ditty/templates/views/new.haml.tt +10 -0
- data/lib/ditty/version.rb +1 -1
- data/lib/rubocop/cop/ditty/call_services_directly.rb +42 -0
- data/migrate/20181209_add_user_login_traits.rb +16 -0
- data/migrate/20181209_extend_audit_log.rb +12 -0
- data/migrate/20190220_add_parent_id_to_roles.rb +9 -0
- data/spec/ditty/api_spec.rb +51 -0
- data/spec/ditty/controllers/roles_spec.rb +67 -0
- data/spec/ditty/controllers/user_login_traits_spec.rb +72 -0
- data/spec/ditty/controllers/users_spec.rb +72 -0
- data/spec/ditty/emails/base_spec.rb +76 -0
- data/spec/ditty/emails/forgot_password_spec.rb +20 -0
- data/spec/ditty/helpers/component_spec.rb +85 -0
- data/spec/ditty/models/user_spec.rb +36 -0
- data/spec/ditty/services/email_spec.rb +36 -0
- data/spec/ditty/services/logger_spec.rb +68 -0
- data/spec/ditty/services/settings_spec.rb +63 -0
- data/spec/ditty_spec.rb +9 -0
- data/spec/factories.rb +46 -0
- data/spec/fixtures/logger.yml +17 -0
- data/spec/fixtures/section.yml +3 -0
- data/spec/fixtures/settings.yml +8 -0
- data/spec/spec_helper.rb +51 -0
- data/spec/support/api_shared_examples.rb +250 -0
- data/spec/support/crud_shared_examples.rb +145 -0
- data/views/403.haml +2 -0
- data/views/404.haml +2 -4
- data/views/500.haml +11 -0
- data/views/audit_logs/index.haml +32 -28
- data/views/auth/forgot_password.haml +32 -16
- data/views/auth/identity.haml +14 -13
- data/views/auth/ldap.haml +17 -0
- data/views/auth/login.haml +23 -17
- data/views/auth/register.haml +20 -18
- data/views/auth/register_identity.haml +27 -12
- data/views/auth/reset_password.haml +36 -19
- data/views/blank.haml +43 -0
- data/views/emails/forgot_password.haml +1 -1
- data/views/emails/layouts/action.haml +10 -6
- data/views/emails/layouts/alert.haml +2 -1
- data/views/emails/layouts/billing.haml +2 -1
- data/views/embedded.haml +17 -11
- data/views/error.haml +8 -3
- data/views/index.haml +1 -1
- data/views/layout.haml +45 -30
- data/views/partials/actions.haml +15 -14
- data/views/partials/content_tag.haml +0 -0
- data/views/partials/delete_form.haml +1 -1
- data/views/partials/filter_control.haml +2 -2
- data/views/partials/footer.haml +13 -5
- data/views/partials/form_control.haml +30 -19
- data/views/partials/form_tag.haml +1 -1
- data/views/partials/navitems.haml +42 -0
- data/views/partials/notifications.haml +12 -8
- data/views/partials/pager.haml +44 -25
- data/views/partials/search.haml +15 -11
- data/views/partials/sidebar.haml +15 -37
- data/views/partials/sort_ui.haml +2 -0
- data/views/partials/timespan_selector.haml +64 -0
- data/views/partials/topbar.haml +53 -0
- data/views/partials/user_associations.haml +32 -0
- data/views/quick_start.haml +23 -0
- data/views/roles/display.haml +27 -6
- data/views/roles/edit.haml +3 -3
- data/views/roles/form.haml +1 -0
- data/views/roles/index.haml +23 -14
- data/views/roles/new.haml +2 -2
- data/views/user_login_traits/display.haml +32 -0
- data/views/user_login_traits/edit.haml +10 -0
- data/views/user_login_traits/form.haml +5 -0
- data/views/user_login_traits/index.haml +28 -0
- data/views/user_login_traits/new.haml +10 -0
- data/views/users/display.haml +15 -16
- data/views/users/edit.haml +3 -3
- data/views/users/form.haml +0 -0
- data/views/users/index.haml +31 -24
- data/views/users/login_traits.haml +25 -0
- data/views/users/new.haml +2 -2
- data/views/users/profile.haml +17 -15
- data/views/users/user.haml +1 -1
- metadata +314 -76
- data/lib/ditty/components/app.rb +0 -77
- data/lib/ditty/controllers/application.rb +0 -175
- data/lib/ditty/controllers/roles.rb +0 -16
- data/lib/ditty/rake_tasks.rb +0 -102
- data/views/partials/navbar.haml +0 -23
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
%form{ { method: %i[get post].include?(form_verb.to_sym) ? form_verb : :post, action: url }.merge(attributes) }
|
|
2
|
-
= Rack::Csrf.csrf_tag(env) unless ENV['APP_ENV'] == 'test'
|
|
2
|
+
= Rack::Csrf.csrf_tag(env) unless form_verb.to_sym == :get || ENV['APP_ENV'] == 'test'
|
|
3
3
|
- if form_verb.to_sym == :get && layout
|
|
4
4
|
%input{ name: 'layout', value: layout, type: 'hidden' }
|
|
5
5
|
- if %i[get post].include?(form_verb.to_sym) == false
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
- if authenticated?
|
|
2
|
+
- Ditty::Components.navigation(request).each do |item|
|
|
3
|
+
- if item[:type] == 'divider'
|
|
4
|
+
%hr.sidebar-divider.my-0
|
|
5
|
+
- elsif item[:target].nil? || policy(item[:target]).list?
|
|
6
|
+
- if item[:group]
|
|
7
|
+
%li.nav-item
|
|
8
|
+
%a.nav-link.collapsed{ href: '#', 'data-toggle': 'collapse', 'data-target': "##{item[:group].parameterize}", 'aria-expanded': 'true', 'aria-controls': item[:group].parameterize }
|
|
9
|
+
- if item[:icon]
|
|
10
|
+
%i.fas.fa-fw{ class: "fa-#{item[:icon]}" }
|
|
11
|
+
%span= item[:group]
|
|
12
|
+
.collapse{ id: item[:group].parameterize, 'data-parent': '#accordionSidebar' }
|
|
13
|
+
.bg-white.py-2.collapse-inner.rounded
|
|
14
|
+
- item[:items].each do |sub_item|
|
|
15
|
+
- next unless sub_item[:target] && policy(sub_item[:target]).list?
|
|
16
|
+
%a.collapse-item{ href: "#{settings.map_path}#{sub_item[:link]}" }
|
|
17
|
+
- if sub_item[:icon]
|
|
18
|
+
%i.fa.fa-fw{ class: "fa-#{sub_item[:icon]}" }
|
|
19
|
+
= sub_item[:text]
|
|
20
|
+
- else
|
|
21
|
+
%li.nav-item
|
|
22
|
+
%a.nav-link{ href: "#{settings.map_path}#{item[:link]}" }
|
|
23
|
+
- if item[:icon]
|
|
24
|
+
%i.fas.fa-fw{ class: "fa-#{item[:icon]}" }
|
|
25
|
+
%span= item[:text]
|
|
26
|
+
%hr.sidebar-divider.my-0
|
|
27
|
+
%li.nav-item
|
|
28
|
+
= delete_form_tag("#{settings.map_path}/auth", attributes: { id: 'logout-form' }) do
|
|
29
|
+
%a.nav-link{ type: 'submit', onClick: 'document.getElementById("logout-form").submit()' }
|
|
30
|
+
%i.fas.fa-fw.fa-sign-out-alt
|
|
31
|
+
%span Logout
|
|
32
|
+
- else
|
|
33
|
+
%li.nav-item
|
|
34
|
+
%a.nav-link{ href: "#{settings.map_path}/auth/login" }
|
|
35
|
+
%i.fas.fa-fw.fa-user
|
|
36
|
+
%span Log In
|
|
37
|
+
- if policy(::Ditty::User).register?
|
|
38
|
+
%li.nav-item
|
|
39
|
+
%a.nav-link{ href: "#{settings.map_path}/auth/register" }
|
|
40
|
+
%i.fas.fa-fw.fa-pen-square
|
|
41
|
+
%span Register
|
|
42
|
+
|
|
@@ -1,28 +1,32 @@
|
|
|
1
1
|
- if flash[:danger]
|
|
2
2
|
.alert.alert-danger.alert-dismissible{ role: "alert" }
|
|
3
|
-
%button.close{
|
|
4
|
-
|
|
3
|
+
%button.close{ type: 'button', 'aria-label': 'Close', 'data-dismiss': 'alert' }
|
|
4
|
+
%span{ 'aria-hidden': 'true' } ×
|
|
5
|
+
%ul.mb-0
|
|
5
6
|
- [*flash[:danger]].each do |msg|
|
|
6
7
|
%li= msg
|
|
7
8
|
|
|
8
9
|
- if flash[:warning]
|
|
9
10
|
.alert.alert-warning.alert-dismissible{ role: "alert" }
|
|
10
|
-
%button.close{
|
|
11
|
-
|
|
11
|
+
%button.close{ type: 'button', 'aria-label': 'Close', 'data-dismiss': 'alert' }
|
|
12
|
+
%span{ 'aria-hidden': 'true' } ×
|
|
13
|
+
%ul.mb-0
|
|
12
14
|
- [*flash[:warning]].each do |msg|
|
|
13
15
|
%li= msg
|
|
14
16
|
|
|
15
17
|
- if flash[:success]
|
|
16
18
|
.alert.alert-success.alert-dismissible{ role: "alert" }
|
|
17
|
-
%button.close{
|
|
18
|
-
|
|
19
|
+
%button.close{ type: 'button', 'aria-label': 'Close', 'data-dismiss': 'alert' }
|
|
20
|
+
%span{ 'aria-hidden': 'true' } ×
|
|
21
|
+
%ul.mb-0
|
|
19
22
|
- [*flash[:success]].each do |msg|
|
|
20
23
|
%li= msg
|
|
21
24
|
|
|
22
25
|
|
|
23
26
|
- if flash[:info]
|
|
24
27
|
.alert.alert-info.alert-dismissible{ role: "alert" }
|
|
25
|
-
%button.close{
|
|
26
|
-
|
|
28
|
+
%button.close{ type: 'button', 'aria-label': 'Close', 'data-dismiss': 'alert' }
|
|
29
|
+
%span{ 'aria-hidden': 'true' } ×
|
|
30
|
+
%ul.mb-0
|
|
27
31
|
- [*flash[:info]].each do |msg|
|
|
28
32
|
%li= msg
|
data/views/partials/pager.haml
CHANGED
|
@@ -1,26 +1,45 @@
|
|
|
1
1
|
%nav{"aria-label" => "Page navigation"}
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
-
|
|
11
|
-
%
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
%
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
2
|
+
.row
|
|
3
|
+
.col-sm-12.col-md-6
|
|
4
|
+
%p.my-2
|
|
5
|
+
- if list.pagination_record_count > 0
|
|
6
|
+
Showing #{list.current_page_record_range} of #{list.pagination_record_count} records
|
|
7
|
+
- else
|
|
8
|
+
%p.text-center No records to show
|
|
9
|
+
.col-sm-12.col-md-6
|
|
10
|
+
- if list.pagination_record_count > 0
|
|
11
|
+
%ul.pagination.justify-content-end
|
|
12
|
+
- if list.first_page?
|
|
13
|
+
%li.page-item.disabled
|
|
14
|
+
%span.page-link First
|
|
15
|
+
%li.page-item.disabled
|
|
16
|
+
%span.page-link Previous
|
|
17
|
+
- else
|
|
18
|
+
%li.page-item
|
|
19
|
+
%a.page-link{ href: first_link } First
|
|
20
|
+
%li.page-item
|
|
21
|
+
%a.page-link{ href: prev_link } Previous
|
|
22
|
+
%li.page-item
|
|
23
|
+
.dropdown
|
|
24
|
+
%button.page-link.dropdown-toggle{ type: 'button', id: 'dropdownMenuButton', 'data-toggle': 'dropdown', 'aria-haspopup': 'true', 'aria-expanded': 'false' }
|
|
25
|
+
= params[:count] || 10
|
|
26
|
+
.dropdown-menu
|
|
27
|
+
%a.dropdown-item{ href: "#{base_path}?#{query_string(count: 10)}" } 10
|
|
28
|
+
%a.dropdown-item{ href: "#{base_path}?#{query_string(count: 25)}" } 25
|
|
29
|
+
%a.dropdown-item{ href: "#{base_path}?#{query_string(count: 50)}" } 50
|
|
30
|
+
%a.dropdown-item{ href: "#{base_path}?#{query_string(count: 100)}" } 100
|
|
31
|
+
- if list.last_page?
|
|
32
|
+
%li.page-item.disabled
|
|
33
|
+
%span.page-link Next
|
|
34
|
+
%li.page-item.disabled
|
|
35
|
+
%span.page-link Last
|
|
36
|
+
- else
|
|
37
|
+
%li.page-item
|
|
38
|
+
%a.page-link{ href: next_link } Next
|
|
39
|
+
%li.page-item
|
|
40
|
+
%a.page-link{ href: last_link } Last
|
|
41
|
+
%li
|
|
42
|
+
|
|
43
|
+
%li
|
|
44
|
+
%a.page-link{ href: "#{base_path}/.csv?#{URI.encode_www_form(params.merge(count: 'all'))}" }
|
|
45
|
+
Export
|
data/views/partials/search.haml
CHANGED
|
@@ -1,21 +1,25 @@
|
|
|
1
|
-
- if self.class.const_defined?(:SEARCHABLE) || self.class.const_defined?(:FILTERS)
|
|
1
|
+
- if self.class.const_defined?(:SEARCHABLE) && SEARCHABLE.count.positive? || self.class.const_defined?(:FILTERS) && FILTERS.count.positive?
|
|
2
2
|
= form_tag(base_path, form_verb: :get, attributes: { class: '' }) do
|
|
3
|
-
- if self.class.const_defined?(:SEARCHABLE)
|
|
3
|
+
- if self.class.const_defined?(:SEARCHABLE) && SEARCHABLE.count.positive?
|
|
4
4
|
.form-group
|
|
5
5
|
.input-group
|
|
6
6
|
%input.form-control{ name: 'q', type: 'text', placeholder: 'Search...', value: params[:q] }
|
|
7
7
|
.input-group-btn
|
|
8
8
|
%button.btn.btn-primary{ type: 'submit' }
|
|
9
9
|
%span.fa.fa-search
|
|
10
|
-
- if self.class.const_defined?
|
|
10
|
+
- if self.class.const_defined?(:FILTERS) && FILTERS.count.positive?
|
|
11
11
|
.input-group-btn
|
|
12
|
-
%button.btn.btn-
|
|
12
|
+
%button.btn.btn-secondary{ type: 'button', :'data-toggle' => 'collapse', :'data-target' => '#filter-form', :'aria-expanded' => 'false', :'aria-controls' => '#filter-form'}
|
|
13
13
|
%span.fa.fa-arrow-down
|
|
14
14
|
|
|
15
|
-
- if self.class.const_defined?(:FILTERS)
|
|
16
|
-
#filter-form{ class: self.class.const_defined?(:SEARCHABLE) ? 'collapse' : '' }
|
|
17
|
-
.
|
|
18
|
-
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
15
|
+
- if self.class.const_defined?(:FILTERS) && FILTERS.count.positive?
|
|
16
|
+
#filter-form{ class: self.class.const_defined?(:SEARCHABLE) && SEARCHABLE.count.positive? ? 'collapse' : '' }
|
|
17
|
+
.card.card-default.mb-2
|
|
18
|
+
.card-body
|
|
19
|
+
.row
|
|
20
|
+
- FILTERS.each do |filter|
|
|
21
|
+
= filter_control(filter, filters: FILTERS.count)
|
|
22
|
+
- unless self.class.const_defined?(:SEARCHABLE) && SEARCHABLE.count.positive?
|
|
23
|
+
.form-group
|
|
24
|
+
%label
|
|
25
|
+
%button.form-control.btn.btn-secondary{ type: 'submit'} Go
|
data/views/partials/sidebar.haml
CHANGED
|
@@ -1,37 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
%ul.nav.nav-second-level
|
|
17
|
-
- item[:items].each do |sub_item|
|
|
18
|
-
- if sub_item[:target].nil? || policy(sub_item[:target]).list?
|
|
19
|
-
%li
|
|
20
|
-
%a{ href: "#{settings.map_path}#{sub_item[:link]}" }
|
|
21
|
-
%i.fa.fa-fw{ class: "fa-#{sub_item[:icon]}" }
|
|
22
|
-
= sub_item[:text]
|
|
23
|
-
- else
|
|
24
|
-
%li
|
|
25
|
-
%a{ href: "#{settings.map_path}#{item[:link]}" }
|
|
26
|
-
%i.fa.fa-fw{ class: "fa-#{item[:icon]}" }
|
|
27
|
-
= item[:text]
|
|
28
|
-
- else
|
|
29
|
-
%li.active
|
|
30
|
-
%a{ href: "#{settings.map_path}/auth/login" }
|
|
31
|
-
%i.fa.fa-user.fa-fw
|
|
32
|
-
Log In
|
|
33
|
-
- if policy(::Ditty::User).register?
|
|
34
|
-
%li
|
|
35
|
-
%a{ href: "#{settings.map_path}/auth/register" }
|
|
36
|
-
%i.fa.fa-pencil-square-o.fa-fw
|
|
37
|
-
Register
|
|
1
|
+
/ Sidebar
|
|
2
|
+
%ul#accordionSidebar.navbar-nav.bg-gradient-primary.sidebar.sidebar-dark.accordion
|
|
3
|
+
/ Sidebar - Brand
|
|
4
|
+
%a.sidebar-brand.d-flex.align-items-center.justify-content-center{ href: config('ditty.home_page', settings.map_path || '/') }
|
|
5
|
+
.sidebar-brand-icon.rotate-n-15
|
|
6
|
+
%i.fas{ class: config('ditty.brand-icon', 'fa-laugh-wink') }
|
|
7
|
+
.sidebar-brand-text.mx-3
|
|
8
|
+
= config('ditty.title', 'Ditty')
|
|
9
|
+
|
|
10
|
+
%hr.sidebar-divider.my-0
|
|
11
|
+
|
|
12
|
+
= haml :'partials/navitems'
|
|
13
|
+
|
|
14
|
+
.text-center.d-none.d-md-inline
|
|
15
|
+
%button#sidebarToggle.rounded-circle.border-0
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
- if defined?(context)
|
|
2
|
+
- if context.interval
|
|
3
|
+
%li.nav-item.dropdown.no-arrow
|
|
4
|
+
%a#intervalDropdown.nav-link.dropdown-toggle{ href: '#', role: 'button', 'aria-haspopup': 'true', 'area-expanded': 'false', 'data-toggle': 'dropdown' }
|
|
5
|
+
%span.mr-2.d-none.d-lg-inline.text-gray-600
|
|
6
|
+
Interval /
|
|
7
|
+
%strong
|
|
8
|
+
= context.interval
|
|
9
|
+
.dropdown-menu.dropdown-menu-right.shadow.animated--grow-in{ 'aria-labelledby': 'intervalDropdown' }
|
|
10
|
+
%a.dropdown-item{ href: "?#{URI.encode_www_form(and_params.merge(interval: '1m'))}", class: context.interval == '1m' ? 'active' : '' }
|
|
11
|
+
1 Minute
|
|
12
|
+
%a.dropdown-item{ href: "?#{URI.encode_www_form(and_params.merge(interval: '5m'))}", class: context.interval == '5m' ? 'active' : '' }
|
|
13
|
+
5 Minutes
|
|
14
|
+
%a.dropdown-item{ href: "?#{URI.encode_www_form(and_params.merge(interval: '15m'))}", class: context.interval == '15m' ? 'active' : '' }
|
|
15
|
+
15 Minutes
|
|
16
|
+
.dropdown-divider
|
|
17
|
+
%a.dropdown-item{ href: "?#{URI.encode_www_form(and_params.merge(interval: '1h'))}", class: context.interval == '1h' ? 'active' : '' }
|
|
18
|
+
1 Hour
|
|
19
|
+
%a.dropdown-item{ href: "?#{URI.encode_www_form(and_params.merge(interval: '3h'))}", class: context.interval == '3h' ? 'active' : '' }
|
|
20
|
+
3 Hours
|
|
21
|
+
%a.dropdown-item{ href: "?#{URI.encode_www_form(and_params.merge(interval: '6h'))}", class: context.interval == '6h' ? 'active' : '' }
|
|
22
|
+
6 Hours
|
|
23
|
+
.dropdown-divider
|
|
24
|
+
%a.dropdown-item{ href: "?#{URI.encode_www_form(and_params.merge(interval: '1d'))}", class: context.interval == '1d' ? 'active' : '' }
|
|
25
|
+
1 Day
|
|
26
|
+
%a.dropdown-item{ href: "?#{URI.encode_www_form(and_params.merge(interval: '2d'))}", class: context.interval == '2d' ? 'active' : '' }
|
|
27
|
+
2 Days
|
|
28
|
+
%a.dropdown-item{ href: "?#{URI.encode_www_form(and_params.merge(interval: '1w'))}", class: context.interval == '1w' ? 'active' : '' }
|
|
29
|
+
1 Week
|
|
30
|
+
|
|
31
|
+
- if context.timespan
|
|
32
|
+
%li.nav-item.dropdown.no-arrow
|
|
33
|
+
%a#timespanDropdown.nav-link.dropdown-toggle{ href: '#', role: 'button', 'aria-haspopup': 'true', 'area-expanded': 'false', 'data-toggle': 'dropdown' }
|
|
34
|
+
%span.mr-2.d-none.d-lg-inline.text-gray-600
|
|
35
|
+
Timespan /
|
|
36
|
+
%strong
|
|
37
|
+
= context.timespan.split('/').first
|
|
38
|
+
.dropdown-menu.dropdown-menu-right.shadow.animated--grow-in{ 'aria-labelledby': 'timespanDropdown' }
|
|
39
|
+
%a.dropdown-item{ href: "?#{URI.encode_www_form(and_params.merge(timespan: '1h', interval: ''))}", class: context.timespan == '1h' ? 'active' : '' }
|
|
40
|
+
%i.fas.fa-chevron-right.fa-sm.fa-fw.mr-2.text-gray-400
|
|
41
|
+
1 Hour
|
|
42
|
+
%a.dropdown-item{ href: "?#{URI.encode_www_form(and_params.merge(timespan: '1d', interval: ''))}", class: context.timespan == '1d' ? 'active' : '' }
|
|
43
|
+
%i.fas.fa-chevron-right.fa-sm.fa-fw.mr-2.text-gray-400
|
|
44
|
+
1 Day
|
|
45
|
+
.dropdown-divider
|
|
46
|
+
%a.dropdown-item{ href: "?#{URI.encode_www_form(and_params.merge(timespan: '1w/d', interval: ''))}", class: context.timespan == '1w/d' ? 'active' : '' }
|
|
47
|
+
%i.fas.fa-chevron-right.fa-sm.fa-fw.mr-2.text-gray-400
|
|
48
|
+
1 Week
|
|
49
|
+
%a.dropdown-item{ href: "?#{URI.encode_www_form(and_params.merge(timespan: '2w/d', interval: ''))}", class: context.timespan == '2w/d' ? 'active' : '' }
|
|
50
|
+
%i.fas.fa-chevron-right.fa-sm.fa-fw.mr-2.text-gray-400
|
|
51
|
+
2 Weeks
|
|
52
|
+
%a.dropdown-item{ href: "?#{URI.encode_www_form(and_params.merge(timespan: '1M/d', interval: ''))}", class: context.timespan == '1M/d' ? 'active' : '' }
|
|
53
|
+
%i.fas.fa-chevron-right.fa-sm.fa-fw.mr-2.text-gray-400
|
|
54
|
+
1 Month
|
|
55
|
+
.dropdown-divider
|
|
56
|
+
%a.dropdown-item{ href: "?#{URI.encode_www_form(and_params.merge(timespan: '3M/d', interval: ''))}", class: context.timespan == '3M/d' ? 'active' : '' }
|
|
57
|
+
%i.fas.fa-chevron-right.fa-sm.fa-fw.mr-2.text-gray-400
|
|
58
|
+
3 Months
|
|
59
|
+
%a.dropdown-item{ href: "?#{URI.encode_www_form(and_params.merge(timespan: '6M/d', interval: ''))}", class: context.timespan == '6M/d' ? 'active' : '' }
|
|
60
|
+
%i.fas.fa-chevron-right.fa-sm.fa-fw.mr-2.text-gray-400
|
|
61
|
+
6 Months
|
|
62
|
+
%a.dropdown-item{ href: "?#{URI.encode_www_form(and_params.merge(timespan: '1y/d', interval: ''))}", class: context.timespan == '1y/d' ? 'active' : '' }
|
|
63
|
+
%i.fas.fa-chevron-right.fa-sm.fa-fw.mr-2.text-gray-400
|
|
64
|
+
1 Year
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
%nav.navbar.navbar-expand.navbar-light.bg-white.topbar.mb-4.static-top.shadow
|
|
2
|
+
/ Sidebar Toggle
|
|
3
|
+
%button#sidebarToggleTop.btn.btn-link.d-md-none.rounded-circle.mr-3
|
|
4
|
+
%i.fa.fa-bars
|
|
5
|
+
|
|
6
|
+
/ Topbar Search
|
|
7
|
+
%form.d-none.d-sm-inline-block.form-inline.mr-auto.ml-md-3.my-2.my-md-0.mw-100.navbar-search
|
|
8
|
+
.input-group
|
|
9
|
+
%input.form-control.bg-light.border-0.small{ type: 'text', placeholder: 'Search for...', 'aria-label': 'Search', 'aria-describedby': 'basic-addon2' }
|
|
10
|
+
.input-group-append
|
|
11
|
+
%button.btn.btn-primary{ type: 'button' }
|
|
12
|
+
%i.fas.fa-search.fa-sm
|
|
13
|
+
|
|
14
|
+
/ Topbar Navbar
|
|
15
|
+
%ul.navbar-nav.ml-auto
|
|
16
|
+
/ Nav Item - Search Dropdown (Visible Only XS)
|
|
17
|
+
%li.nav-item.dropdown.no-arrow.d-sm-none
|
|
18
|
+
%a#searchDropdown.nav-link.dropdown-toggle{ href: '#', role: 'button', 'data-toggle': 'dropdown', 'aria-haspopup': 'true', 'aria-expanded': 'false' }
|
|
19
|
+
%i.fas.fa-search.fa-fw
|
|
20
|
+
/ Dropdown - Messages
|
|
21
|
+
.dropdown-menu.dropdown-menu-right.p-3.shadow.animated--grow-in{ :'aria-labelledby' => 'searchDropdown' }
|
|
22
|
+
%form.form-inline.mr-auto.w-100.navbar-search
|
|
23
|
+
.input-group
|
|
24
|
+
%input.form-control.bg-light.border-0.small{ type: 'text', placeholder: 'Search for...', :'aria-label' => 'Search', :'aria-describedby' => 'basic-addon2' }
|
|
25
|
+
.input-group-append
|
|
26
|
+
%button.btn.btn-primary{ type: 'button' }
|
|
27
|
+
%i.fas.fa-.fa-sm
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
.topbar-divider.d-none.d-sm-block
|
|
31
|
+
|
|
32
|
+
/ Nav Item - User Information
|
|
33
|
+
- if authenticated?
|
|
34
|
+
%li.nav-item.dropdown.no-arrow
|
|
35
|
+
%a#userDropdown.nav-link.dropdown-toggle{ href: '#', role: 'button', 'aria-haspopup': 'true', 'area-expanded': 'false', 'data-toggle': 'dropdown' }
|
|
36
|
+
%span.mr-2.d-none.d-lg-inline.text-gray-600.small= current_user.display_name
|
|
37
|
+
%img.img-profile.rounded-circle{ src: current_user.gravatar }
|
|
38
|
+
/ Dropdown - User Information
|
|
39
|
+
.dropdown-menu.dropdown-menu-right.shadow.animated--grow-in{ 'aria-labelledby': 'userDropdown' }
|
|
40
|
+
%a.dropdown-item{ href: "#{settings.map_path}/users/profile" }
|
|
41
|
+
%i.fas.fa-user.fa-sm.fa-fw.mr-2.text-gray-400
|
|
42
|
+
Profile
|
|
43
|
+
/ %a.dropdown-item{ href: '#' }
|
|
44
|
+
/ %i.fas.fa-cogs.fa-sm.fa-fw.mr-2.text-gray-400
|
|
45
|
+
/ Settings
|
|
46
|
+
%a.dropdown-item{ href: "#{settings.map_path}/login-traits" }
|
|
47
|
+
%i.fas.fa-list.fa-sm.fa-fw.mr-2.text-gray-400
|
|
48
|
+
Past Logins
|
|
49
|
+
.dropdown-divider
|
|
50
|
+
%a.dropdown-item{ href: '#', data: { toggle: 'modal', target: '#logoutModal' } }
|
|
51
|
+
%i.fas.fa-sign-out-alt.fa-sm.fa-fw.mr-2.text-gray-400
|
|
52
|
+
Logout
|
|
53
|
+
- else
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
- group = entity.class.to_s.demodulize.underscore
|
|
2
|
+
%table.table.mb-0
|
|
3
|
+
%tbody
|
|
4
|
+
- if entity.users.count.positive?
|
|
5
|
+
- entity.users.each do |user|
|
|
6
|
+
%tr
|
|
7
|
+
%td
|
|
8
|
+
- if policy(user).read?
|
|
9
|
+
%a{ href: "#{settings.map_path}/users/#{user.id}" }
|
|
10
|
+
= user.username
|
|
11
|
+
- else
|
|
12
|
+
= user.username
|
|
13
|
+
%td.text-right
|
|
14
|
+
= delete_form_tag "#{base_path}/#{entity.display_id}/users/#{user.id}" do
|
|
15
|
+
%button.btn.btn-danger.btn-sm{ type: 'submit' } ×
|
|
16
|
+
- else
|
|
17
|
+
%tr
|
|
18
|
+
%td{ colspan: 2 } No Users Associated
|
|
19
|
+
%tr
|
|
20
|
+
%td{ colspan: 2 }
|
|
21
|
+
- users = user_options.select { |k, v| entity.users.map(&:id).include?(k) == false }
|
|
22
|
+
- if users && users.count.positive?
|
|
23
|
+
= new_form_tag "#{base_path}/#{entity.display_id}/users" do
|
|
24
|
+
.input-group
|
|
25
|
+
%select.form-control{ name: "#{group}[user_id]", id: 'user_id' }
|
|
26
|
+
%option{ value: '' } Select User
|
|
27
|
+
- users.each do |key, value|
|
|
28
|
+
%option{ value: key }= value
|
|
29
|
+
%span.input-group-append
|
|
30
|
+
%button.btn.btn-primary{ type: 'submit' } Add User
|
|
31
|
+
- else
|
|
32
|
+
No Users available to link
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
%link{ rel: 'stylesheet', href: 'https://cdnjs.cloudflare.com/ajax/libs/prism/1.20.0/themes/prism-okaidia.min.css' }
|
|
2
|
+
|
|
3
|
+
.row.mb-4
|
|
4
|
+
.col-2
|
|
5
|
+
.col-8
|
|
6
|
+
.card.card-default.border-left-dark.shadow.h-100
|
|
7
|
+
%h4.card-header Run on a folder
|
|
8
|
+
.card-body
|
|
9
|
+
%pre
|
|
10
|
+
%code.lang-shell
|
|
11
|
+
:preserve
|
|
12
|
+
docker run -d -e ELASTICSEARCH_HOSTS=192.168.1.200:9200 \
|
|
13
|
+
--volume=/var/log/nginx/:/usr/share/incoming/ \
|
|
14
|
+
hackerplanet/requestd-filebeat:latest
|
|
15
|
+
.card.card-default.border-left-dark.shadow.h-100
|
|
16
|
+
%h4.card-header Run on a single file
|
|
17
|
+
.card-body
|
|
18
|
+
%pre
|
|
19
|
+
%code.lang-shell
|
|
20
|
+
:preserve
|
|
21
|
+
docker run -d -e ELASTICSEARCH_HOSTS=elastic.hackerpla.net:9200 \
|
|
22
|
+
--volume=/var/log/nginx/access.log:/usr/share/incoming/access.log \
|
|
23
|
+
hackerplanet/requestd-filebeat:latest
|
data/views/roles/display.haml
CHANGED
|
@@ -1,17 +1,38 @@
|
|
|
1
|
-
.row
|
|
1
|
+
.row.mb-4
|
|
2
2
|
.col-md-2
|
|
3
3
|
.col-md-8
|
|
4
|
-
.
|
|
5
|
-
.
|
|
4
|
+
.card.card-default.shadow
|
|
5
|
+
.card-body
|
|
6
6
|
%p.description
|
|
7
7
|
%label Name:
|
|
8
|
-
= entity.name
|
|
8
|
+
= entity.name.titlecase
|
|
9
|
+
%p.description
|
|
10
|
+
%label Parent:
|
|
11
|
+
%a{ href: "#{base_path}/#{entity.parent_id}" }= entity.parent&.name&.titlecase || '(None)'
|
|
9
12
|
|
|
10
13
|
.row
|
|
11
14
|
.col-md-6
|
|
12
|
-
%a.btn.btn-
|
|
15
|
+
%a.btn.btn-secondary{ href: "#{base_path}/#{entity.display_id}/edit" } Edit
|
|
13
16
|
.col-md-6.text-right
|
|
14
17
|
- if policy(entity).delete?
|
|
15
|
-
= delete_form_tag("#{base_path}/#{entity.
|
|
18
|
+
= delete_form_tag("#{base_path}/#{entity.display_id}") do
|
|
16
19
|
%button.btn.btn-warning{ type: 'submit' } Delete
|
|
17
20
|
.col-md-2
|
|
21
|
+
|
|
22
|
+
.row
|
|
23
|
+
.col-md-2
|
|
24
|
+
.col-md-8
|
|
25
|
+
.card.card-default.shadow
|
|
26
|
+
.card-body
|
|
27
|
+
%h4.card-title Included Roles
|
|
28
|
+
%table.table.table-striped.mb-0
|
|
29
|
+
%tbody
|
|
30
|
+
- if entity.descendants.count > 0
|
|
31
|
+
- entity.descendants.each do |role|
|
|
32
|
+
%tr
|
|
33
|
+
%td
|
|
34
|
+
%a.btn-block{ href: "#{settings.map_path}/role/#{role.id}" }
|
|
35
|
+
= role.name.titlecase
|
|
36
|
+
- else
|
|
37
|
+
%tr
|
|
38
|
+
%td.text-center No records
|