social_stream-base 0.14.2 → 0.14.3
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.
- data/app/assets/stylesheets/cheesecake.css.scss +43 -12
- data/app/controllers/contacts_controller.rb +1 -1
- data/app/models/activity.rb +4 -1
- data/app/models/actor.rb +2 -14
- data/app/models/relation/single.rb +2 -7
- data/app/models/relation.rb +2 -4
- data/app/models/tie.rb +2 -1
- data/app/views/activities/_new.html.erb +1 -1
- data/app/views/cheesecake/_cheesecake.html.erb +170 -105
- data/app/views/cheesecake/_index.html.erb +45 -47
- data/app/views/cheesecake/_sector_form.html.erb +1 -0
- data/app/views/toolbar/_home.html.erb +1 -1
- data/config/locales/en.yml +2 -0
- data/config/locales/es.yml +2 -0
- data/config/locales/rails.es.yml +192 -0
- data/db/migrate/20110912074426_add_reject_relation.rb +2 -2
- data/db/migrate/20120201185454_singleton_single_relations.rb +46 -0
- data/lib/social_stream/base/version.rb +1 -1
- data/lib/tasks/db/populate.rake +1 -1
- data/spec/controllers/posts_controller_spec.rb +2 -2
- data/spec/factories/activity.rb +1 -1
- data/spec/factories/post.rb +1 -1
- data/spec/factories/tie.rb +3 -3
- data/spec/models/activity_authorization_spec.rb +3 -3
- data/spec/support/db.rb +3 -1
- metadata +69 -66
@@ -13,6 +13,24 @@
|
|
13
13
|
float: left;
|
14
14
|
position: relative;
|
15
15
|
}
|
16
|
+
#sector_form {
|
17
|
+
float: left;
|
18
|
+
position: relative;
|
19
|
+
width: 0px;
|
20
|
+
padding: 0px;
|
21
|
+
margin: 0px;
|
22
|
+
overflow: hidden;
|
23
|
+
height: 450px;
|
24
|
+
}
|
25
|
+
#contacts_explorer {
|
26
|
+
float: right;
|
27
|
+
position: relative;
|
28
|
+
width: 300px;
|
29
|
+
padding: 0px;
|
30
|
+
margin: 0px;
|
31
|
+
overflow: hidden;
|
32
|
+
height: 450px;
|
33
|
+
}
|
16
34
|
#contacts_filter {
|
17
35
|
width: 290px;
|
18
36
|
height: 45px;
|
@@ -49,14 +67,14 @@
|
|
49
67
|
|
50
68
|
#contacts_grid {
|
51
69
|
width: 300px;
|
52
|
-
height:
|
70
|
+
height: 340px;
|
53
71
|
overflow: hidden;
|
54
72
|
position: relative;
|
55
73
|
float: left;
|
56
74
|
}
|
57
75
|
#contacts_grid_available {
|
58
76
|
width: 300px;
|
59
|
-
height:
|
77
|
+
height: 308px;
|
60
78
|
position: relative;
|
61
79
|
float: left;
|
62
80
|
overflow: auto;
|
@@ -71,13 +89,14 @@
|
|
71
89
|
text-align: center;
|
72
90
|
vertical-align: middle;
|
73
91
|
background-color: $fill-color;
|
92
|
+
z-index: 2000;
|
74
93
|
}
|
75
94
|
#contacts_save {
|
76
95
|
width: 130px;
|
77
96
|
padding-right: 5px;
|
78
97
|
height: 30px;
|
79
98
|
text-align: right;
|
80
|
-
float:
|
99
|
+
float: left;
|
81
100
|
margin-right: 20px;
|
82
101
|
}
|
83
102
|
#contacts_save_form {
|
@@ -96,7 +115,7 @@
|
|
96
115
|
#contacts_changes_button {
|
97
116
|
width: 130px;
|
98
117
|
height: 25px;
|
99
|
-
float:
|
118
|
+
float: left;
|
100
119
|
margin-top: 10px;
|
101
120
|
cursor: pointer;
|
102
121
|
}
|
@@ -163,7 +182,7 @@
|
|
163
182
|
width: 48px;
|
164
183
|
height: 48px;
|
165
184
|
float: left;
|
166
|
-
|
185
|
+
padding: 4px;
|
167
186
|
opacity: 0.8;
|
168
187
|
}
|
169
188
|
#contacts_grid .actor img {
|
@@ -172,7 +191,9 @@
|
|
172
191
|
}
|
173
192
|
#contacts_grid .actor.focused {
|
174
193
|
opacity: 1;
|
175
|
-
|
194
|
+
padding: 3px;
|
195
|
+
background: $secondary-color;
|
196
|
+
border: 1px solid $main-color;
|
176
197
|
}
|
177
198
|
#contacts_grid .actor.focused img {
|
178
199
|
|
@@ -183,14 +204,18 @@
|
|
183
204
|
width: 24px;
|
184
205
|
height: 24px;
|
185
206
|
float: left;
|
186
|
-
|
207
|
+
padding: 2px 2px 0px 2px;
|
208
|
+
background-color: $fill-color;
|
187
209
|
}
|
188
210
|
#contacts_grid_selected .actor img {
|
189
211
|
width: 24px;
|
190
212
|
height: 24px;
|
191
213
|
}
|
192
|
-
#contacts_grid_selected
|
193
|
-
|
214
|
+
#contacts_grid_selected .actor.focused {
|
215
|
+
opacity: 1;
|
216
|
+
background: $header-notification-color;
|
217
|
+
padding: 2px 2px 2px 2px;
|
218
|
+
border: 0px;
|
194
219
|
}
|
195
220
|
#contacts_grid_selected .actor.focused img {
|
196
221
|
|
@@ -198,10 +223,16 @@
|
|
198
223
|
#contacts_grid_selected {
|
199
224
|
width: 280px;
|
200
225
|
min-height: 28px;
|
201
|
-
background-color: $
|
226
|
+
background-color: $secondary-color;
|
202
227
|
border: 1px solid $main-color;
|
203
|
-
|
204
|
-
|
228
|
+
padding: 0px;
|
229
|
+
margin-bottom: 2px;
|
230
|
+
}
|
231
|
+
#contacts_grid_selected_hint {
|
232
|
+
padding-top: 5px;
|
233
|
+
margin: auto;
|
234
|
+
height: 11px;
|
235
|
+
text-align: center;
|
205
236
|
}
|
206
237
|
.cheesecake_actor_tipsy.tipsy {
|
207
238
|
padding-top: 2px;
|
data/app/models/activity.rb
CHANGED
@@ -228,7 +228,10 @@ class Activity < ActiveRecord::Base
|
|
228
228
|
|
229
229
|
rels = Relation.normalize(relation_ids)
|
230
230
|
|
231
|
-
own_rels
|
231
|
+
own_rels = rels.select{ |r| r.actor_id == channel.author_id }
|
232
|
+
# Consider Relation::Single as own_relations
|
233
|
+
own_rels += rels.select{ |r| r.is_a?(Relation::Single) }
|
234
|
+
|
232
235
|
foreign_rels = rels - own_rels
|
233
236
|
|
234
237
|
# Only posting to own relations or allowed to post to foreign relations
|
data/app/models/actor.rb
CHANGED
@@ -205,16 +205,6 @@ class Actor < ActiveRecord::Base
|
|
205
205
|
relations.joins(:relation_permissions => :permission).where('permissions.action' => 'notify')
|
206
206
|
end
|
207
207
|
|
208
|
-
# The {Relation::Public} for this {Actor}
|
209
|
-
def relation_public
|
210
|
-
Relation::Public.of(self)
|
211
|
-
end
|
212
|
-
|
213
|
-
# The {Relation::Reject} for this {Actor}
|
214
|
-
def relation_reject
|
215
|
-
Relation::Reject.of(self)
|
216
|
-
end
|
217
|
-
|
218
208
|
# All the {Actor Actors} this one has ties with:
|
219
209
|
#
|
220
210
|
# actor.contact_actors #=> array of actors that sent and receive ties from actor
|
@@ -381,7 +371,7 @@ class Actor < ActiveRecord::Base
|
|
381
371
|
#
|
382
372
|
def activity_relations(subject, options = {})
|
383
373
|
if Actor.normalize(subject) == self
|
384
|
-
return relation_customs + Array.wrap(
|
374
|
+
return relation_customs + Array.wrap(Relation::Public.instance)
|
385
375
|
else
|
386
376
|
Array.new
|
387
377
|
end
|
@@ -507,7 +497,7 @@ class Actor < ActiveRecord::Base
|
|
507
497
|
id
|
508
498
|
a = Activity.new :verb => "like",
|
509
499
|
:channel => channel,
|
510
|
-
:relation_ids => Array(
|
500
|
+
:relation_ids => Array(Relation::Public.instance.id)
|
511
501
|
|
512
502
|
a.activity_objects << activity_object
|
513
503
|
|
@@ -534,8 +524,6 @@ class Actor < ActiveRecord::Base
|
|
534
524
|
# After create callback
|
535
525
|
def create_initial_relations
|
536
526
|
Relation::Custom.defaults_for(self)
|
537
|
-
Relation::Public.default_for(self)
|
538
|
-
Relation::Reject.default_for(self)
|
539
527
|
end
|
540
528
|
|
541
529
|
# After create callback
|
@@ -5,13 +5,8 @@
|
|
5
5
|
#
|
6
6
|
class Relation::Single < Relation
|
7
7
|
class << self
|
8
|
-
def
|
9
|
-
create!
|
10
|
-
end
|
11
|
-
|
12
|
-
# The {Relation::Public} belonging to actor
|
13
|
-
def of(actor)
|
14
|
-
actor(actor).first
|
8
|
+
def instance
|
9
|
+
first || create!
|
15
10
|
end
|
16
11
|
end
|
17
12
|
|
data/app/models/relation.rb
CHANGED
@@ -55,8 +55,6 @@ class Relation < ActiveRecord::Base
|
|
55
55
|
has_many :audiences, :dependent => :destroy
|
56
56
|
has_many :activities, :through => :audiences
|
57
57
|
|
58
|
-
validates_presence_of :actor_id
|
59
|
-
|
60
58
|
scope :actor, lambda { |a|
|
61
59
|
where(:actor_id => Actor.normalize_id(a))
|
62
60
|
}
|
@@ -125,12 +123,12 @@ class Relation < ActiveRecord::Base
|
|
125
123
|
|
126
124
|
conds =
|
127
125
|
Permission.arel_table[:action].eq(action).and(Permission.arel_table[:object].eq(object))
|
128
|
-
|
129
|
-
# Relation::Public permissions cannot be customized yet
|
126
|
+
# Relation::Public permissions cannot be customized and should not depend on the subject
|
130
127
|
if action == 'read' && object == 'activity' && (options[:public].nil? || options[:public])
|
131
128
|
conds = conds.or(Relation.arel_table[:type].eq('Relation::Public'))
|
132
129
|
end
|
133
130
|
|
131
|
+
|
134
132
|
# Add in condition
|
135
133
|
if ! options[:in].nil?
|
136
134
|
conds = conds.and(Relation.arel_table[:id].in(Relation.normalize_id(Array(options[:in]))))
|
data/app/models/tie.rb
CHANGED
@@ -141,7 +141,8 @@ class Tie < ActiveRecord::Base
|
|
141
141
|
|
142
142
|
def relation_belongs_to_sender
|
143
143
|
errors.add(:relation, "must belong to sender") unless
|
144
|
-
|
144
|
+
relation.is_a?(Relation::Single) ||
|
145
|
+
contact.sender_id == relation.actor_id
|
145
146
|
end
|
146
147
|
end
|
147
148
|
|
@@ -25,7 +25,7 @@
|
|
25
25
|
<div id="securities">
|
26
26
|
<% if current_subject == receiver %>
|
27
27
|
<%= javascript_tag do %>
|
28
|
-
var relation_public = <%=
|
28
|
+
var relation_public = <%= Relation::Public.instance.id %>;
|
29
29
|
var public_selected = false;
|
30
30
|
var relation_options = <%= escape_javascript(current_subject.activity_relations(receiver).sort.map{ |r| r.id }.to_json) %>;
|
31
31
|
var relation_public_pos = 0;
|
@@ -5,121 +5,186 @@ $(function(){
|
|
5
5
|
width: 440,
|
6
6
|
height: 440
|
7
7
|
},
|
8
|
-
|
8
|
+
grid: {
|
9
9
|
id: "contacts_grid",
|
10
|
-
divIdPrefix: "actor_"
|
10
|
+
divIdPrefix: "actor_",
|
11
|
+
maxOpacity: 0.8
|
11
12
|
},
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
var changes = cheesecake.getChanges();
|
31
|
-
if((changes.actors)&&(changes.actors.length==0)&&(changes.sectors)&&(changes.sectors.length==0)&&(changes.subsectors)&&(changes.subsectors.length==0)){
|
32
|
-
$("#contacts_changes_button").hide();
|
33
|
-
$("#contacts_save").hide();
|
34
|
-
}else{
|
35
|
-
$("#contacts_changes_button").show();
|
36
|
-
$("#contacts_save").show();
|
37
|
-
var total = 0;
|
38
|
-
if(changes.actors)
|
39
|
-
total += changes.actors.length;
|
40
|
-
if(changes.sectors)
|
41
|
-
total += changes.sectors.length;
|
42
|
-
if(changes.subsectors)
|
43
|
-
total += changes.subsectors.length;
|
44
|
-
$("#contacts_changes_button_total").html(total);
|
13
|
+
colors : {
|
14
|
+
normalSector : {
|
15
|
+
background : "#DEEFF8",
|
16
|
+
border : "#1F4A75",
|
17
|
+
font : "#1F4A75",
|
18
|
+
click : "#BDC7D8",
|
19
|
+
mouseover : "#D4E4EA",
|
20
|
+
mouseup : "#DEEFF8",
|
21
|
+
mouseout : "#DEEFF8"
|
22
|
+
},
|
23
|
+
extraSector : {
|
24
|
+
background : "#879EB5",
|
25
|
+
border : "#1F4A75",
|
26
|
+
font : "#1F4A75",
|
27
|
+
click : "#97AEC5",
|
28
|
+
mouseover : "#97AEC5",
|
29
|
+
mouseup : "#879EB5",
|
30
|
+
mouseout : "#879EB5"
|
45
31
|
}
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
32
|
+
},
|
33
|
+
rMax : 200,
|
34
|
+
center: {x : 220, y : 220}
|
35
|
+
};
|
36
|
+
cheesecakeData.sectors = <%= raw(current_subject.cheesecake_json) %>.sectors;
|
37
|
+
var cheese = new socialCheesecake.Cheesecake(cheesecakeData);
|
38
|
+
cheese.syncSectorFocusCallbacks = false;
|
39
|
+
cheese.onSectorFocusBegin = function(cheesecake,callback){
|
40
|
+
if(cheese.highlightedSector.auxiliar){
|
41
|
+
$("#contacts_explorer").animate({width: 0},500,function(){
|
42
|
+
$("#contacts_explorer").hide();
|
43
|
+
});
|
44
|
+
setTimeout(function(){
|
45
|
+
$("#sector_form").show();
|
46
|
+
$("#sector_form").animate({width: 300},500);
|
47
|
+
},100);
|
48
|
+
}else{
|
49
|
+
$("#contacts_grid_available").fadeOut("fast", callback);
|
50
|
+
}
|
51
|
+
};
|
52
|
+
cheese.onSectorFocusEnd = function(cheesecake){
|
53
|
+
if(cheese.highlightedSector.auxiliar){
|
54
|
+
|
55
|
+
}else{
|
56
|
+
$("#contacts_grid_available").fadeIn("fast");
|
57
|
+
}
|
58
|
+
};
|
59
|
+
cheese.onSectorUnfocusBegin = function(cheesecake,callback){
|
60
|
+
if(cheese.highlightedSector.auxiliar){
|
61
|
+
|
62
|
+
}else{
|
63
|
+
$("#contacts_grid_available").fadeOut("fast", callback);
|
64
|
+
}
|
65
|
+
};
|
66
|
+
cheese.onSectorUnfocusEnd = function(cheesecake){
|
67
|
+
if(cheese.highlightedSector.auxiliar){
|
68
|
+
$("#sector_form").animate({width: 0},500,function(){
|
69
|
+
$("#sector_form").hide();
|
70
|
+
});
|
71
|
+
setTimeout(function(){
|
72
|
+
$("#contacts_explorer").show();
|
73
|
+
$("#contacts_explorer").animate({width: 300},500);
|
74
|
+
},100);
|
75
|
+
}else{
|
76
|
+
$("#contacts_grid_available").fadeIn("fast");
|
77
|
+
}
|
78
|
+
};
|
79
|
+
$("#contacts_filter_input").keyup(function(){
|
80
|
+
cheese.searchEngine.filter($("#contacts_filter_input").val());
|
81
|
+
//TODO: Make users unfiltered visible again
|
82
|
+
});
|
83
|
+
cheese.onChange = function(cheesecake){
|
84
|
+
var initial = cheesecake.getInitialState();
|
85
|
+
var changes = cheesecake.getChanges();
|
86
|
+
if((changes.actors)&&(changes.actors.length==0)&&(changes.sectors)&&(changes.sectors.length==0)&&(changes.subsectors)&&(changes.subsectors.length==0)){
|
87
|
+
$("#contacts_changes_button").hide();
|
88
|
+
$("#contacts_save").hide();
|
89
|
+
}else{
|
90
|
+
$("#contacts_changes_button").show();
|
91
|
+
$("#contacts_save").show();
|
92
|
+
var total = 0;
|
93
|
+
if(changes.actors)
|
94
|
+
total += changes.actors.length;
|
95
|
+
if(changes.sectors)
|
96
|
+
total += changes.sectors.length;
|
97
|
+
if(changes.subsectors)
|
98
|
+
total += changes.subsectors.length;
|
99
|
+
$("#contacts_changes_button_total").html(total);
|
100
|
+
}
|
101
|
+
var changes_html = "";
|
102
|
+
var actors = changes.actors;
|
103
|
+
$("#contacts_save_changes").val(JSON.stringify(changes));
|
104
|
+
for(var i in actors){
|
105
|
+
actor = actors[i];
|
106
|
+
if(actor.justAdded){
|
107
|
+
var new_subsectors = actor.subsectors;
|
108
|
+
var new_subsectors_string = "";
|
109
|
+
for(var i in new_subsectors){
|
110
|
+
if(i > 0) new_subsectors_string += ", ";
|
111
|
+
new_subsectors_string += cheesecake.getSubsectorById(new_subsectors[i]).label;
|
112
|
+
}
|
113
|
+
changes_html += "<div class=\"change_added\">" + actor.name + " has been removed from " + old_subsectors_string + "</div>";
|
114
|
+
}else if(actor.subsectors.length==0){
|
115
|
+
var old_subsectors = [];
|
116
|
+
var old_subsectors_string = "";
|
117
|
+
for(var i in initial.actors){
|
118
|
+
if(actor.id==initial.actors[i].id){
|
119
|
+
old_subsectors = initial.actors[i].subsectors;
|
120
|
+
break;
|
71
121
|
}
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
122
|
+
}
|
123
|
+
for(var i in old_subsectors){
|
124
|
+
if(i > 0) old_subsectors_string += ", ";
|
125
|
+
old_subsectors_string += cheesecake.getSubsectorById(old_subsectors[i]).label;
|
126
|
+
}
|
127
|
+
changes_html += "<div class=\"change_deleted\">" + actor.name + " has been removed from " + old_subsectors_string + "</div>";
|
128
|
+
}else{
|
129
|
+
var old_subsectors = [];
|
130
|
+
var new_subsectors = actor.subsectors;
|
131
|
+
var left_subsectors = "";
|
132
|
+
var joined_subsectors = "";
|
133
|
+
for(var i in initial.actors){
|
134
|
+
if(actor.id==initial.actors[i].id){
|
135
|
+
old_subsectors = initial.actors[i].subsectors;
|
136
|
+
break;
|
83
137
|
}
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
left_subsectors += cheesecake.getSubsectorById(old_subsectors[i]).label;
|
138
|
+
}
|
139
|
+
for(var i in old_subsectors){
|
140
|
+
if(new_subsectors.indexOf(old_subsectors[i])==-1){
|
141
|
+
if(left_subsectors.length!=0){
|
142
|
+
left_subsectors += ", ";
|
90
143
|
}
|
144
|
+
left_subsectors += cheesecake.getSubsectorById(old_subsectors[i]).label;
|
91
145
|
}
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
joined_subsectors += cheesecake.getSubsectorById(new_subsectors[i]).label;
|
146
|
+
}
|
147
|
+
for(var i in new_subsectors){
|
148
|
+
if(old_subsectors.indexOf(new_subsectors[i])==-1){
|
149
|
+
if(joined_subsectors.length!=0){
|
150
|
+
joined_subsectors += ", ";
|
98
151
|
}
|
152
|
+
joined_subsectors += cheesecake.getSubsectorById(new_subsectors[i]).label;
|
99
153
|
}
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
154
|
+
}
|
155
|
+
if((joined_subsectors.length!=0)&&(left_subsectors.length!=0)){
|
156
|
+
changes_html += "<div class=\"change_modified\">" + actor.name + " has been removed from " + left_subsectors + " and added to " + joined_subsectors + "</div>";
|
157
|
+
}else if(joined_subsectors.length!=0){
|
158
|
+
changes_html += "<div class=\"change_added\">" + actor.name + " has been added to " + joined_subsectors + "</div>";
|
159
|
+
}else{
|
160
|
+
changes_html += "<div class=\"change_deleted\">" + actor.name + " has been removed from " + left_subsectors + "</div>";
|
107
161
|
}
|
108
162
|
}
|
109
|
-
$("#contacts_changes_details").html(changes_html);
|
110
163
|
}
|
111
|
-
$(
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
164
|
+
$("#contacts_changes_details").html(changes_html);
|
165
|
+
}
|
166
|
+
$('#contacts_changes_button').tipsy({
|
167
|
+
delayIn: 0,
|
168
|
+
delayOut: 0,
|
169
|
+
gravity: 'se',
|
170
|
+
opacity: 1,
|
171
|
+
trigger: 'manual',
|
172
|
+
className: 'contacts_changes_tipsy_menu',
|
173
|
+
html: true,
|
174
|
+
hoverable: true,
|
175
|
+
title: function(){
|
176
|
+
return $('#contacts_changes').html();
|
177
|
+
}
|
178
|
+
});
|
179
|
+
$("#contacts_save_changes").val(JSON.stringify(cheese.getChanges()));
|
180
|
+
$("#contacts_save_form").off("submit.disable");
|
181
|
+
$("#contacts_save_form").on("submit.disable",function(){
|
182
|
+
|
183
|
+
if($(".contacts_changes_tipsy_menu").length != 0){
|
184
|
+
$("#contacts_changes_button").tipsy("hide");
|
185
|
+
}
|
186
|
+
$("#contacts_grid_saving").show();
|
187
|
+
cheese.disable();
|
188
|
+
$("#contacts_save_button").val("<%= t('cheesecake.changes.saving') %>").attr("disabled","true");
|
189
|
+
});
|
125
190
|
});
|