tolaria 1.2.1 → 2.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/.travis.yml +1 -3
- data/README.md +8 -3
- data/Rakefile +1 -0
- data/app/assets/fonts/admin/fontawesome.woff +0 -0
- data/app/assets/fonts/admin/fontawesome.woff2 +0 -0
- data/app/assets/stylesheets/admin/components/_navigation.scss +8 -13
- data/app/assets/stylesheets/admin/components/_resource_form.scss +16 -5
- data/app/assets/stylesheets/admin/settings/_fonts.scss +2 -8
- data/app/assets/stylesheets/admin/settings/_icons.scss +123 -0
- data/app/controllers/admin/admin_controller.rb +1 -1
- data/app/controllers/admin/sessions_controller.rb +1 -1
- data/app/controllers/tolaria/resource_controller.rb +42 -19
- data/app/controllers/tolaria/tolaria_controller.rb +2 -2
- data/app/helpers/admin/table_helper.rb +7 -7
- data/app/helpers/admin/view_helper.rb +6 -9
- data/app/views/admin/tolaria_resource/_form_buttons.html.erb +1 -3
- data/app/views/admin/tolaria_resource/_index_table.html.erb +1 -1
- data/app/views/admin/tolaria_resource/edit.html.erb +12 -3
- data/app/views/admin/tolaria_resource/index.html.erb +1 -4
- data/app/views/admin/tolaria_resource/show.html.erb +1 -1
- data/lib/tolaria.rb +1 -1
- data/lib/tolaria/engine.rb +0 -1
- data/lib/tolaria/ransack.rb +43 -0
- data/lib/tolaria/version.rb +1 -1
- data/test/demo/app/models/application_record.rb +3 -0
- data/test/demo/app/models/blog_post.rb +1 -1
- data/test/demo/app/models/footnote.rb +1 -1
- data/test/demo/app/models/image.rb +1 -1
- data/test/demo/app/models/legal_page.rb +1 -1
- data/test/demo/app/models/miscellany.rb +6 -2
- data/test/demo/app/models/topic.rb +1 -1
- data/test/demo/app/models/video.rb +1 -1
- data/test/demo/app/views/admin/legal_pages/_form.html.erb +1 -1
- data/test/demo/app/views/admin/miscellany/_form.html.erb +3 -0
- data/test/demo/config/application.rb +0 -4
- data/test/demo/config/environments/test.rb +2 -2
- data/test/demo/db/schema.rb +8 -15
- data/test/integration/filter_preservation_test.rb +1 -2
- data/test/integration/forbidden_routes_test.rb +28 -2
- data/test/integration/pagination_test.rb +76 -0
- data/test/integration/session_test.rb +1 -2
- data/tolaria.gemspec +5 -5
- metadata +34 -31
- data/app/assets/fonts/admin/fontawesome.eot +0 -0
- data/app/assets/fonts/admin/fontawesome.svg +0 -655
- data/app/assets/fonts/admin/fontawesome.ttf +0 -0
- data/test/demo/app/models/.keep +0 -0
@@ -38,11 +38,6 @@ module Admin::ViewHelper
|
|
38
38
|
lookup_context.template_exists?("admin/#{template_path}", [], true)
|
39
39
|
end
|
40
40
|
|
41
|
-
# True if Ransack filtering parameters are present
|
42
|
-
def currently_filtering?
|
43
|
-
params[:q].present? && params[:q].is_a?(Hash) && params[:q].keys.reject{|key| key == "s"}.any?
|
44
|
-
end
|
45
|
-
|
46
41
|
# Attempt to automatically construct a default text search
|
47
42
|
# field name for Ransack from a given model's table settings
|
48
43
|
def ransack_text_search_chain(model)
|
@@ -58,12 +53,14 @@ module Admin::ViewHelper
|
|
58
53
|
return %{Are you sure you want to delete the #{resource.model_name.human.downcase} “#{Tolaria.display_name(resource)}”? This action is not reversible.}
|
59
54
|
end
|
60
55
|
|
56
|
+
# Returns the correct value to pass to the `url:` of `form_for`,
|
57
|
+
# based on the current controller.action_name
|
61
58
|
def contextual_form_url
|
62
59
|
case controller.action_name
|
63
|
-
when "edit"
|
64
|
-
url_for(action:"
|
65
|
-
when "new"
|
66
|
-
url_for(action:"
|
60
|
+
when "edit"
|
61
|
+
url_for(action:"update", id:@resource.id)
|
62
|
+
when "new"
|
63
|
+
url_for(action:"create")
|
67
64
|
else
|
68
65
|
nil
|
69
66
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
<% if @managed_class.allows? :index %>
|
2
|
-
<%= link_to url_for(action:"index", q:
|
2
|
+
<%= link_to url_for(action:"index", q:ransack_params, p:page_param), class:"button -cancel" do %>
|
3
3
|
<%= fontawesome_icon :close %>
|
4
4
|
Cancel
|
5
5
|
<% end %>
|
@@ -17,5 +17,3 @@
|
|
17
17
|
<%= fontawesome_icon :check %>
|
18
18
|
<%= @resource.persisted?? "Save" : "Create" %>
|
19
19
|
<% end %>
|
20
|
-
|
21
|
-
|
@@ -6,19 +6,28 @@
|
|
6
6
|
|
7
7
|
<%= form_for [:admin, @resource], url:contextual_form_url, builder:Admin::FormBuilder, html:{class:"resource-form"} do |form_builder| %>
|
8
8
|
|
9
|
-
<% if
|
10
|
-
|
9
|
+
<% if page_param.present? %>
|
10
|
+
|
11
|
+
<% end %>
|
12
|
+
|
13
|
+
<% if ransack_params.present? %>
|
14
|
+
<% ransack_params.each do |key, value| %>
|
15
|
+
<% next if value.respond_to?(:keys) %>
|
11
16
|
<%= hidden_field_tag "q[#{key}]", value %>
|
12
17
|
<% end %>
|
13
18
|
<% end %>
|
14
19
|
|
20
|
+
<% if page_param.present? %>
|
21
|
+
<%= hidden_field_tag :p, page_param %>
|
22
|
+
<% end %>
|
23
|
+
|
15
24
|
<div class="main-controls">
|
16
25
|
<div class="main-controls-left">
|
17
26
|
<h1>
|
18
27
|
<span class="crumb">
|
19
28
|
<%= fontawesome_icon @managed_class.icon %>
|
20
29
|
<% if @managed_class.allows? :index %>
|
21
|
-
<%= link_to @managed_class.model_name.human.pluralize.titleize, url_for(action:"index", controller:@managed_class.plural, q:
|
30
|
+
<%= link_to @managed_class.model_name.human.pluralize.titleize, url_for(action:"index", controller:@managed_class.plural, q:ransack_params, p:page_param) %>
|
22
31
|
<% else %>
|
23
32
|
<%= @managed_class.model_name.human.pluralize.titleize %>
|
24
33
|
<% end %>
|
@@ -26,7 +26,7 @@
|
|
26
26
|
<% end %>
|
27
27
|
|
28
28
|
<% if @managed_class.allows?(:new) %>
|
29
|
-
<%= link_to url_for(action:"new", q:
|
29
|
+
<%= link_to url_for(action:"new", q:ransack_params, p:page_param), class:"button -primary" do %>
|
30
30
|
<%= fontawesome_icon :plus %>
|
31
31
|
New <%= @managed_class.model_name.human.titleize %>
|
32
32
|
<% end %>
|
@@ -38,6 +38,3 @@
|
|
38
38
|
|
39
39
|
<%= render "admin/tolaria_resource/search_form" %>
|
40
40
|
<%= render "admin/tolaria_resource/index_table" %>
|
41
|
-
|
42
|
-
|
43
|
-
|
@@ -7,7 +7,7 @@
|
|
7
7
|
<span class="crumb">
|
8
8
|
<%= fontawesome_icon @managed_class.icon %>
|
9
9
|
<% if @managed_class.allows? :index %>
|
10
|
-
<%= link_to @managed_class.model_name.human.pluralize.titleize, url_for(action:"index", controller:@managed_class.plural, q:
|
10
|
+
<%= link_to @managed_class.model_name.human.pluralize.titleize, url_for(action:"index", controller:@managed_class.plural, q:ransack_params, p:page_param) %>
|
11
11
|
<% else %>
|
12
12
|
<%= @managed_class.model_name.human.pluralize.titleize %>
|
13
13
|
<% end %>
|
data/lib/tolaria.rb
CHANGED
@@ -9,12 +9,12 @@ require "kaminari"
|
|
9
9
|
require "ransack"
|
10
10
|
|
11
11
|
require "tolaria/version"
|
12
|
+
require "tolaria/ransack"
|
12
13
|
require "tolaria/engine"
|
13
14
|
require "tolaria/config"
|
14
15
|
require "tolaria/default_config"
|
15
16
|
require "tolaria/random_tokens"
|
16
17
|
require "tolaria/admin"
|
17
|
-
|
18
18
|
require "tolaria/reload"
|
19
19
|
require "tolaria/managed_class"
|
20
20
|
require "tolaria/manage"
|
data/lib/tolaria/engine.rb
CHANGED
@@ -0,0 +1,43 @@
|
|
1
|
+
# Until Ransack releases a new gem version, we have to patch in this
|
2
|
+
# Rails 5 support from their master branch
|
3
|
+
|
4
|
+
module Ransack
|
5
|
+
module Helpers
|
6
|
+
module FormHelper
|
7
|
+
|
8
|
+
def sort_link(search_object, attribute, *args, &block)
|
9
|
+
search, routing_proxy = extract_search_and_routing_proxy(search_object)
|
10
|
+
unless Search === search
|
11
|
+
raise TypeError, 'First argument must be a Ransack::Search!'
|
12
|
+
end
|
13
|
+
args.unshift(capture(&block)) if block_given?
|
14
|
+
s = SortLink.new(search, attribute, args, params, &block)
|
15
|
+
link_to(s.name, url(routing_proxy, s.url_options), s.html_options(args))
|
16
|
+
end
|
17
|
+
|
18
|
+
class SortLink
|
19
|
+
|
20
|
+
def initialize(search, attribute, args, params)
|
21
|
+
@search = search
|
22
|
+
@params = parameters_hash(params)
|
23
|
+
@field = attribute.to_s
|
24
|
+
@sort_fields = extract_sort_fields_and_mutate_args!(args).compact
|
25
|
+
@current_dir = existing_sort_direction
|
26
|
+
@label_text = extract_label_and_mutate_args!(args)
|
27
|
+
@options = extract_options_and_mutate_args!(args)
|
28
|
+
@hide_indicator = @options.delete(:hide_indicator) || Ransack.options[:hide_sort_order_indicators]
|
29
|
+
@default_order = @options.delete :default_order
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def parameters_hash(params)
|
35
|
+
return params unless params.respond_to?(:to_unsafe_h)
|
36
|
+
params.to_unsafe_h
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
data/lib/tolaria/version.rb
CHANGED
@@ -1,12 +1,16 @@
|
|
1
|
-
class Miscellany <
|
1
|
+
class Miscellany < ApplicationRecord
|
2
2
|
|
3
3
|
manage_with_tolaria using:{
|
4
4
|
icon: "cogs",
|
5
5
|
category: "Settings",
|
6
|
-
allowed_actions: [:index, :
|
6
|
+
allowed_actions: [:index, :edit, :update],
|
7
7
|
permit_params: [
|
8
8
|
:value
|
9
9
|
],
|
10
10
|
}
|
11
11
|
|
12
|
+
def to_s
|
13
|
+
key
|
14
|
+
end
|
15
|
+
|
12
16
|
end
|
@@ -18,9 +18,5 @@ module Demo
|
|
18
18
|
# config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
|
19
19
|
# config.i18n.default_locale = :de
|
20
20
|
|
21
|
-
# Do not swallow errors in after_commit/after_rollback callbacks.
|
22
|
-
config.active_record.raise_in_transactional_callbacks = true
|
23
|
-
|
24
21
|
end
|
25
22
|
end
|
26
|
-
|
@@ -14,8 +14,8 @@ Rails.application.configure do
|
|
14
14
|
config.eager_load = false
|
15
15
|
|
16
16
|
# Configure static file server for tests with Cache-Control for performance.
|
17
|
-
config.
|
18
|
-
config.
|
17
|
+
config.public_file_server.enabled = true
|
18
|
+
config.public_file_server.headers = {"Cache-Control" => "public, max-age=3600"}
|
19
19
|
|
20
20
|
# Show full error reports and disable caching.
|
21
21
|
config.consider_all_requests_local = true
|
data/test/demo/db/schema.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
# encoding: UTF-8
|
2
1
|
# This file is auto-generated from the current state of the database. Instead
|
3
2
|
# of editing this file, please use the migrations feature of Active Record to
|
4
3
|
# incrementally modify your database, and then regenerate this schema definition.
|
@@ -26,19 +25,17 @@ ActiveRecord::Schema.define(version: 20150610135235) do
|
|
26
25
|
t.integer "lockout_strikes", default: 0, null: false
|
27
26
|
t.integer "total_strikes", default: 0, null: false
|
28
27
|
t.integer "sessions_created", default: 0, null: false
|
28
|
+
t.index ["auth_token"], name: "index_administrators_on_auth_token"
|
29
|
+
t.index ["email"], name: "index_administrators_on_email"
|
29
30
|
end
|
30
31
|
|
31
|
-
add_index "administrators", ["auth_token"], name: "index_administrators_on_auth_token"
|
32
|
-
add_index "administrators", ["email"], name: "index_administrators_on_email"
|
33
|
-
|
34
32
|
create_table "blog_post_topics", force: :cascade do |t|
|
35
33
|
t.integer "blog_post_id", null: false
|
36
34
|
t.integer "topic_id", null: false
|
35
|
+
t.index ["blog_post_id"], name: "index_blog_post_topics_on_blog_post_id"
|
36
|
+
t.index ["topic_id"], name: "index_blog_post_topics_on_topic_id"
|
37
37
|
end
|
38
38
|
|
39
|
-
add_index "blog_post_topics", ["blog_post_id"], name: "index_blog_post_topics_on_blog_post_id"
|
40
|
-
add_index "blog_post_topics", ["topic_id"], name: "index_blog_post_topics_on_topic_id"
|
41
|
-
|
42
39
|
create_table "blog_posts", force: :cascade do |t|
|
43
40
|
t.datetime "created_at", null: false
|
44
41
|
t.datetime "updated_at", null: false
|
@@ -57,10 +54,9 @@ ActiveRecord::Schema.define(version: 20150610135235) do
|
|
57
54
|
t.integer "blog_post_id", null: false
|
58
55
|
t.text "description"
|
59
56
|
t.text "url"
|
57
|
+
t.index ["blog_post_id"], name: "index_footnotes_on_blog_post_id"
|
60
58
|
end
|
61
59
|
|
62
|
-
add_index "footnotes", ["blog_post_id"], name: "index_footnotes_on_blog_post_id"
|
63
|
-
|
64
60
|
create_table "images", force: :cascade do |t|
|
65
61
|
t.datetime "created_at", null: false
|
66
62
|
t.datetime "updated_at", null: false
|
@@ -78,29 +74,26 @@ ActiveRecord::Schema.define(version: 20150610135235) do
|
|
78
74
|
t.string "slug", null: false
|
79
75
|
t.text "summary", null: false
|
80
76
|
t.text "body"
|
77
|
+
t.index ["slug"], name: "index_legal_pages_on_slug"
|
81
78
|
end
|
82
79
|
|
83
|
-
add_index "legal_pages", ["slug"], name: "index_legal_pages_on_slug"
|
84
|
-
|
85
80
|
create_table "miscellany", force: :cascade do |t|
|
86
81
|
t.datetime "created_at", null: false
|
87
82
|
t.datetime "updated_at", null: false
|
88
83
|
t.string "key", null: false
|
89
84
|
t.text "value", null: false
|
90
85
|
t.text "description", null: false
|
86
|
+
t.index ["key"], name: "index_miscellany_on_key"
|
91
87
|
end
|
92
88
|
|
93
|
-
add_index "miscellany", ["key"], name: "index_miscellany_on_key"
|
94
|
-
|
95
89
|
create_table "topics", force: :cascade do |t|
|
96
90
|
t.datetime "created_at"
|
97
91
|
t.datetime "updated_at"
|
98
92
|
t.string "label", null: false
|
99
93
|
t.string "slug", null: false
|
94
|
+
t.index ["slug"], name: "index_topics_on_slug"
|
100
95
|
end
|
101
96
|
|
102
|
-
add_index "topics", ["slug"], name: "index_topics_on_slug"
|
103
|
-
|
104
97
|
create_table "videos", force: :cascade do |t|
|
105
98
|
t.datetime "created_at", null: false
|
106
99
|
t.datetime "updated_at", null: false
|
@@ -25,7 +25,7 @@ class FilterPreservationTest < ActionDispatch::IntegrationTest
|
|
25
25
|
find_link("Organization").click
|
26
26
|
find_link("Nintendo").click
|
27
27
|
first(".button.-cancel").click
|
28
|
-
assert page.current_url.include?("q[s]=organization+asc"), "filter
|
28
|
+
assert page.current_url.include?("q[s]=organization+asc"), "filter should be retained"
|
29
29
|
end
|
30
30
|
|
31
31
|
test "after filtering index, should retain filter on edit and save" do
|
@@ -58,4 +58,3 @@ class FilterPreservationTest < ActionDispatch::IntegrationTest
|
|
58
58
|
end
|
59
59
|
|
60
60
|
end
|
61
|
-
|
@@ -92,8 +92,8 @@ class ForbiddenRoutesTest < ActionDispatch::IntegrationTest
|
|
92
92
|
assert page.has_content?("Delete")
|
93
93
|
assert page.has_content?("Edit")
|
94
94
|
|
95
|
-
assert_raises
|
96
|
-
visit
|
95
|
+
assert_raises ActionController::RoutingError do
|
96
|
+
visit "/admin/cards"
|
97
97
|
end
|
98
98
|
|
99
99
|
# Unseat the Card class so that it doesn't leak out of this test
|
@@ -102,4 +102,30 @@ class ForbiddenRoutesTest < ActionDispatch::IntegrationTest
|
|
102
102
|
|
103
103
|
end
|
104
104
|
|
105
|
+
test "handles only allowed_actions index, edit, update" do
|
106
|
+
|
107
|
+
# Miscellany only allows index, edit, update
|
108
|
+
Miscellany.create(value:"Tchotchke", key:"tchotchke", description:"Test Tchotchke")
|
109
|
+
|
110
|
+
sign_in_dummy_administrator!
|
111
|
+
visit admin_miscellany_index_path
|
112
|
+
assert page.has_content?("tchotchke"), "should see the Miscellany on the index"
|
113
|
+
|
114
|
+
visit edit_admin_miscellany_path(Miscellany.first.id)
|
115
|
+
assert page.has_content?("Tchotchke"), "can see the Miscellany form"
|
116
|
+
assert page.has_content?("Save"), "can see the Miscellany form"
|
117
|
+
|
118
|
+
assert_raises ActionController::RoutingError do
|
119
|
+
visit "/admin/miscellany/new" # This route shouldn’t exist
|
120
|
+
end
|
121
|
+
|
122
|
+
assert_raises ActionController::RoutingError do
|
123
|
+
visit "/admin/miscellany/1" # This route shouldn’t exist
|
124
|
+
end
|
125
|
+
|
126
|
+
# Remove the test object
|
127
|
+
Miscellany.first.destroy
|
128
|
+
|
129
|
+
end
|
130
|
+
|
105
131
|
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
class PaginationTest < ActionDispatch::IntegrationTest
|
4
|
+
|
5
|
+
def setup
|
6
|
+
BlogPost.destroy_all
|
7
|
+
50.times do
|
8
|
+
BlogPost.create!({
|
9
|
+
title: SecureRandom.uuid,
|
10
|
+
body: "X",
|
11
|
+
summary: "X",
|
12
|
+
published_at: Time.current,
|
13
|
+
})
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def teardown
|
18
|
+
BlogPost.destroy_all
|
19
|
+
end
|
20
|
+
|
21
|
+
test "shows pagination and its usable" do
|
22
|
+
sign_in_dummy_administrator!
|
23
|
+
visit("/admin/blog_posts")
|
24
|
+
assert page.has_content?("Next")
|
25
|
+
assert page.has_content?("Last")
|
26
|
+
assert page.has_content?("3")
|
27
|
+
visit("/admin/blog_posts?p=3")
|
28
|
+
assert page.has_content?("Next")
|
29
|
+
assert page.has_content?("Last")
|
30
|
+
assert page.has_content?("First")
|
31
|
+
assert page.has_content?("Prev")
|
32
|
+
end
|
33
|
+
|
34
|
+
test "after paginating index, should retain page on edit and back with crumb" do
|
35
|
+
sign_in_dummy_administrator!
|
36
|
+
visit("/admin/blog_posts?p=3")
|
37
|
+
first(".button.-edit").click # Open the editor form for a random blog post
|
38
|
+
first(".crumb a").click
|
39
|
+
assert page.current_url.include?("p=3"), "page should be retained"
|
40
|
+
end
|
41
|
+
|
42
|
+
test "after paginating index, should retain page on edit and back with button" do
|
43
|
+
sign_in_dummy_administrator!
|
44
|
+
visit("/admin/blog_posts?p=3")
|
45
|
+
first(".button.-edit").click # Open the editor form for a random blog post
|
46
|
+
first(".button.-cancel").click
|
47
|
+
assert page.current_url.include?("p=3"), "page should be retained"
|
48
|
+
end
|
49
|
+
|
50
|
+
test "after paginating index, should retain page on edit and save" do
|
51
|
+
sign_in_dummy_administrator!
|
52
|
+
visit("/admin/blog_posts?p=3")
|
53
|
+
first(".button.-edit").click # Open the editor form for a random blog post
|
54
|
+
first(".button.-save").click
|
55
|
+
assert page.current_url.include?("p=3"), "page should be retained"
|
56
|
+
end
|
57
|
+
|
58
|
+
test "after paginating index, should retain page on edit and failed validation" do
|
59
|
+
sign_in_dummy_administrator!
|
60
|
+
visit("/admin/blog_posts?p=3")
|
61
|
+
first(".button.-edit").click # Open the editor form for a random blog post
|
62
|
+
fill_in("blog_post[title]", with:"")
|
63
|
+
first(".button.-save").click
|
64
|
+
first(".button.-cancel").click
|
65
|
+
assert page.current_url.include?("p=3"), "page should be retained"
|
66
|
+
end
|
67
|
+
|
68
|
+
test "after paginating index, should NOT retain page on save and review" do
|
69
|
+
sign_in_dummy_administrator!
|
70
|
+
visit("/admin/blog_posts?p=3")
|
71
|
+
first(".button.-edit").click # Open the editor form for a random blog post
|
72
|
+
first(".button.-save-and-review").click
|
73
|
+
assert page.current_url.exclude?("p=3"), "page should not have been retained"
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|