klastera 1.3 → 1.3.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/app/assets/stylesheets/klastera/clusters.css.scss +36 -1
- data/app/controllers/klastera/clusters_controller.rb +4 -6
- data/app/models/klastera/concerns/cluster.rb +2 -20
- data/app/models/klastera/concerns/organization.rb +1 -1
- data/app/models/klastera/concerns/transfer.rb +13 -22
- data/app/views/klastera/clusters/_form.html.erb +4 -4
- data/app/views/klastera/clusters/_form_transfer.html.erb +2 -2
- data/app/views/klastera/clusters/_table.html.erb +4 -12
- data/app/views/klastera/clusters/index.html.erb +1 -1
- data/app/views/layouts/klastera/_options.html.erb +1 -17
- data/lib/klastera.rb +44 -2
- data/lib/klastera/version.rb +2 -2
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a8ffbcdd772da4880e6fac3a2fa9165754a873673afb5f2108161d099e634622
|
4
|
+
data.tar.gz: 8541bb3c9c26b8e0084e42b91ef9262b443dbaf1250e4bd209a2fde9db6d92a9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
42
|
-
|
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
|
-
|
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.
|
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
|
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-
|
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-
|
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
|
+
<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-
|
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
|
6
|
-
<% if
|
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
|
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
|
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>
|
@@ -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>
|
data/lib/klastera.rb
CHANGED
@@ -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 <<
|
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
|
data/lib/klastera/version.rb
CHANGED
@@ -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:
|
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-
|
11
|
+
date: 2020-06-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|