klastera 1.3 → 1.3.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 999d5c067d080b90f56c82a36cbeb286e08000bf09af922845bdd67df023d16c
4
- data.tar.gz: e4e105b33d55b228cc4d515e0167586b7b962218860d78593a29f6a71b436712
3
+ metadata.gz: a8ffbcdd772da4880e6fac3a2fa9165754a873673afb5f2108161d099e634622
4
+ data.tar.gz: 8541bb3c9c26b8e0084e42b91ef9262b443dbaf1250e4bd209a2fde9db6d92a9
5
5
  SHA512:
6
- metadata.gz: 6902637aaf11219cff0b3ed2f9dcdf1f86c74d2e6c43211d683c559177da39498220d5fca6b987418b936a89c6b08dde5d49a0014d0b86d1fe3c258612912f92
7
- data.tar.gz: 1ec8aad0c6793c426c01969bcdb9f04deed692b06499b0726ee047f13932fda3fe5046067432604947cf85e68662269569d61c482971b8855595a92dc87d1d29
6
+ metadata.gz: e43f85ef19e054e32274ad4c5c99db112333c76fa831383e72f3e0f7d7ad312d5b48519c33794a46ad3148dd4d50cca62117620e756b12933f0889a9891ad631
7
+ data.tar.gz: dc98ab10fc1588bec841af4b1e3a4caee5b976986e8023b7528c70190ee2b27fb2e230855773aaa1fcf1a28392380b9f63d186b9165e4f5704acf2631cd3d40f
@@ -8,4 +8,39 @@
8
8
  background: none;
9
9
  }
10
10
  }
