klastera 1.5.3 → 1.5.5
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/MIT-LICENSE +20 -0
- data/README.rdoc +3 -0
- data/Rakefile +37 -0
- data/app/assets/javascripts/klastera/application.js +13 -0
- data/app/assets/javascripts/klastera/clusters.js +2 -0
- data/app/assets/stylesheets/klastera/clusters.scss +46 -0
- data/app/controllers/klastera/application_controller.rb +29 -0
- data/app/controllers/klastera/clusters_controller.rb +60 -0
- data/app/helpers/klastera/application_helper.rb +40 -0
- data/app/models/klastera/cluster.rb +5 -0
- data/app/models/klastera/cluster_entity.rb +5 -0
- data/app/models/klastera/cluster_filter.rb +5 -0
- data/app/models/klastera/cluster_user.rb +5 -0
- data/app/models/klastera/concerns/cluster.rb +67 -0
- data/app/models/klastera/concerns/cluster_entity.rb +18 -0
- data/app/models/klastera/concerns/cluster_filter.rb +22 -0
- data/app/models/klastera/concerns/cluster_user.rb +41 -0
- data/app/models/klastera/concerns/clusterizable.rb +115 -0
- data/app/models/klastera/concerns/organization.rb +49 -0
- data/app/models/klastera/concerns/transfer.rb +45 -0
- data/app/models/klastera/concerns/user.rb +77 -0
- data/app/models/klastera/transfer.rb +5 -0
- data/app/views/klastera/clusters/_filter.html.erb +0 -0
- data/app/views/klastera/clusters/_form.html.erb +22 -0
- data/app/views/klastera/clusters/_form_transfer.html.erb +34 -0
- data/app/views/klastera/clusters/_table.html.erb +33 -0
- data/app/views/klastera/clusters/create.js.erb +1 -0
- data/app/views/klastera/clusters/destroy.js.erb +6 -0
- data/app/views/klastera/clusters/edit.html.erb +10 -0
- data/app/views/klastera/clusters/index.html.erb +21 -0
- data/app/views/klastera/clusters/new.html.erb +10 -0
- data/app/views/klastera/clusters/transfer.html.erb +10 -0
- data/app/views/klastera/clusters/update.js.erb +1 -0
- data/app/views/layouts/klastera/_cluster_entity_fields.html.erb +10 -0
- data/app/views/layouts/klastera/_cluster_filter.html.erb +23 -0
- data/app/views/layouts/klastera/_cluster_role.html.erb +48 -0
- data/app/views/layouts/klastera/_cluster_selector.html.erb +21 -0
- data/app/views/layouts/klastera/_cluster_user_fields.html.erb +10 -0
- data/app/views/layouts/klastera/_nested_cluster_entity.html.erb +43 -0
- data/app/views/layouts/klastera/_nested_cluster_user.html.erb +22 -0
- data/app/views/layouts/klastera/_options.html.erb +21 -0
- data/config/locales/es.yml +96 -0
- data/config/routes.rb +7 -0
- data/db/migrate/20200324203929_create_klastera_clusters.rb +12 -0
- data/db/migrate/20200326111219_add_cluster_options_to_organizations.rb +6 -0
- data/db/migrate/20200330010551_create_klastera_cluster_users.rb +9 -0
- data/db/migrate/20200330221601_add_order_field_to_clusters.rb +5 -0
- data/db/migrate/20200518142609_create_klastera_cluster_entities.rb +8 -0
- data/db/migrate/20200908180057_add_cluster_config_to_organization.rb +5 -0
- data/db/migrate/20220602222332_add_unique_index_to_cluster_entities.rb +5 -0
- data/db/migrate/20250429110829_add_entity_id_index_to_cluster_entities.rb +6 -0
- data/db/migrate/20250429110830_add_entity_id_index_and_entity_type_index_to_cluster_entities.klastera.rb +7 -0
- data/lib/klastera/engine.rb +5 -0
- data/lib/klastera/version.rb +3 -0
- data/lib/klastera.rb +253 -0
- data/lib/tasks/klastera_tasks.rake +32 -0
- data/test/controllers/klastera/clusters_controller_test.rb +52 -0
- data/test/fixtures/klastera/cluster_users.yml +9 -0
- data/test/fixtures/klastera/clusters.yml +11 -0
- data/test/integration/navigation_test.rb +8 -0
- data/test/klastera_test.rb +7 -0
- data/test/models/klastera/cluster_test.rb +9 -0
- data/test/models/klastera/cluster_user_test.rb +9 -0
- data/test/test_helper.rb +21 -0
- metadata +79 -7
@@ -0,0 +1,7 @@
|
|
1
|
+
# This migration comes from klastera (originally 20250429110947)
|
2
|
+
class AddEntityIdIndexAndEntityTypeIndexToClusterEntities < ActiveRecord::Migration[5.2]
|
3
|
+
disable_ddl_transaction!
|
4
|
+
def change
|
5
|
+
add_index :cluster_entities, [:entity_id,:entity_type], algorithm: :concurrently
|
6
|
+
end
|
7
|
+
end
|
data/lib/klastera.rb
ADDED
@@ -0,0 +1,253 @@
|
|
1
|
+
require "klastera/engine"
|
2
|
+
|
3
|
+
module Klastera
|
4
|
+
mattr_accessor :organization_class
|
5
|
+
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
UNCLUSTERED_POSITION = 9999
|
9
|
+
UNCLUSTERED_ENTITY = 'without_cluster'.freeze
|
10
|
+
KLSTR_HELPERS = %i[ cluster_user cluster_organization cluster_list cluster_scope cluster_scope_through_of user_clusters_string_list cluster_scope_left_join ].freeze
|
11
|
+
|
12
|
+
class << self
|
13
|
+
|
14
|
+
##
|
15
|
+
# TODO:
|
16
|
+
# Implement a validation to ensure that
|
17
|
+
# object is a ActiveRecord::Base class
|
18
|
+
# (or just try to guess how to retrieve the argument class)
|
19
|
+
#
|
20
|
+
##
|
21
|
+
def scope_class(object)
|
22
|
+
object
|
23
|
+
end
|
24
|
+
|
25
|
+
##
|
26
|
+
# Returns which clusters a user can see avoiding unnecessary queries if the cluster restraint doesn't apply
|
27
|
+
#
|
28
|
+
def cluster_list!(organization,user,include_unclustered=true)
|
29
|
+
# Only the cluster mode on and the mandatory user-cluster relation will use a join clause to get the clusters list
|
30
|
+
if organization.is_in_cluster_mode? && user.cannot_skip_cluster_clause?
|
31
|
+
active_record_collection = ::ClusterUser.clusters_of(organization,user)
|
32
|
+
else
|
33
|
+
active_record_collection = ::Cluster.where({ organization_id: organization }).order(order: :asc)
|
34
|
+
end
|
35
|
+
|
36
|
+
active_record_collection = active_record_collection.order(order: :asc)
|
37
|
+
|
38
|
+
if include_unclustered && organization.optional_suborganization_mode? # For show and use modes only
|
39
|
+
active_record_collection.to_a.append(
|
40
|
+
::Cluster.new({nid: UNCLUSTERED_ENTITY, name: I18n.t("klastera.#{UNCLUSTERED_ENTITY}"), order: UNCLUSTERED_POSITION })
|
41
|
+
)
|
42
|
+
end
|
43
|
+
active_record_collection
|
44
|
+
end
|
45
|
+
|
46
|
+
##
|
47
|
+
# Return a string with cluster attribute separated by separator argument
|
48
|
+
# A array of cluster ids can be passed fo filter the result
|
49
|
+
# Optimized version that uses preloaded associations when available
|
50
|
+
#
|
51
|
+
def entity_clusters_string_list!(cluster_entities,separator,attribute=:name,allowed_cluster_ids=nil)
|
52
|
+
_cluster_entities = cluster_entities.reject(&:nil?)
|
53
|
+
if allowed_cluster_ids.is_a?(Array)
|
54
|
+
_cluster_entities.select!{|ce| allowed_cluster_ids.include?(ce.cluster_id)}
|
55
|
+
end
|
56
|
+
|
57
|
+
# Performance optimization: Use preloaded data when available
|
58
|
+
if cluster_entities.respond_to?(:loaded?) && cluster_entities.loaded? &&
|
59
|
+
_cluster_entities.all? { |ce| ce.association(:cluster).loaded? }
|
60
|
+
# Use in-memory data (much faster)
|
61
|
+
_cluster_entities.map do |ce|
|
62
|
+
ce.cluster.try(attribute)
|
63
|
+
end.compact.sort.join(separator)
|
64
|
+
else
|
65
|
+
# Fallback to original method with database query
|
66
|
+
# But use a single query instead of N+1
|
67
|
+
cluster_ids = _cluster_entities.map(&:cluster_id).compact.uniq
|
68
|
+
return "" if cluster_ids.empty?
|
69
|
+
|
70
|
+
clusters_hash = ::Cluster.where(id: cluster_ids).pluck(:id, attribute).to_h
|
71
|
+
_cluster_entities.map do |ce|
|
72
|
+
clusters_hash[ce.cluster_id]
|
73
|
+
end.compact.sort.join(separator)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
##
|
78
|
+
# cluster_list! needs a user and a organization. that why we perfomed this logic here
|
79
|
+
#
|
80
|
+
def user_clusters_string_list!(user,organization,cluster_entities,separator,attribute=:name)
|
81
|
+
@clusters_session ||= Klastera.cluster_list!(organization,user)
|
82
|
+
self.entity_clusters_string_list!(cluster_entities, separator, attribute, @clusters_session.map(&:id))
|
83
|
+
end
|
84
|
+
|
85
|
+
#
|
86
|
+
# We will try to avoid cluster clause except when:
|
87
|
+
# 1.- cluster mode is active
|
88
|
+
# AND
|
89
|
+
# 2a.- cluster_filter is present (someone wants to filter by cluster)
|
90
|
+
# OR
|
91
|
+
# 2b.- the current user has some limitations and must checks they cluster relation
|
92
|
+
# - User is having clusters in optional_suborganization mode
|
93
|
+
# - User IS NOT having clusters in required_suborganization mode
|
94
|
+
#
|
95
|
+
# For the other hand, with force_cluster_clause we can skip the previous logic if
|
96
|
+
# cluster_filter_id is present when the optional_suborganization mode is on. BUT!
|
97
|
+
# Be aware that if the cluster_filter is not present, the value of force_cluster_clause
|
98
|
+
# will be overridden by the returned value of cannot_skip_cluster_clause? method.
|
99
|
+
def should_clusterize_scope?(user, organization, cluster_filter=nil, force_cluster_clause=false)
|
100
|
+
should = false # I don't know if this is a good idea
|
101
|
+
if organization.is_in_cluster_mode? && ( cluster_filter.present? || force_cluster_clause = user.cannot_skip_cluster_clause? ) # yes, this is an assignation
|
102
|
+
cluster_ids = []
|
103
|
+
# Set another variable as array to get the cluster id(s)
|
104
|
+
if cluster_filter.present?
|
105
|
+
cluster_ids = cluster_filter.is_a?(Array) ? cluster_filter : [cluster_filter]
|
106
|
+
elsif force_cluster_clause
|
107
|
+
cluster_ids = ::ClusterUser.clusters_of(organization,user).map(&:id)
|
108
|
+
end
|
109
|
+
# We will avoid the query unless cluster_ids is having values OR force_cluster_clause is set (see method description)
|
110
|
+
if cluster_ids.present? || force_cluster_clause
|
111
|
+
# We add the unclustered if the value of cluster_filter have the special without_cluster string or as method description says
|
112
|
+
if cluster_ids.delete(UNCLUSTERED_ENTITY) || ( force_cluster_clause && organization.optional_suborganization_mode? )
|
113
|
+
cluster_ids << nil
|
114
|
+
end
|
115
|
+
should = true
|
116
|
+
end
|
117
|
+
end
|
118
|
+
yield(should,cluster_ids)
|
119
|
+
end
|
120
|
+
|
121
|
+
#
|
122
|
+
# The cleanest and fast way to clusterize a entity!
|
123
|
+
#
|
124
|
+
def cluster_scope!(scope_klass, user, organization, cluster_filter=nil, force_cluster_clause=false)
|
125
|
+
scope = scope_class(scope_klass)
|
126
|
+
should_clusterize_scope?(user,organization,cluster_filter,force_cluster_clause) do |should,cluster_ids|
|
127
|
+
if should
|
128
|
+
scope = scope.eager_load(:organization,cluster_entities: :cluster).where( cluster_entities: { cluster_id: cluster_ids } )
|
129
|
+
end
|
130
|
+
end
|
131
|
+
scope.where(organization_id: organization)
|
132
|
+
end
|
133
|
+
|
134
|
+
#
|
135
|
+
# Filter non-clustered entity through a clusterized one
|
136
|
+
#
|
137
|
+
def cluster_scope_through_of!(relation, cluster_entity_klass, scope_klass, user, organization, cluster_filter=nil, force_cluster_clause=false)
|
138
|
+
unclusterized_scope = scope_class(scope_klass)
|
139
|
+
|
140
|
+
if organization.is_in_cluster_mode? && ( force_cluster_clause || user.cannot_skip_cluster_clause? )
|
141
|
+
unclusterized_scope = unclusterized_scope.joins(relation).joins(Klastera::ClusterEntity.left_join_sources_of(cluster_entity_klass))
|
142
|
+
end
|
143
|
+
|
144
|
+
if scope_klass.respond_to?(:organization)
|
145
|
+
unclusterized_scope = unclusterized_scope.where(organization_id: organization)
|
146
|
+
end
|
147
|
+
|
148
|
+
unclusterized_scope.where("#{relation}_id" => cluster_scope!(cluster_entity_klass, user, organization, cluster_filter, force_cluster_clause))
|
149
|
+
end
|
150
|
+
|
151
|
+
#
|
152
|
+
# Returns an array with a clusterized scoped result and its grouped version
|
153
|
+
#
|
154
|
+
def group_by_cluster_scope!(scope_klass, user, organization, cluster_filter=[], scope_scopes=[])
|
155
|
+
cluster_ids = cluster_filter.is_a?(Array) ? cluster_filter : [cluster_filter]
|
156
|
+
kluster_scope = cluster_scope!(scope_klass, user, organization, cluster_ids.compact, organization.is_in_cluster_mode? )
|
157
|
+
|
158
|
+
scope_scopes.each do |tuple_scope|
|
159
|
+
scope_name, scope_arg = tuple_scope
|
160
|
+
kluster_scope = scope_arg.present? ? kluster_scope.send(scope_name,scope_arg) : kluster_scope.send(scope_name)
|
161
|
+
end
|
162
|
+
|
163
|
+
group_by_block = ->(o) {
|
164
|
+
if organization.is_in_cluster_mode?
|
165
|
+
o.cluster.present? ? o.cluster.name : UNCLUSTERED_POSITION
|
166
|
+
else
|
167
|
+
I18n.t("klastera.group_by_cluster_scope.#{scope_klass.model_name.plural}")
|
168
|
+
end
|
169
|
+
}
|
170
|
+
|
171
|
+
grouped_cluster_scope = kluster_scope.group_by(&group_by_block).sort_by{|k,v|k.to_s}
|
172
|
+
|
173
|
+
grouped_cluster_scope.dup.each do |group|
|
174
|
+
if group.first == UNCLUSTERED_POSITION
|
175
|
+
grouped_cluster_scope.delete(group)
|
176
|
+
group[0] = I18n.t("klastera.#{UNCLUSTERED_ENTITY}")
|
177
|
+
grouped_cluster_scope.append(group)
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
[ kluster_scope, grouped_cluster_scope ]
|
182
|
+
end
|
183
|
+
|
184
|
+
#
|
185
|
+
# A helper that returns a CLUSTER SCOPE to build queries that need explicit LEFT OUTER JOIN clause,
|
186
|
+
# instead of the default INNER JOIN provide by ActiveRecord's joins method
|
187
|
+
#
|
188
|
+
def cluster_scope_left_join!(scope_klass,organization)
|
189
|
+
cluster_entities_arel_table = Klastera::ClusterEntity.arel_table
|
190
|
+
cluster_arel_table = ::Cluster.arel_table
|
191
|
+
cluster_entities_cluster = cluster_entities_arel_table.join(cluster_arel_table, Arel::Nodes::OuterJoin).on(
|
192
|
+
cluster_entities_arel_table[:cluster_id].eq(cluster_arel_table[:id]),
|
193
|
+
).join_sources
|
194
|
+
|
195
|
+
scope_class(scope_klass).where(organization_id: organization).joins(Klastera::ClusterEntity.left_join_sources_of(scope_klass)).joins(cluster_entities_cluster)
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
##################################################################################################################################################
|
200
|
+
|
201
|
+
def cluster_user
|
202
|
+
current_user
|
203
|
+
end
|
204
|
+
|
205
|
+
def cluster_organization
|
206
|
+
current_organization
|
207
|
+
end
|
208
|
+
|
209
|
+
def set_cluster_filter
|
210
|
+
cluster_filter_params = params.require(:cluster_filter) rescue {}
|
211
|
+
@cluster_filter = ::ClusterFilter.new(
|
212
|
+
cluster_filter_params.present? ? cluster_filter_params.permit(
|
213
|
+
[ :cluster_id ].concat( ::ClusterFilter.attributes )
|
214
|
+
) : {}
|
215
|
+
)
|
216
|
+
end
|
217
|
+
|
218
|
+
def cluster_list(include_unclustered=true)
|
219
|
+
Klastera.cluster_list!(cluster_organization, cluster_user, include_unclustered)
|
220
|
+
end
|
221
|
+
|
222
|
+
def cluster_scope(scope_klass, cluster_filter=nil, force_cluster_clause=false)
|
223
|
+
Klastera.cluster_scope!(scope_klass, cluster_user, cluster_organization, cluster_filter, force_cluster_clause)
|
224
|
+
end
|
225
|
+
|
226
|
+
def cluster_scope_through_of(relation, cluster_entity_klass, scope_klass, cluster_filter=nil, force_cluster_clause=false)
|
227
|
+
Klastera.cluster_scope_through_of!(relation, cluster_entity_klass, scope_klass, cluster_user, cluster_organization, cluster_filter, force_cluster_clause)
|
228
|
+
end
|
229
|
+
|
230
|
+
def group_by_cluster_scope(scope_klass, cluster_filter=[], scope_scopes=[])
|
231
|
+
Klastera.group_by_cluster_scope!(scope_klass, cluster_user, cluster_organization, cluster_filter, scope_scopes)
|
232
|
+
end
|
233
|
+
|
234
|
+
def user_clusters_string_list(object_entity, separator, attribute=:name)
|
235
|
+
Klastera.user_clusters_string_list!(cluster_user, cluster_organization, object_entity.try(:cluster_entities), separator, attribute)
|
236
|
+
end
|
237
|
+
|
238
|
+
def cluster_scope_left_join(scope_klass)
|
239
|
+
Klastera.cluster_scope_left_join!(scope_klas,cluster_organization)
|
240
|
+
end
|
241
|
+
|
242
|
+
included do
|
243
|
+
Klastera::KLSTR_HELPERS.each do |action|
|
244
|
+
if respond_to?(:helper_method)
|
245
|
+
helper_method(action)
|
246
|
+
end
|
247
|
+
if respond_to?(:hide_action)
|
248
|
+
hide_action(helper)
|
249
|
+
hide_action("#{helper}=")
|
250
|
+
end
|
251
|
+
end
|
252
|
+
end
|
253
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# desc "Explaining what the task does"
|
2
|
+
# task :klastera do
|
3
|
+
# # Task goes here
|
4
|
+
# end
|
5
|
+
|
6
|
+
|
7
|
+
namespace :klastera do
|
8
|
+
namespace :seed do
|
9
|
+
|
10
|
+
desc "Move cluster_id to cluster_entities"
|
11
|
+
task :cluster_entities, [:entity] => :environment do |task,args|
|
12
|
+
begin
|
13
|
+
klass = args.entity.constantize
|
14
|
+
ActiveRecord::Base.transaction do
|
15
|
+
klass.where.not(cluster_id: nil).each do |entity|
|
16
|
+
if entity.cluster.blank?
|
17
|
+
puts "Cluster ID #{entity.cluster_id} was not found!"
|
18
|
+
puts "skip..."
|
19
|
+
next
|
20
|
+
end
|
21
|
+
Klastera::ClusterEntity.create(entity: entity, cluster: entity.cluster)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
rescue NameError => ne
|
25
|
+
puts "NameError Exception: #{ne}"
|
26
|
+
rescue ActiveRecord::StatementInvalid => asi
|
27
|
+
puts "ActiveRecord::StatementInvalid Exception #{asi}"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module Klastera
|
4
|
+
class ClustersControllerTest < ActionController::TestCase
|
5
|
+
setup do
|
6
|
+
@cluster = klastera_clusters(:one)
|
7
|
+
@routes = Engine.routes
|
8
|
+
end
|
9
|
+
|
10
|
+
test "should get index" do
|
11
|
+
get :index
|
12
|
+
assert_response :success
|
13
|
+
assert_not_nil assigns(:clusters)
|
14
|
+
end
|
15
|
+
|
16
|
+
test "should get new" do
|
17
|
+
get :new
|
18
|
+
assert_response :success
|
19
|
+
end
|
20
|
+
|
21
|
+
test "should create cluster" do
|
22
|
+
assert_difference('Cluster.count') do
|
23
|
+
post :create, cluster: { color: @cluster.color, name: @cluster.name, nid: @cluster.nid }
|
24
|
+
end
|
25
|
+
|
26
|
+
assert_redirected_to cluster_path(assigns(:cluster))
|
27
|
+
end
|
28
|
+
|
29
|
+
test "should show cluster" do
|
30
|
+
get :show, id: @cluster
|
31
|
+
assert_response :success
|
32
|
+
end
|
33
|
+
|
34
|
+
test "should get edit" do
|
35
|
+
get :edit, id: @cluster
|
36
|
+
assert_response :success
|
37
|
+
end
|
38
|
+
|
39
|
+
test "should update cluster" do
|
40
|
+
patch :update, id: @cluster, cluster: { color: @cluster.color, name: @cluster.name, nid: @cluster.nid }
|
41
|
+
assert_redirected_to cluster_path(assigns(:cluster))
|
42
|
+
end
|
43
|
+
|
44
|
+
test "should destroy cluster" do
|
45
|
+
assert_difference('Cluster.count', -1) do
|
46
|
+
delete :destroy, id: @cluster
|
47
|
+
end
|
48
|
+
|
49
|
+
assert_redirected_to clusters_path
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# Configure Rails Environment
|
2
|
+
ENV["RAILS_ENV"] = "test"
|
3
|
+
|
4
|
+
require File.expand_path("../../test/dummy/config/environment.rb", __FILE__)
|
5
|
+
ActiveRecord::Migrator.migrations_paths = [File.expand_path("../../test/dummy/db/migrate", __FILE__)]
|
6
|
+
ActiveRecord::Migrator.migrations_paths << File.expand_path('../../db/migrate', __FILE__)
|
7
|
+
require "rails/test_help"
|
8
|
+
|
9
|
+
# Filter out Minitest backtrace while allowing backtrace from other libraries
|
10
|
+
# to be shown.
|
11
|
+
Minitest.backtrace_filter = Minitest::BacktraceFilter.new
|
12
|
+
|
13
|
+
# Load support files
|
14
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
|
15
|
+
|
16
|
+
# Load fixtures from the engine
|
17
|
+
if ActiveSupport::TestCase.respond_to?(:fixture_path=)
|
18
|
+
ActiveSupport::TestCase.fixture_path = File.expand_path("../fixtures", __FILE__)
|
19
|
+
ActionDispatch::IntegrationTest.fixture_path = ActiveSupport::TestCase.fixture_path
|
20
|
+
ActiveSupport::TestCase.fixtures :all
|
21
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: klastera
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.5.
|
4
|
+
version: 1.5.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Gino Barahona
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2025-06-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: 5.2.6
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
26
|
+
version: 5.2.6
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: pg
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -44,7 +44,71 @@ email:
|
|
44
44
|
executables: []
|
45
45
|
extensions: []
|
46
46
|
extra_rdoc_files: []
|
47
|
-
files:
|
47
|
+
files:
|
48
|
+
- MIT-LICENSE
|
49
|
+
- README.rdoc
|
50
|
+
- Rakefile
|
51
|
+
- app/assets/javascripts/klastera/application.js
|
52
|
+
- app/assets/javascripts/klastera/clusters.js
|
53
|
+
- app/assets/stylesheets/klastera/clusters.scss
|
54
|
+
- app/controllers/klastera/application_controller.rb
|
55
|
+
- app/controllers/klastera/clusters_controller.rb
|
56
|
+
- app/helpers/klastera/application_helper.rb
|
57
|
+
- app/models/klastera/cluster.rb
|
58
|
+
- app/models/klastera/cluster_entity.rb
|
59
|
+
- app/models/klastera/cluster_filter.rb
|
60
|
+
- app/models/klastera/cluster_user.rb
|
61
|
+
- app/models/klastera/concerns/cluster.rb
|
62
|
+
- app/models/klastera/concerns/cluster_entity.rb
|
63
|
+
- app/models/klastera/concerns/cluster_filter.rb
|
64
|
+
- app/models/klastera/concerns/cluster_user.rb
|
65
|
+
- app/models/klastera/concerns/clusterizable.rb
|
66
|
+
- app/models/klastera/concerns/organization.rb
|
67
|
+
- app/models/klastera/concerns/transfer.rb
|
68
|
+
- app/models/klastera/concerns/user.rb
|
69
|
+
- app/models/klastera/transfer.rb
|
70
|
+
- app/views/klastera/clusters/_filter.html.erb
|
71
|
+
- app/views/klastera/clusters/_form.html.erb
|
72
|
+
- app/views/klastera/clusters/_form_transfer.html.erb
|
73
|
+
- app/views/klastera/clusters/_table.html.erb
|
74
|
+
- app/views/klastera/clusters/create.js.erb
|
75
|
+
- app/views/klastera/clusters/destroy.js.erb
|
76
|
+
- app/views/klastera/clusters/edit.html.erb
|
77
|
+
- app/views/klastera/clusters/index.html.erb
|
78
|
+
- app/views/klastera/clusters/new.html.erb
|
79
|
+
- app/views/klastera/clusters/transfer.html.erb
|
80
|
+
- app/views/klastera/clusters/update.js.erb
|
81
|
+
- app/views/layouts/klastera/_cluster_entity_fields.html.erb
|
82
|
+
- app/views/layouts/klastera/_cluster_filter.html.erb
|
83
|
+
- app/views/layouts/klastera/_cluster_role.html.erb
|
84
|
+
- app/views/layouts/klastera/_cluster_selector.html.erb
|
85
|
+
- app/views/layouts/klastera/_cluster_user_fields.html.erb
|
86
|
+
- app/views/layouts/klastera/_nested_cluster_entity.html.erb
|
87
|
+
- app/views/layouts/klastera/_nested_cluster_user.html.erb
|
88
|
+
- app/views/layouts/klastera/_options.html.erb
|
89
|
+
- config/locales/es.yml
|
90
|
+
- config/routes.rb
|
91
|
+
- db/migrate/20200324203929_create_klastera_clusters.rb
|
92
|
+
- db/migrate/20200326111219_add_cluster_options_to_organizations.rb
|
93
|
+
- db/migrate/20200330010551_create_klastera_cluster_users.rb
|
94
|
+
- db/migrate/20200330221601_add_order_field_to_clusters.rb
|
95
|
+
- db/migrate/20200518142609_create_klastera_cluster_entities.rb
|
96
|
+
- db/migrate/20200908180057_add_cluster_config_to_organization.rb
|
97
|
+
- db/migrate/20220602222332_add_unique_index_to_cluster_entities.rb
|
98
|
+
- db/migrate/20250429110829_add_entity_id_index_to_cluster_entities.rb
|
99
|
+
- db/migrate/20250429110830_add_entity_id_index_and_entity_type_index_to_cluster_entities.klastera.rb
|
100
|
+
- lib/klastera.rb
|
101
|
+
- lib/klastera/engine.rb
|
102
|
+
- lib/klastera/version.rb
|
103
|
+
- lib/tasks/klastera_tasks.rake
|
104
|
+
- test/controllers/klastera/clusters_controller_test.rb
|
105
|
+
- test/fixtures/klastera/cluster_users.yml
|
106
|
+
- test/fixtures/klastera/clusters.yml
|
107
|
+
- test/integration/navigation_test.rb
|
108
|
+
- test/klastera_test.rb
|
109
|
+
- test/models/klastera/cluster_test.rb
|
110
|
+
- test/models/klastera/cluster_user_test.rb
|
111
|
+
- test/test_helper.rb
|
48
112
|
homepage: https://github.com/ginosx/klastera
|
49
113
|
licenses:
|
50
114
|
- MIT
|
@@ -64,8 +128,16 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
64
128
|
- !ruby/object:Gem::Version
|
65
129
|
version: '0'
|
66
130
|
requirements: []
|
67
|
-
rubygems_version: 3.
|
131
|
+
rubygems_version: 3.4.10
|
68
132
|
signing_key:
|
69
133
|
specification_version: 4
|
70
134
|
summary: Clusterization Engine
|
71
|
-
test_files:
|
135
|
+
test_files:
|
136
|
+
- test/controllers/klastera/clusters_controller_test.rb
|
137
|
+
- test/fixtures/klastera/cluster_users.yml
|
138
|
+
- test/fixtures/klastera/clusters.yml
|
139
|
+
- test/integration/navigation_test.rb
|
140
|
+
- test/klastera_test.rb
|
141
|
+
- test/models/klastera/cluster_test.rb
|
142
|
+
- test/models/klastera/cluster_user_test.rb
|
143
|
+
- test/test_helper.rb
|