klastera 1.1.4 → 1.2.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/stylesheets/klastera/clusters.css.scss +11 -0
- data/app/models/klastera/cluster_entity.rb +5 -0
- data/app/models/klastera/concerns/cluster_entity.rb +12 -0
- data/app/models/klastera/concerns/cluster_user.rb +38 -1
- data/app/models/klastera/concerns/clusterizable.rb +28 -3
- data/app/models/klastera/concerns/user.rb +23 -2
- data/app/views/layouts/klastera/_cluster_entity_fields.html.erb +10 -0
- data/app/views/layouts/klastera/_cluster_filter.html.erb +1 -1
- data/app/views/layouts/klastera/_cluster_selector.html.erb +1 -1
- data/app/views/layouts/klastera/_cluster_user_fields.html.erb +2 -2
- data/app/views/layouts/klastera/_nested_cluster_entity.html.erb +41 -0
- data/app/views/layouts/klastera/_nested_cluster_user.html.erb +18 -16
- data/app/views/layouts/klastera/_options.html.erb +1 -1
- data/config/locales/es.yml +2 -0
- data/db/migrate/20200518142609_create_klastera_cluster_entities.rb +8 -0
- data/lib/klastera.rb +114 -34
- data/lib/klastera/version.rb +2 -2
- data/lib/tasks/klastera_tasks.rake +23 -0
- metadata +9 -76
- data/app/assets/stylesheets/klastera/application.css +0 -15
- data/app/assets/stylesheets/klastera/clusters.css +0 -4
- data/app/assets/stylesheets/scaffold.css +0 -56
- data/test/dummy/README.rdoc +0 -28
- data/test/dummy/Rakefile +0 -6
- data/test/dummy/app/assets/javascripts/application.js +0 -13
- data/test/dummy/app/assets/stylesheets/application.css +0 -15
- data/test/dummy/app/controllers/application_controller.rb +0 -5
- data/test/dummy/app/helpers/application_helper.rb +0 -2
- data/test/dummy/app/views/layouts/application.html.erb +0 -14
- data/test/dummy/bin/bundle +0 -3
- data/test/dummy/bin/rails +0 -4
- data/test/dummy/bin/rake +0 -4
- data/test/dummy/bin/setup +0 -29
- data/test/dummy/config.ru +0 -4
- data/test/dummy/config/application.rb +0 -26
- data/test/dummy/config/boot.rb +0 -5
- data/test/dummy/config/database.yml +0 -1
- data/test/dummy/config/environment.rb +0 -5
- data/test/dummy/config/environments/development.rb +0 -41
- data/test/dummy/config/environments/production.rb +0 -79
- data/test/dummy/config/environments/test.rb +0 -42
- data/test/dummy/config/initializers/assets.rb +0 -11
- data/test/dummy/config/initializers/backtrace_silencers.rb +0 -7
- data/test/dummy/config/initializers/cookies_serializer.rb +0 -3
- data/test/dummy/config/initializers/filter_parameter_logging.rb +0 -4
- data/test/dummy/config/initializers/inflections.rb +0 -16
- data/test/dummy/config/initializers/mime_types.rb +0 -4
- data/test/dummy/config/initializers/session_store.rb +0 -3
- data/test/dummy/config/initializers/to_time_preserves_timezone.rb +0 -10
- data/test/dummy/config/initializers/wrap_parameters.rb +0 -14
- data/test/dummy/config/locales/en.yml +0 -23
- data/test/dummy/config/routes.rb +0 -4
- data/test/dummy/config/secrets.yml +0 -22
- data/test/dummy/public/404.html +0 -67
- data/test/dummy/public/422.html +0 -67
- data/test/dummy/public/500.html +0 -66
- data/test/dummy/public/favicon.ico +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ae9963c78d2880fca43b1fd6bef6be6c7ebcdd957289dd1117d81b815fdef707
|
4
|
+
data.tar.gz: 3ae1a3a37239c56675aaa9b9c82cfd65f6262777746bf6e720465c62e66af069
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ed36fabfe91b44b8d8209a1484081021be21cb0309bfd8731cd1380aa6dcf210464f0e1e6cd5dbba218691cbae023223160ee287d6b698ce99756bc452e4c563
|
7
|
+
data.tar.gz: 62ce187ce73ebf4bf07e045835a1f3c79a0c2a911c0f45c54d980938851afdf38dfe8f632641f0b6da40b5c62e82d03cf7d0286b321fed90c3873c267cce2574
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module Klastera::Concerns::ClusterEntity
|
2
|
+
extend ActiveSupport::Concern
|
3
|
+
|
4
|
+
included do
|
5
|
+
self.table_name = 'cluster_entities'
|
6
|
+
belongs_to :entity, polymorphic: true
|
7
|
+
belongs_to :cluster, class_name: ::Cluster
|
8
|
+
end
|
9
|
+
|
10
|
+
module ClassMethods
|
11
|
+
end
|
12
|
+
end
|
@@ -7,14 +7,51 @@ module Klastera::Concerns::ClusterUser
|
|
7
7
|
belongs_to :user
|
8
8
|
belongs_to :cluster
|
9
9
|
|
10
|
-
validates :user_id, presence: true
|
11
10
|
validates :cluster_id, presence: true
|
12
11
|
|
13
12
|
scope :of, -> (user,organization) {
|
13
|
+
Rails.logger.warn("DON'T USE THIS SCOPE DIRECTLY: Use ::ClusterUser.clusters_from class method instead!")
|
14
14
|
includes(:cluster).where(user_id: user, "clusters.organization_id": organization)
|
15
15
|
}
|
16
16
|
end
|
17
17
|
|
18
18
|
module ClassMethods
|
19
|
+
|
20
|
+
##
|
21
|
+
# Returns a hash with the users with cluster relation
|
22
|
+
#
|
23
|
+
def user_clusters_from(organization)
|
24
|
+
users_hash = {}
|
25
|
+
organization_cluster_ids = ::Cluster.of(organization).map(&:id)
|
26
|
+
::ClusterUser.includes(:user).where(cluster_id: organization_cluster_ids).each do |cluster_user|
|
27
|
+
user_id = cluster_user.user_id || :uncluster
|
28
|
+
users_hash[user_id] ||= []
|
29
|
+
users_hash[user_id] << cluster_user.cluster_id
|
30
|
+
end
|
31
|
+
users_hash
|
32
|
+
end
|
33
|
+
|
34
|
+
##
|
35
|
+
# Returns a Cluster::ActiveRecord_Relation
|
36
|
+
#
|
37
|
+
##
|
38
|
+
def clusters_from(user,organization)
|
39
|
+
clusters = []
|
40
|
+
unless user.can_admin_clusters?
|
41
|
+
# We could return cu.clusters but you may quering this result and a array can't handle order, where and etc.
|
42
|
+
# So we take only the cluster_ids and perfome a new search in order to get a Cluster::ActiveRecord_Relation
|
43
|
+
# like the else block.
|
44
|
+
# TODO: resolve it without quering twice
|
45
|
+
clusters_id = ::ClusterUser.of(user,organization).map(&:cluster_id)
|
46
|
+
clusters = ::Cluster.where(id: clusters_id)
|
47
|
+
# Add a empty cluster instance to handle models without a cluster assignation. Only for use and show modes
|
48
|
+
if organization.optional_mode?
|
49
|
+
clusters << ::Cluster.new({nid: :without_cluster, name: I18n.t('klastera.without_cluster')})
|
50
|
+
end
|
51
|
+
else
|
52
|
+
clusters = ::Cluster.of(organization)
|
53
|
+
end
|
54
|
+
clusters
|
55
|
+
end
|
19
56
|
end
|
20
57
|
end
|
@@ -3,12 +3,37 @@ module Klastera::Concerns::Clusterizable
|
|
3
3
|
included do
|
4
4
|
attr_accessor :lonely_cluster
|
5
5
|
belongs_to :cluster
|
6
|
-
|
6
|
+
|
7
|
+
has_many :cluster_entities, as: :entity, class_name: Klastera::ClusterEntity
|
8
|
+
accepts_nested_attributes_for :cluster_entities, reject_if: :all_blank, allow_destroy: true
|
9
|
+
|
10
|
+
validates :cluster_id, presence: true, if: proc { self.try(:cluster_id) && self.organization.required_suborganization_mode? }
|
11
|
+
validate :at_least_one_cluster_entity, if: proc { self.organization.required_suborganization_mode? }
|
12
|
+
|
13
|
+
scope :related_clusters, ->() {
|
14
|
+
includes(:cluster_entities).where("cluster_entities.entity_id = #{self.table_name}.id")
|
15
|
+
}
|
16
|
+
|
17
|
+
def at_least_one_cluster_entity
|
18
|
+
if cluster_entities.length == 0 || cluster_entities.reject{|cluster_entity| cluster_entity._destroy == true}.empty?
|
19
|
+
return errors.add(:cluster_entities, I18n.t('klastera.messages.at_least_one_cluster_entity'))
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def clusters_string_separated_by(separator)
|
24
|
+
self.cluster_entities.map{|ce|ce.cluster.name}.join(separator)
|
25
|
+
end
|
26
|
+
|
27
|
+
def has_one_cluster_entity
|
28
|
+
if cluster_entities.length > 1
|
29
|
+
return errors.add(:cluster_entities, I18n.t('klastera.messages.has_one_cluster_entity'))
|
30
|
+
end
|
31
|
+
end
|
7
32
|
end
|
8
33
|
|
9
34
|
module ClassMethods
|
10
|
-
def
|
11
|
-
[ :cluster_id, :lonely_cluster ]
|
35
|
+
def cluster_entity_params
|
36
|
+
[ :cluster_id, :lonely_cluster, { cluster_entities_attributes: [:id, :cluster_id, :_destroy] } ]
|
12
37
|
end
|
13
38
|
end
|
14
39
|
end
|
@@ -14,8 +14,6 @@ module Klastera::Concerns::User
|
|
14
14
|
validates :cluster_role, presence: true, if: proc{ self.organization.is_in_cluster_mode? }
|
15
15
|
validates :cluster_role, inclusion: { in: CLUSTER_ROLES , message: I18n.t('klastera.clusters.wrong_option') }, if: proc{ cluster_role.present? }
|
16
16
|
validate :at_least_one_role, if: proc{ self.use_cluster? && self.try(:need_cluster_assignation?) }
|
17
|
-
before_destroy do |record|
|
18
|
-
end
|
19
17
|
|
20
18
|
def use_cluster?; self.cluster_role.present?; end
|
21
19
|
|
@@ -35,6 +33,29 @@ module Klastera::Concerns::User
|
|
35
33
|
self.organization.is_in_cluster_mode? && ( self.is_a_cluster_admin? || self.is_a_cluster_root? )
|
36
34
|
end
|
37
35
|
|
36
|
+
#
|
37
|
+
# We will try to create a cluster_user record whether
|
38
|
+
# the organization is using force mode (if cluster_id isn't present, it will raise a validation error)
|
39
|
+
# or
|
40
|
+
# cluster_id is present (on show/use mode organizations).
|
41
|
+
#
|
42
|
+
def try_to_clusterify!(role,cluster_ids)
|
43
|
+
if self.try(:organization).try(:is_in_cluster_mode?)
|
44
|
+
self.cluster_role = role
|
45
|
+
if self.try(:organization).try(:required_suborganization_mode?) || cluster_ids.present?
|
46
|
+
timestamp = DateTime.now.to_i
|
47
|
+
nested_attributes = {}
|
48
|
+
cluster_ids.each do |cluster_id|
|
49
|
+
nested_attributes["#{cluster_id}_#{timestamp}"] = {
|
50
|
+
cluster_id: cluster_id,
|
51
|
+
_destroy: false
|
52
|
+
}
|
53
|
+
end
|
54
|
+
self.cluster_users_attributes = nested_attributes
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
38
59
|
private
|
39
60
|
|
40
61
|
def at_least_one_role
|
@@ -0,0 +1,10 @@
|
|
1
|
+
<tr class="nested-fields">
|
2
|
+
<td class="field">
|
3
|
+
<%= f.select :cluster_id, cluster_clusters.map{|c|[c.name,c.id]}, { include_blank: true }, { class: 'form-control' } %>
|
4
|
+
</td>
|
5
|
+
<td class="action vertical-align-middle text-center" width="44">
|
6
|
+
<%= link_to_remove_association f, class: 'btn btn-danger btn-xs text-danger' do %>
|
7
|
+
<i class="fa fa-trash"></i>
|
8
|
+
<% end %>
|
9
|
+
</td>
|
10
|
+
</tr>
|
@@ -4,7 +4,7 @@
|
|
4
4
|
<%= button_tag(t('klastera.actions.filter'), class: 'btn btn-primary btn-sm float-right', data: { disable_with: "<i class='fa fa-spinner spin'></i>" }) %>
|
5
5
|
</div>
|
6
6
|
|
7
|
-
<%=yield(f)%>
|
7
|
+
<%=yield(f) if block_given? %>
|
8
8
|
|
9
9
|
<% if cluster_organization.is_in_cluster_mode? %>
|
10
10
|
<% cluster_collection = cluster_clusters.map{|c|[c.name,(c.id||c.nid)]} %>
|
@@ -1,8 +1,8 @@
|
|
1
1
|
<tr class="nested-fields">
|
2
2
|
<td class="field">
|
3
3
|
<%= f.select :cluster_id, @user.organization.clusters.map{|c|[c.name,c.id]}, { include_blank: true }, { class: 'form-control' } %>
|
4
|
-
|
5
|
-
<td class="action vertical-align-middle" width="44">
|
4
|
+
</td>
|
5
|
+
<td class="action vertical-align-middle text-center" width="44">
|
6
6
|
<%= link_to_remove_association f, class: 'btn btn-danger btn-xs text-danger' do %>
|
7
7
|
<i class="fa fa-trash"></i>
|
8
8
|
<% end %>
|
@@ -0,0 +1,41 @@
|
|
1
|
+
<% if cluster_organization.is_in_cluster_mode? %>
|
2
|
+
<div class="col-xs-12">
|
3
|
+
<% if hide_title||=false %>
|
4
|
+
<div class="form-group file required <%=f.object.class.name.parameterize%>_cluster_entity<%=' has-error' if f.object.errors.has_key?(:cluster_entities)%>">
|
5
|
+
<label class="text" for="<%=f.object.class.name.parameterize%>_cluster_entity">
|
6
|
+
<%=t('klastera.clusters.title')%>
|
7
|
+
<% if cluster_organization.required_suborganization_mode? %>
|
8
|
+
<abbr title="required">*</abbr>
|
9
|
+
<% end %>
|
10
|
+
</label>
|
11
|
+
<% end %>
|
12
|
+
|
13
|
+
<div class="nested-cluster-entity">
|
14
|
+
<div class="panel panel-default">
|
15
|
+
<div class="panel-heading<%=' custom-required' if cluster_organization.required_suborganization_mode? %>">
|
16
|
+
<h4 class="panel-title">
|
17
|
+
<% unless hide_title||=false %>
|
18
|
+
<div class="float-left" style="line-height: 20px"><%=t('klastera.clusters.title')%></div>
|
19
|
+
<% end %>
|
20
|
+
<%= link_to_add_association f, :cluster_entities, partial: 'layouts/klastera/cluster_entity_fields', data: { 'association-insertion-node': :'tbody.cluster-entity-rows', 'association-insertion-method': :append }, class: 'btn btn-success btn-xs float-right color-white' do %>
|
21
|
+
<i class="fa fa-plus"></i>
|
22
|
+
<% end %>
|
23
|
+
<div class="clearfix"></div>
|
24
|
+
</h4>
|
25
|
+
</div>
|
26
|
+
<table id="cluster-entities" class="table table-striped">
|
27
|
+
<tbody class="cluster-entity-rows">
|
28
|
+
<%= f.fields_for :cluster_entities do |cluster_entity|%>
|
29
|
+
<%= render 'layouts/klastera/cluster_entity_fields', f: cluster_entity %>
|
30
|
+
<% end %>
|
31
|
+
</body>
|
32
|
+
</table>
|
33
|
+
</div>
|
34
|
+
</div>
|
35
|
+
|
36
|
+
<% if hide_title||=false %>
|
37
|
+
<div class="invalid-feedback"><%=f.object.try(:errors)&.[](:cluster_entities).try(:first)%></div>
|
38
|
+
</div>
|
39
|
+
<% end %>
|
40
|
+
</div>
|
41
|
+
<% end %>
|
@@ -1,20 +1,22 @@
|
|
1
1
|
<% if @user.try(:is_a_cluster_user?) %>
|
2
|
-
<div class="
|
3
|
-
<div class="panel-
|
4
|
-
<
|
5
|
-
<
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
2
|
+
<div class="nested-cluster-user">
|
3
|
+
<div class="panel panel-default">
|
4
|
+
<div class="panel-heading">
|
5
|
+
<h4 class="panel-title">
|
6
|
+
<div class="float-left" style="line-height: 20px"><%=t('klastera.clusters.title')%></div>
|
7
|
+
<%= link_to_add_association f, :cluster_users, partial: 'layouts/klastera/cluster_user_fields', data: { 'association-insertion-node': :'tbody.cluster-user-rows', 'association-insertion-method': :append }, class: 'btn btn-success btn-xs float-right color-white' do %>
|
8
|
+
<i class="fa fa-plus"></i>
|
9
|
+
<% end %>
|
10
|
+
<div class="clearfix"></div>
|
11
|
+
</h4>
|
12
|
+
</div>
|
13
|
+
<table id="cluster-users" class="table table-striped">
|
14
|
+
<tbody class="cluster-user-rows">
|
15
|
+
<%= f.fields_for :cluster_users do |cluster_user|%>
|
16
|
+
<%= render 'layouts/klastera/cluster_user_fields', f: cluster_user %>
|
17
|
+
<% end %>
|
18
|
+
</body>
|
19
|
+
</table>
|
11
20
|
</div>
|
12
|
-
<table id="cluster-users" class="table">
|
13
|
-
<tbody class="cluster-user-rows">
|
14
|
-
<%= f.fields_for :cluster_users do |cluster_user|%>
|
15
|
-
<%= render 'layouts/klastera/cluster_user_fields', f: cluster_user %>
|
16
|
-
<% end %>
|
17
|
-
</body>
|
18
|
-
</table>
|
19
21
|
</div>
|
20
22
|
<% end %>
|
@@ -13,7 +13,7 @@
|
|
13
13
|
>
|
14
14
|
<%= fa_icon 'info-circle', class: 'btn-link' %>
|
15
15
|
</span>
|
16
|
-
<%= f.select :use_cluster_as, Cluster::MODES.map{|cm|[t("klastera.#{cm}"),cm]}, { include_blank: true }, { class: 'form-control' } %>
|
16
|
+
<%= f.select :use_cluster_as, ::Cluster::MODES.map{|cm|[t("klastera.#{cm}"),cm]}, { include_blank: true }, { class: 'form-control' } %>
|
17
17
|
</div>
|
18
18
|
|
19
19
|
<script type="text/javascript">
|
data/config/locales/es.yml
CHANGED
@@ -57,6 +57,8 @@ es:
|
|
57
57
|
created: Creado
|
58
58
|
updated: Actualizado
|
59
59
|
messages:
|
60
|
+
has_one_cluster_entity: Está permitido agregar un sólo cluster
|
61
|
+
at_least_one_cluster_entity: Debe agregar al menos un cluster
|
60
62
|
record_action_successfully: Registro %{a} exitosamente
|
61
63
|
cant_delete_the_last_record_in_required_suborganization_mode: No se puede eliminar el único cluster de esta organización
|
62
64
|
new_cluster_id:
|
data/lib/klastera.rb
CHANGED
@@ -3,29 +3,92 @@ require "klastera/engine"
|
|
3
3
|
module Klastera
|
4
4
|
mattr_accessor :organization_class
|
5
5
|
|
6
|
-
class RelatedClusterEntityComplianceError < StandardError; end
|
7
6
|
extend ActiveSupport::Concern
|
8
7
|
|
9
8
|
class << self
|
10
|
-
def cluster_scope!(user,organization,scope,includes=[])
|
11
|
-
scope_klass = scope_class(scope)
|
12
|
-
raise RelatedClusterEntityComplianceError, "attribute cluster_id was not found in #{scope_klass}" unless scope_klass.try(:column_names).try(:include?,'cluster_id')
|
13
|
-
scope_klass = scope_klass.includes(includes) if includes.present?
|
14
|
-
scope_klass = scope_klass.where(organization_id: organization)
|
15
9
|
|
16
|
-
|
17
|
-
|
10
|
+
#
|
11
|
+
# I like to wrap methods
|
12
|
+
#
|
13
|
+
def cluster_scope_filtered!(scope,cluster_id,user,organization,includes=[])
|
14
|
+
self.filter_clusterized_collection_with!(
|
15
|
+
organization,
|
16
|
+
cluster_id,
|
17
|
+
self.cluster_scope!(user,organization,scope,includes)
|
18
|
+
)
|
19
|
+
end
|
18
20
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
21
|
+
#
|
22
|
+
# In order to this works, active_record_collection argument
|
23
|
+
# should be passed through cluster_scope! method before.
|
24
|
+
#
|
25
|
+
def filter_clusterized_collection_with!(cluster_organization,cluster_id,active_record_collection)
|
26
|
+
if cluster_organization.is_in_cluster_mode?
|
27
|
+
if cluster_id.present?
|
28
|
+
cluster_array = [cluster_id]
|
29
|
+
# Based on force/use/show definition we don't really need this validation.
|
30
|
+
# A force cluster organization won't return an entity out of a cluster, but
|
31
|
+
# we don't know if the clusterized entities are fully definition-compliant.
|
32
|
+
cluster_array << nil if cluster_organization.optional_suborganization_mode?
|
33
|
+
active_record_collection = active_record_collection.where("cluster_entities.cluster_id": cluster_array)
|
25
34
|
end
|
35
|
+
# you may use a block only with clusterizable data
|
36
|
+
yield(active_record_collection) if block_given?
|
37
|
+
end
|
38
|
+
active_record_collection
|
39
|
+
end
|
26
40
|
|
41
|
+
#
|
42
|
+
#
|
43
|
+
#
|
44
|
+
def set_collection_before_group_by_entity!(cluster_organization,active_record_collection,model_class,entity_params)
|
45
|
+
entity_params_keys = [:entity_name,:entity_attribute,:entity_id,:entity_id_attribute,:unamed]
|
46
|
+
entity_params = entity_params.slice(*entity_params_keys).values
|
47
|
+
if model_class.try(:reflections).try(:keys).try(:include?,entity_params[0])
|
48
|
+
entity_params << "#{entity_params[0]}_id".to_sym
|
49
|
+
if entity_params[0] == 'cluster'
|
50
|
+
entity_params << :unclustered if cluster_organization.is_in_cluster_mode?
|
51
|
+
active_record_collection = Klastera.filter_clusterized_collection_with!(
|
52
|
+
cluster_organization,
|
53
|
+
entity_params[2],
|
54
|
+
active_record_collection
|
55
|
+
)
|
56
|
+
end
|
57
|
+
yield(
|
58
|
+
active_record_collection,
|
59
|
+
entity_params_keys.zip(entity_params).to_h)
|
27
60
|
end
|
61
|
+
end
|
62
|
+
|
63
|
+
##
|
64
|
+
# Returns a ::Cluster::ActiveRecord_Relation from a given scope
|
65
|
+
#
|
66
|
+
def clusters_from!(user,organization,scope,includes=[])
|
67
|
+
cluster_scope!(user,organization,scope,includes).related_clusters
|
68
|
+
end
|
28
69
|
|
70
|
+
##
|
71
|
+
# Returns a scope filtered by clusters or its
|
72
|
+
# organization if the cluster mode is not active.
|
73
|
+
#
|
74
|
+
def cluster_scope!(user,organization,scope,includes=[])
|
75
|
+
scope_klass = scope_class(scope).where(organization_id: organization)
|
76
|
+
session_clusters(user,organization) do |clusters|
|
77
|
+
if organization.is_in_cluster_mode?
|
78
|
+
scope_klass = scope_klass.includes(includes) if includes.present?
|
79
|
+
cluster_ids = clusters.map(&:id)
|
80
|
+
if organization.required_suborganization_mode?
|
81
|
+
scope_klass = scope_klass.joins(:cluster_entities).where( cluster_entities: { cluster_id: cluster_ids } )
|
82
|
+
else
|
83
|
+
scope_klass = scope_klass.joins("
|
84
|
+
LEFT OUTER JOIN cluster_entities
|
85
|
+
ON cluster_entities.cluster_id IN (#{cluster_ids.join(",")})
|
86
|
+
AND entity_id = #{scope.table_name}.id
|
87
|
+
AND entity_type = '#{scope}'
|
88
|
+
")
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
29
92
|
scope_klass
|
30
93
|
end
|
31
94
|
|
@@ -33,6 +96,7 @@ module Klastera
|
|
33
96
|
# TODO:
|
34
97
|
# Implement a validation to ensure that
|
35
98
|
# object is a ActiveRecord::Base class
|
99
|
+
# (or just try to guess how to retrieve the argument class)
|
36
100
|
#
|
37
101
|
##
|
38
102
|
def scope_class(object)
|
@@ -40,22 +104,17 @@ module Klastera
|
|
40
104
|
end
|
41
105
|
|
42
106
|
##
|
107
|
+
# Returns a cluster array if organization is using the cluster mode
|
43
108
|
#
|
109
|
+
# Use this only to get current_user/organization clusters
|
110
|
+
# understanding this wont be useful out of a cluster mode context.
|
44
111
|
#
|
45
112
|
##
|
46
113
|
def session_clusters(user,organization)
|
47
|
-
clusters = []
|
48
|
-
if
|
49
|
-
|
50
|
-
|
51
|
-
# TODO: 2: fix call to ::Cluster instead of Klastera::Cluster
|
52
|
-
clusters = ::ClusterUser.of(user,organization).map{|cu|::Cluster.find(cu.cluster_id)}
|
53
|
-
clusters << ::Cluster.new({nid: :without_cluster, name: I18n.t('klastera.without_cluster')}) if organization.optional_mode?
|
54
|
-
else
|
55
|
-
# TODO: remove "to_a" after ClusterUser.of result became a Cluster::ActiveRecord_Relation object
|
56
|
-
clusters = ::Cluster.of(organization).to_a
|
57
|
-
end
|
58
|
-
yield(clusters) if block_given?
|
114
|
+
clusters = organization.is_in_cluster_mode? ? ::ClusterUser.clusters_from(user,organization) : []
|
115
|
+
if block_given?
|
116
|
+
clusters = clusters.reject{|c|c.id.blank?}
|
117
|
+
yield(clusters)
|
59
118
|
end
|
60
119
|
clusters
|
61
120
|
end
|
@@ -68,7 +127,9 @@ module Klastera
|
|
68
127
|
helper_method :cluster_user
|
69
128
|
helper_method :cluster_organization
|
70
129
|
helper_method :cluster_clusters
|
71
|
-
|
130
|
+
helper_method :cluster_scope_filtered
|
131
|
+
helper_method :user_has_more_than_one_cluster
|
132
|
+
helper_method :clusters_from
|
72
133
|
end
|
73
134
|
if respond_to?(:hide_action)
|
74
135
|
hide_action :cluster_scope
|
@@ -81,18 +142,22 @@ module Klastera
|
|
81
142
|
hide_action :cluster_organization=
|
82
143
|
hide_action :cluster_clusters
|
83
144
|
hide_action :cluster_clusters=
|
84
|
-
|
85
|
-
|
145
|
+
hide_action :cluster_scope_filtered
|
146
|
+
hide_action :cluster_scope_filtered=
|
147
|
+
hide_action :user_has_more_than_one_cluster
|
148
|
+
hide_action :user_has_more_than_one_cluster=
|
149
|
+
hide_action :clusters_from
|
150
|
+
hide_action :clusters_from=
|
86
151
|
end
|
87
152
|
before_action :set_the_lonely_cluster, only: %i[ create update ]
|
88
153
|
end
|
89
154
|
|
90
155
|
def set_the_lonely_cluster
|
91
|
-
form_model = params[:controller].singularize
|
156
|
+
form_model = @form_record ? model_name_from_record_or_class(@form_record).param_key : params[:controller].singularize
|
92
157
|
parameters = params.require( form_model ) rescue nil
|
93
158
|
lonely_cluster = parameters.blank? ? false : parameters.permit( :lonely_cluster ).present?
|
94
159
|
if lonely_cluster
|
95
|
-
params[form_model][:cluster_id] =
|
160
|
+
params[form_model][:cluster_id] = cluster_clusters.first.try(:id)
|
96
161
|
end
|
97
162
|
end
|
98
163
|
|
@@ -112,9 +177,24 @@ module Klastera
|
|
112
177
|
Klastera.session_clusters(cluster_user,cluster_organization)
|
113
178
|
end
|
114
179
|
|
115
|
-
|
116
|
-
|
117
|
-
|
180
|
+
def cluster_scope_filtered(scope,cluster_id,includes=[])
|
181
|
+
Klastera.cluster_scope_filtered!(
|
182
|
+
scope,
|
183
|
+
cluster_id,
|
184
|
+
cluster_user,
|
185
|
+
cluster_organization,
|
186
|
+
includes
|
187
|
+
)
|
188
|
+
end
|
189
|
+
|
190
|
+
def user_has_more_than_one_cluster
|
191
|
+
@cluster_clusters ||= cluster_clusters
|
192
|
+
@cluster_clusters.size > 1
|
193
|
+
end
|
194
|
+
|
195
|
+
def clusters_from(scope,includes=[])
|
196
|
+
Klastera.clusters_from!(cluster_user,cluster_organization,scope,includes)
|
197
|
+
end
|
118
198
|
|
119
199
|
def set_cluster_filter
|
120
200
|
@filter = ::ClusterFilter.new(cluster_filter_params)
|