11
- }
11
+ }
12
+
13
+ #cluster-remote-table {
14
+ .cluster-id { width: 70px; }
15
+ .cluster-order { width: 70px; }
16
+ .cluster-color { width: 70px; }
17
+ .odd .colorless { color: #F9F9F9 }
18
+ .even .colorless { color: #FFF }
19
+ tr:hover .colorless { color: #444; opacity: 0.2;}
20
+ }
21
+
22
+ #cluster-remote-form {
23
+ h4.blank-modal-title {
24
+ margin: 0;
25
+ line-height: 28px;
26
+ letter-spacing: 0.05rem;
27
+ font-size: 21px;
28
+ font-weight: 400;
29
+ color: #666;
30
+ }
31
+ }
32
+
33
+
34
+ ul.klastera-option-help {
35
+ padding-left: 20px;
36
+ list-style-type: disc;
37
+ }
38
+
39
+ ul.klastera-option-help li {
40
+ margin-bottom: 10px;
41
+ padding-bottom: 5px;
42
+ border-bottom: 1px solid #DDD;
43
+ }
44
+
45
+ ul.klastera-option-help li b { color: #8A8A8A; font-weight: 400; }
46
+ ul.klastera-option-help li b:first-child { color: #2E5F9B; font-weight: bold; }
@@ -33,13 +33,11 @@ module Klastera
33
33
 
34
34
  def destroy
35
35
  new_cluster_id = params.require(:transfer).permit(:new_cluster_id).values.first rescue nil
36
- @transfer = Transfer.new(
37
- current_cluster: @cluster,
38
- new_cluster_id: new_cluster_id
39
- )
36
+ @transfer = Transfer.new( current_cluster: @cluster, new_cluster_id: new_cluster_id )
40
37
  if @transfer.valid?
41
- @transfer.to!(::Cluster.related_entities.map{|re|re.constantize})
42
- @cluster.destroy
38
+ if @transfer.apply!
39
+ @cluster.destroy
40
+ end
43
41
  set_clusters
44
42
  end
45
43
  end
@@ -12,6 +12,7 @@ module Klastera::Concerns::Cluster
12
12
 
13
13
  belongs_to :organization, class_name: Klastera.organization_class
14
14
  has_many :cluster_users
15
+ has_many :cluster_entities, dependent: :destroy
15
16
 
16
17
  scope :of, -> (organization,except_ids=[]) {
17
18
  _scope = where(organization: organization)
@@ -42,7 +43,7 @@ module Klastera::Concerns::Cluster
42
43
  end
43
44
 
44
45
  def has_related_entities_using_it?
45
- ::Cluster.total_records_assign_to(self) > 0
46
+ self.cluster_entities.size > 0
46
47
  end
47
48
 
48
49
  def can_transfer_and_destroy?
@@ -60,24 +61,5 @@ module Klastera::Concerns::Cluster
60
61
  end
61
62
 
62
63
  module ClassMethods
63
- def related_entities(attr_needed: :class_name, macro: :has_many)
64
- ::Cluster.reflections.map do |association_name, reflection|
65
- reflection.send(attr_needed) if reflection.macro == macro
66
- end.compact
67
- end
68
-
69
- def total_records_assign_to(cluster_instance)
70
- related_entities(attr_needed: :name).inject(0) do |total, association_name|
71
- entity = cluster_instance.send(association_name)
72
- if entity.respond_to?(:cluster_id)
73
- total+=entity.where(cluster_id: cluster_instance.id).count
74
- end
75
- total
76
- end
77
- end
78
-
79
- def modes_as_strings
80
- ::Cluster::MODES.map{|m|m.to_s}
81
- end
82
64
  end
83
65
  end
@@ -4,7 +4,7 @@ module Klastera::Concerns::Organization
4
4
 
5
5
  has_many :clusters
6
6
 
7
- validates :use_cluster_as, inclusion: { in: ::Cluster.modes_as_strings , message: I18n.t('klastera.clusters.wrong_option') }, if: proc{ use_cluster_as.present? }
7
+ validates :use_cluster_as, inclusion: { in: ::Cluster::MODES.map{|m|m.to_s}, message: I18n.t('klastera.clusters.wrong_option') }, if: proc{ use_cluster_as.present? }
8
8
 
9
9
  # Return a symbol version of use_cluster_as value
10
10
  def cluster_mode
@@ -7,20 +7,14 @@ module Klastera::Concerns::Transfer
7
7
  include ActiveModel::Model
8
8
  include ActiveModel::Validations::Callbacks
9
9
 
10
- attr_accessor :current_cluster, :new_cluster_id, :entities_transfered
10
+ attr_accessor :current_cluster, :new_cluster_id
11
11
 
12
12
  validates :current_cluster, presence: true
13
13
  validates :new_cluster_id, presence: true, if: proc { self.required_transfer? }
14
14
 
15
15
  validate do
16
16
  new_cluster = ::Cluster.find(self.new_cluster_id.to_i) rescue nil
17
- #
18
- # In my time, to_a? didnt work
19
- # current_cluster.class returned:
20
- # Cluster(id: integer, name: string, nid: text, organization_id: integer, created_at: datetime, updated_at: datetime, color: string)
21
- #
22
- # If you see this, please fixe it. Thanks
23
- #
17
+
24
18
  if current_cluster.class.name != 'Cluster' || current_cluster.try(:is_the_last_record_in_required_suborganization_mode?)
25
19
  errors.add(:current_cluster, I18n.t('klastera.messages.current_cluster.cant_transfer'))
26
20
  elsif self.required_transfer? && new_cluster_id.present? && new_cluster.nil?
@@ -33,22 +27,19 @@ module Klastera::Concerns::Transfer
33
27
  end
34
28
  end
35
29
 
36
- ##
37
- #
38
- #
39
- def to!(related_entities)
40
- self.entities_transfered = 0
41
- related_entities.each do |entity|
42
- if entity.is_a?(Class) && entity.respond_to?(:cluster_id)
43
- self.entities_transfered += entity.where(
44
- cluster_id: self.current_cluster.id
45
- ).update_all(cluster_id: self.new_cluster_id)
46
- end
47
- end
48
- end
49
-
50
30
  def required_transfer?
51
31
  self.current_cluster.required_transfer? && self.current_cluster.has_related_entities_using_it?
52
32
  end
33
+
34
+ ##
35
+ # A returned boolean is expected. It should always be true even nothing is
36
+ # transfered, and it only will return false if creation fails.
37
+ #
38
+ def apply!
39
+ Klastera::ClusterEntity.create(current_cluster.cluster_entities.map{ |relation|
40
+ next if self.new_cluster_id.blank?
41
+ { cluster_id: self.new_cluster_id, entity_id: relation.entity_id, entity_type: relation.entity_type }
42
+ }.compact)
43
+ end
53
44
  end
54
45
  end
@@ -3,16 +3,16 @@
3
3
 
4
4
  <div class="<%=classes_for_remote_modal_body()%>">
5
5
  <div class="row">
6
- <div class="col-xs-12">
6
+ <div class="col-xs-6">
7
7
  <%= f.input :name, as: :string, label: t('klastera.cluster_name') %>
8
8
  </div>
9
- <div class="col-xs-12">
9
+ <div class="col-xs-6">
10
10
  <%= f.input :nid, as: :string, label: t('klastera.cluster_nid') %>
11
11
  </div>
12
- <div class="col-xs-12">
12
+ <div class="col-xs-6">
13
13
  <%= f.input :color, as: :string, label: t('klastera.cluster_color'), input_html: { class: 'color-picker'} %>
14
14
  </div>
15
- <div class="col-xs-12">
15
+ <div class="col-xs-6">
16
16
  <%= f.input :order, as: :string, label: t('klastera.cluster_order') %>
17
17
  </div>
18
18
  </div>
@@ -2,8 +2,8 @@
2
2
  <%= simple_form_for( @transfer, url: cluster_path(@cluster), method: :delete, remote: true, html: { autocomplete: :off, class: 'destroy-form slim-form-field' } ) do |f| %>
3
3
  <%=render 'layouts/remote_form/header', o: @cluster, title: title, fa: :qrcode %>
4
4
  <div class="<%=classes_for_remote_modal_body()%>">
5
- <h4 class="text-center">Esta acción es irreversible.<br/>¿Está seguro?</h4>
6
- <% if ::Cluster.total_records_assign_to(@cluster) > 0 %>
5
+ <h4 class="blank-modal-title text-center">Esta acción es irreversible<br/>¿Está seguro?</h4>
6
+ <% if @cluster.cluster_entities.size > 0 %>
7
7
  <br />
8
8
  <div class="row">
9
9
  <% if can_transfer_and_destroy %>
@@ -1,4 +1,4 @@
1
- <table class="table table-striped table-hover table-condensed table-bordered datatable">
1
+ <table class="table table-striped table-hover table-condensed table-bordered datatable table">
2
2
  <thead>
3
3
  <tr>
4
4
  <th class="text-center cluster-id"><%=t('klastera.cluster_id')%></th>
@@ -6,7 +6,7 @@
6
6
  <th class="text-center cluster-color"><%=t('klastera.cluster_color')%></th>
7
7
  <th class="text-center cluster-name"><%=t('klastera.cluster_name')%></th>
8
8
  <th class="text-center cluster-nid"><%=t('klastera.cluster_nid')%></th>
9
- <th class="cogs-actions four-icons"><span class="fa fa-cogs"></span></th>
9
+ <th class="cogs-actions two-icons"><span class="fa fa-cogs"></span></th>
10
10
  </tr>
11
11
  </thead>
12
12
  <tbody>
@@ -19,7 +19,7 @@
19
19
  </td>
20
20
  <td class="text-center cluster-name"><%= cluster.name %></td>
21
21
  <td class="text-center cluster-nid"><%= cluster.nid %></td>
22
- <td class="cogs-actions four-icons">
22
+ <td class="cogs-actions two-icons">
23
23
  <%= link_to edit_cluster_path(cluster), class:'btn btn-primary btn-xs', title: t('shared.actions.edit'), "data-toggle": "modal", "data-target": "#remote-modal-block" do %>
24
24
  <span class="fa fa-pencil-square-o"></span>
25
25
  <% end %>
@@ -30,12 +30,4 @@
30
30
  </tr>
31
31
  <% end %>
32
32
  </tbody>
33
- </table>
34
- <style type="text/css">
35
- .cluster-id { width: 70px; }
36
- .cluster-order { width: 70px; }
37
- .cluster-color { width: 70px; }
38
- .odd .colorless { color: #F9F9F9 }
39
- .even .colorless { color: #FFF }
40
- tr:hover .colorless { color: #F5F5F5 }
41
- </style>
33
+ </table>
@@ -18,4 +18,4 @@
18
18
 
19
19
  </div>
20
20
 
21
- <%= render 'layouts/remote_form/modal'%>
21
+ <%= render 'layouts/remote_form/modal', width: 'md' %>
@@ -19,20 +19,4 @@
19
19
  <script type="text/javascript">
20
20
  var popoverTemplate = '<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'
21
21
  $('.klastera-cluster-option').popover({ template: popoverTemplate, html: true, trigger: 'click', });
22
- </script>
23
-
24
- <style type="text/css">
25
- ul.klastera-option-help {
26
- padding-left: 20px;
27
- list-style-type: disc;
28
- }
29
-
30
- ul.klastera-option-help li {
31
- margin-bottom: 10px;
32
- padding-bottom: 5px;
33
- border-bottom: 1px solid #DDD;
34
- }
35
-
36
- ul.klastera-option-help li b { color: #8A8A8A; font-weight: 400; }
37
- ul.klastera-option-help li b:first-child { color: #2E5F9B; font-weight: bold; }
38
- </style>
22
+ </script>
@@ -8,7 +8,7 @@ module Klastera
8
8
  UNCLUSTERED_ENTITY = 'without_cluster'
9
9
  KLSTR_HELPERS = %i[
10
10
  cluster_user cluster_organization user_has_more_than_one_cluster cluster_scope cluster_of_my_own
11
- user_clusters_string_list set_collection_before_group_by_entity
11
+ user_clusters_string_list set_collection_before_group_by_entity __cluster_scope
12
12
  ]
13
13
 
14
14
  class << self
@@ -50,7 +50,7 @@ module Klastera
50
50
  if model_relations.include?(entity_params[0])
51
51
  entity_params << "#{entity_params[0]}_id".to_sym
52
52
  if entity_params[0] == 'cluster'
53
- entity_params << :unclustered if organization.is_in_cluster_mode?
53
+ entity_params << I18n.t("klastera.#{UNCLUSTERED_ENTITY}") if organization.is_in_cluster_mode?
54
54
  active_record_collection = Klastera.filter_clusterized!(
55
55
  active_record_collection,
56
56
  entity_params[2],
@@ -113,6 +113,44 @@ module Klastera
113
113
  scope_klass
114
114
  end
115
115
 
116
+
117
+ # Untested version for more optimized queries
118
+ #
119
+ def __cluster_scope!(scope,user,organization,cluster_id=nil,same_scope:false)
120
+ scope_klass = scope_class(scope)
121
+ if organization.is_in_cluster_mode?
122
+ scope_klass = scope_klass.includes(:organization)
123
+
124
+ if cluster_id.present?
125
+ cluster_ids = cluster_id.is_a?(Array) ? cluster_id : [cluster_id]
126
+ else
127
+ clusters = cluster_of!(user,organization)
128
+ cluster_ids = clusters.map(&:id).compact
129
+ end
130
+
131
+ scope_klass = scope_klass.select("DISTINCT ON (#{scope.table_name}.id) #{scope.table_name}.id, #{scope.table_name}.*, clusters.*")
132
+
133
+ if organization.required_suborganization_mode?
134
+ scope_klass = scope_klass.includes(cluster_entities: :cluster).where( cluster_entities: { cluster_id: cluster_ids } )
135
+ else
136
+ or_these_cluster_ids = cluster_ids.present? ? " OR cluster_entities.cluster_id IN (#{cluster_ids.join(",")})" : ""
137
+ scope_klass = scope_klass.joins("
138
+ LEFT OUTER JOIN cluster_entities
139
+ ON entity_id = #{scope.table_name}.id
140
+ AND entity_type = '#{scope}'
141
+ ").joins("
142
+ LEFT OUTER JOIN clusters
143
+ ON clusters.id = cluster_entities.cluster_id
144
+ ").where("cluster_entities.id IS NULL#{or_these_cluster_ids}")
145
+ end
146
+ # Provisional fix to avoid unresolved SQL clashes with the main application due to DISTINCT ON clause
147
+ unless same_scope
148
+ scope_klass = scope_class(scope).eager_load(:cluster_entities).where(id: scope_klass.map(&:id))
149
+ end
150
+ end
151
+ scope_klass.where(organization_id: organization)
152
+ end
153
+
116
154
  ##
117
155
  # TODO:
118
156
  # Implement a validation to ensure that
@@ -207,6 +245,10 @@ module Klastera
207
245
  Klastera.cluster_scope!(scope, cluster_user, cluster_organization, cluster_id)
208
246
  end
209
247
 
248
+ def __cluster_scope(scope,cluster_id=nil,same_scope:false)
249
+ Klastera.__cluster_scope!(scope, cluster_user, cluster_organization, cluster_id, same_scope: same_scope)
250
+ end
251
+
210
252
  def cluster_of_my_own
211
253
  Klastera.cluster_of!(cluster_user, cluster_organization)
212
254
  end
@@ -1,3 +1,3 @@
1
1
  module Klastera
2
- VERSION = "1.3"
3
- end
2
+ VERSION = "1.3.1"
3
+ 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.3'
4
+ version: 1.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gino Barahona
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-06-16 00:00:00.000000000 Z
11
+ date: 2020-06-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails